UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

116 lines (114 loc) 5.19 kB
import database_default from "../../index.js"; import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError } from "@directus/errors"; //#region src/database/errors/dialects/mssql.ts var MSSQLErrorCodes = /* @__PURE__ */ function(MSSQLErrorCodes$1) { MSSQLErrorCodes$1[MSSQLErrorCodes$1["FOREIGN_KEY_VIOLATION"] = 547] = "FOREIGN_KEY_VIOLATION"; MSSQLErrorCodes$1[MSSQLErrorCodes$1["NOT_NULL_VIOLATION"] = 515] = "NOT_NULL_VIOLATION"; MSSQLErrorCodes$1[MSSQLErrorCodes$1["NUMERIC_VALUE_OUT_OF_RANGE"] = 220] = "NUMERIC_VALUE_OUT_OF_RANGE"; MSSQLErrorCodes$1[MSSQLErrorCodes$1["UNIQUE_VIOLATION_INDEX"] = 2601] = "UNIQUE_VIOLATION_INDEX"; MSSQLErrorCodes$1[MSSQLErrorCodes$1["UNIQUE_VIOLATION_CONSTRAINT"] = 2627] = "UNIQUE_VIOLATION_CONSTRAINT"; MSSQLErrorCodes$1[MSSQLErrorCodes$1["VALUE_LIMIT_VIOLATION"] = 2628] = "VALUE_LIMIT_VIOLATION"; return MSSQLErrorCodes$1; }(MSSQLErrorCodes || {}); async function extractError(error, data) { switch (error.number) { case MSSQLErrorCodes.UNIQUE_VIOLATION_CONSTRAINT: case MSSQLErrorCodes.UNIQUE_VIOLATION_INDEX: return await uniqueViolation(error); case MSSQLErrorCodes.NUMERIC_VALUE_OUT_OF_RANGE: return numericValueOutOfRange(); case MSSQLErrorCodes.VALUE_LIMIT_VIOLATION: return valueLimitViolation(); case MSSQLErrorCodes.NOT_NULL_VIOLATION: return notNullViolation(); case MSSQLErrorCodes.FOREIGN_KEY_VIOLATION: return foreignKeyViolation(); } return error; async function uniqueViolation(error$1) { /** * NOTE: * SQL Server doesn't return the name of the offending column when a unique error is thrown: * * Constraint: * insert into [articles] ([unique]) values (@p0) * - Violation of UNIQUE KEY constraint 'unique_contraint_name'. Cannot insert duplicate key in object 'dbo.article'. * The duplicate key value is (rijk). * * Index: * insert into [articles] ([unique]) values (@p0) * - Cannot insert duplicate key row in object 'dbo.articles' with unique index 'unique_index_name'. * The duplicate key value is (rijk). * * While it's not ideal, the best next thing we can do is extract the column name from * information_schema when this happens */ const betweenQuotes = /'([^']+)'/g; const betweenParens = /\(([^)]+)\)/g; const quoteMatches = error$1.message.match(betweenQuotes); const parenMatches = error$1.message.match(betweenParens); if (!quoteMatches || !parenMatches) return error$1; const [keyNameMatchIndex, collectionNameMatchIndex] = error$1.number === MSSQLErrorCodes.UNIQUE_VIOLATION_INDEX ? [1, 0] : [0, 1]; const keyName = quoteMatches[keyNameMatchIndex].slice(1, -1); let collection = quoteMatches[collectionNameMatchIndex].slice(1, -1); let field = null; if (keyName) { const database = database_default(); const constraintUsage = await database.select("sys.columns.name as field", database.raw("OBJECT_NAME(??) as collection", ["sys.columns.object_id"])).from("sys.indexes").innerJoin("sys.index_columns", (join) => { join.on("sys.indexes.object_id", "=", "sys.index_columns.object_id").andOn("sys.indexes.index_id", "=", "sys.index_columns.index_id"); }).innerJoin("sys.columns", (join) => { join.on("sys.index_columns.object_id", "=", "sys.columns.object_id").andOn("sys.index_columns.column_id", "=", "sys.columns.column_id"); }).where("sys.indexes.name", "=", keyName).first(); collection = constraintUsage?.collection; field = constraintUsage?.field; } return new RecordNotUniqueError({ collection, field, value: field ? data[field] : null }); } function numericValueOutOfRange() { const bracketMatches = error.message.match(/\[([^\]]+)\]/g); if (!bracketMatches) return error; return new ValueOutOfRangeError({ collection: bracketMatches[0].slice(1, -1), field: null, value: null }); } function valueLimitViolation() { const betweenBrackets = /\[([^\]]+)\]/g; const betweenQuotes = /'([^']+)'/g; const bracketMatches = error.message.match(betweenBrackets); const quoteMatches = error.message.match(betweenQuotes); if (!bracketMatches || !quoteMatches) return error; const collection = bracketMatches[0].slice(1, -1); const field = quoteMatches[1].slice(1, -1); return new ValueTooLongError({ collection, field, value: field ? data[field] : null }); } function notNullViolation() { const betweenBrackets = /\[([^\]]+)\]/g; const betweenQuotes = /'([^']+)'/g; const bracketMatches = error.message.match(betweenBrackets); const quoteMatches = error.message.match(betweenQuotes); if (!bracketMatches || !quoteMatches) return error; const collection = bracketMatches[0].slice(1, -1); const field = quoteMatches[0].slice(1, -1); if (error.message.includes("Cannot insert the value NULL into column")) return new ContainsNullValuesError({ collection, field }); return new NotNullViolationError({ collection, field }); } function foreignKeyViolation() { return new InvalidForeignKeyError({ value: null, constraint: /constraint ["']([^"']+)["']/i.exec(error.message)?.[1] ?? null }); } } //#endregion export { extractError };