diff --git a/lib/postgres.dart b/lib/postgres.dart index 99b1602..1a5a7fa 100644 --- a/lib/postgres.dart +++ b/lib/postgres.dart @@ -15,7 +15,13 @@ import 'src/v3/protocol.dart'; import 'src/v3/query_description.dart'; export 'src/exceptions.dart' - show BadCertificateException, Severity, PgException, ServerException; + show + BadCertificateException, + Severity, + PgException, + ServerException, + DuplicateKeyException, + ForeignKeyViolationException; export 'src/pool/pool_api.dart'; export 'src/replication.dart'; export 'src/types.dart'; @@ -225,6 +231,7 @@ abstract class Connection implements Session, SessionExecutor { } ConnectionInfo get info; + Channels get channels; } diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart index 4413362..c1aef9f 100644 --- a/lib/src/exceptions.dart +++ b/lib/src/exceptions.dart @@ -191,13 +191,15 @@ ServerException buildExceptionFromErrorFields(List errorFields) { } PgException transformServerException(ServerException ex) { - if (ex.code == '57014') { - return _PgQueryCancelledException( - ['${ex.code}:', ex.message, ex.trace].whereType().join(' '), - severity: ex.severity, - ); - } - return ex; + return switch (ex.code) { + '23505' => DuplicateKeyException(ex.message, severity: ex.severity), + '23503' => ForeignKeyViolationException(ex.message, severity: ex.severity), + '57014' => _PgQueryCancelledException( + ['${ex.code}:', ex.message, ex.trace].whereType().join(' '), + severity: ex.severity, + ), + _ => ex, + }; } class _PgQueryCancelledException extends PgException @@ -210,3 +212,17 @@ class _PgQueryCancelledException extends PgException required super.severity, }); } + +class DuplicateKeyException extends PgException { + DuplicateKeyException( + super.message, { + required super.severity, + }); +} + +class ForeignKeyViolationException extends PgException { + ForeignKeyViolationException( + super.message, { + required super.severity, + }); +} diff --git a/test/error_handling_test.dart b/test/error_handling_test.dart index 772a634..161c8d9 100644 --- a/test/error_handling_test.dart +++ b/test/error_handling_test.dart @@ -67,5 +67,46 @@ void main() { ), ); }); + + test('DuplicateKeyException', () async { + final c = await server.newConnection(); + await c.execute('CREATE TABLE test (id INT PRIMARY KEY);'); + await c.execute('INSERT INTO test (id) VALUES (1);'); + addTearDown(() async => c.execute('DROP TABLE test;')); + + try { + await c.execute('INSERT INTO test (id) VALUES (1);'); + } catch (e) { + expect(e, isA()); + expect( + e.toString(), + contains( + 'duplicate key value violates unique constraint "test_pkey"')); + } + }); + + test('ForeignKeyViolationException', () async { + final c = await server.newConnection(); + await c.execute('CREATE TABLE test (id INT PRIMARY KEY);'); + await c.execute( + 'CREATE TABLE test2 (id INT PRIMARY KEY, test_id INT REFERENCES test(id));'); + await c.execute('INSERT INTO test (id) VALUES (1);'); + addTearDown(() async { + await c.execute('DROP TABLE test2;'); + await c.execute('DROP TABLE test;'); + }); + + try { + await c.execute('INSERT INTO test2 (id, test_id) VALUES (1, 2);'); + } catch (e) { + expect(e, isA()); + expect( + e.toString(), + contains( + 'insert or update on table "test2" violates foreign key constraint "test2_test_id_fkey"', + ), + ); + } + }); }); } diff --git a/test/transaction_test.dart b/test/transaction_test.dart index 3f994a1..137b07d 100644 --- a/test/transaction_test.dart +++ b/test/transaction_test.dart @@ -700,7 +700,7 @@ void main() { // ignore } }), - throwsA(isA()), + throwsA(isA()), ); }); });