2
ContainsNullValuesError,
3
InvalidForeignKeyError,
6
} from '@directus/errors';
7
import type { SQLiteError } from './types.js';
10
// - Sqlite doesn't have varchar with length support, so no ValueTooLongError
11
// - Sqlite doesn't have a max range for numbers, so no ValueOutOfRangeError
13
export function extractError(error: SQLiteError): SQLiteError | Error {
14
if (error.message.includes('SQLITE_CONSTRAINT: NOT NULL')) {
15
return notNullConstraint(error);
18
if (error.message.includes('SQLITE_CONSTRAINT: UNIQUE')) {
19
const errorParts = error.message.split(' ');
20
const [table, column] = errorParts[errorParts.length - 1]!.split('.');
22
if (!table || !column) return error;
24
return new RecordNotUniqueError({
30
if (error.message.includes('SQLITE_CONSTRAINT: FOREIGN KEY')) {
33
* SQLite doesn't return any useful information in it's foreign key constraint failed error, so
34
* we can't extract the table/column/value accurately
36
return new InvalidForeignKeyError({ collection: null, field: null });
42
function notNullConstraint(error: SQLiteError) {
43
const errorParts = error.message.split(' ');
44
const [table, column] = errorParts[errorParts.length - 1]!.split('.');
46
if (table && column) {
47
// Now this gets a little finicky... SQLite doesn't have any native ALTER, so Knex implements
48
// it by creating a new table, and then copying the data over. That also means we'll never get
49
// a ContainsNullValues constraint error, as there is no ALTER. HOWEVER, we can hack around
50
// that by checking for the collection name, as Knex's alter default template name will always
51
// start with _knex_temp. The best we can do in this case is check for that, and use it to
52
// decide between NotNullViolation and ContainsNullValues
53
if (table.startsWith('_knex_temp_alter')) {
54
return new ContainsNullValuesError({ collection: table, field: column });
57
return new NotNullViolationError({