Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
- `insertGraph()` and `upsertGraph()` stay under the number of values that a query can bind on SQL Server, PostgreSQL and SQLite when they insert, patch and remove many rows, and fetch many roots or related models
- `upsertGraphAndFetch()` loads the relations of a `withGraphFetched()` on its query with their modifiers, named modifiers, aliases and options into the fetched models, like `insertGraphAndFetch()`, instead of ignoring the modifiers and aliases [#839](https://github.com/Vincit/objection.js/issues/839)
- The error of `upsertGraph()` queries with other query builder calls names `$query()`, which adds such a call too [#1168](https://github.com/Vincit/objection.js/issues/1168)
- Errors of knex's `better-sqlite3` client are wrapped like those of `sqlite3`, e.g. a unique violation as a `UniqueViolationError` with its table and columns, where they reached the app as the driver's `SqliteError`, also in 3.x
- Errors of knex's `better-sqlite3` client are wrapped like those of `sqlite3`, e.g. a unique violation, also of a primary key, as a `UniqueViolationError` with its table and columns, where they reached the app as the driver's `SqliteError`, also in 3.x

### Types

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
// puts the SQL with its values in front, so the last match is SQLite's own.
export function getConstraintMessage(err, kind) {
const text = `${kind} constraint failed`;
// A duplicate primary key is a unique violation, with its own code:
const codes = kind === 'UNIQUE' ? ['UNIQUE', 'PRIMARYKEY'] : [kind.replace(' ', '')];
const isKind =
err.code === `SQLITE_CONSTRAINT_${kind.replace(' ', '')}` ||
codes.some((code) => err.code === `SQLITE_CONSTRAINT_${code}`) ||
(err.code === 'SQLITE_CONSTRAINT' &&
/.*SQLITE_CONSTRAINT: (.*)$/s.exec(err.message)?.[1].startsWith(text));

Expand Down
12 changes: 12 additions & 0 deletions tests/unit/dbErrors/sqlite.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ describe('SQLite database errors', () => {
expect(err).toMatchObject({ table: 't', columns: ['a', 'b'], client: 'sqlite' });
});

it('should wrap primary key violations as unique violations', () => {
const err = wrapError(
createError(
'SQLITE_CONSTRAINT',
'SQLITE_CONSTRAINT_PRIMARYKEY',
'UNIQUE constraint failed: p.id',
),
);
expect(err).toBeInstanceOf(UniqueViolationError);
expect(err).toMatchObject({ table: 'p', columns: ['id'] });
});

it('should wrap not null violations', () => {
const err = wrapError(
createError(
Expand Down
Loading