@@ -236,6 +236,92 @@ describe('[#5495] autonumber sequence re-seed on a provable collision', () => {
236236 ) . toBeUndefined ( ) ;
237237 } ) ;
238238
239+ /**
240+ * The three-state routing, held against the shapes Postgres and MySQL
241+ * actually hand knex.
242+ *
243+ * This package's unit suite boots SQLite only, so the other two dialects'
244+ * errors are INJECTED rather than driven through a live server — the same
245+ * method, and the same reason, as `sql-driver-unique-violation-predicate`.
246+ * What it buys: the routing is what decides whether a caller's 409 survives,
247+ * and on MySQL — where `uniqueViolationColumn` can never answer, by contract
248+ * — state 3 is the only state that exists. Reasoning about that limb is not
249+ * the same as pinning it.
250+ */
251+ describe ( 'three-state routing on the dialects this package ships' , ( ) => {
252+ const reservation = {
253+ field : 'case_number' ,
254+ tableName : 'crm_case' ,
255+ prefix : 'CASE-' ,
256+ scope : '' ,
257+ suffix : '' ,
258+ tenantField : 'organization_id' ,
259+ tenantId : 'orgA' ,
260+ value : 'CASE-00001' ,
261+ } ;
262+
263+ /** Route one injected error, against a table where `CASE-00001` DOES exist. */
264+ const route = async ( error : unknown ) => {
265+ const colliding = await ( driver as any ) . collidingAutoNumberReservations ( error , [ reservation ] ) ;
266+ return colliding . map ( ( r : any ) => r . field ) ;
267+ } ;
268+
269+ beforeEach ( async ( ) => {
270+ await driver . initObjects ( [ CRM_CASE ] ) ;
271+ await knex ( ) ( 'crm_case' ) . insert ( { id : 'taken' , organization_id : 'orgA' , case_number : 'CASE-00001' , title : 'taken' } ) ;
272+ } ) ;
273+
274+ it ( 'state 1 — Postgres names our column in its DETAIL line' , async ( ) => {
275+ const err : any = new Error ( 'insert into "crm_case" … - duplicate key value violates unique constraint "uniq_crm_case_case_number"' ) ;
276+ err . code = '23505' ;
277+ err . detail = 'Key (case_number)=(CASE-00001) already exists.' ;
278+ expect ( uniqueViolationColumn ( err ) ) . toBe ( 'case_number' ) ;
279+ expect ( await route ( err ) ) . toEqual ( [ 'case_number' ] ) ;
280+ } ) ;
281+
282+ it ( 'state 2 — Postgres names a column the CALLER supplied, so nothing is retried' , async ( ) => {
283+ const err : any = new Error ( 'insert into "crm_case" … - duplicate key value violates unique constraint "uniq_crm_case_email"' ) ;
284+ err . code = '23505' ;
285+ err . detail = 'Key (email)=(dup@example.com) already exists.' ;
286+ expect ( uniqueViolationColumn ( err ) ) . toBe ( 'email' ) ;
287+ // Decided WITHOUT probing the data — and the data would have said yes,
288+ // since CASE-00001 is present. That is the whole point: a named column
289+ // that is not ours ends the matter.
290+ expect ( await route ( err ) ) . toEqual ( [ ] ) ;
291+ } ) ;
292+
293+ it ( 'state 3 — Postgres composite DETAIL names no single column, so the DATA decides' , async ( ) => {
294+ const err : any = new Error ( 'insert into "crm_case" … - duplicate key value violates unique constraint "uniq_crm_case_org_case"' ) ;
295+ err . code = '23505' ;
296+ err . detail = 'Key (organization_id, case_number)=(orgA, CASE-00001) already exists.' ;
297+ expect ( uniqueViolationColumn ( err ) ) . toBeUndefined ( ) ;
298+ expect ( await route ( err ) ) . toEqual ( [ 'case_number' ] ) ;
299+ } ) ;
300+
301+ it ( 'state 3 — MySQL can only ever name an index, so the DATA decides there always' , async ( ) => {
302+ const err : any = new Error ( "insert into `crm_case` … - ER_DUP_ENTRY: Duplicate entry 'orgA-CASE-00001' for key 'uniq_crm_case_org_case'" ) ;
303+ err . errno = 1062 ;
304+ err . code = 'ER_DUP_ENTRY' ;
305+ expect ( isUniqueViolationError ( err ) ) . toBe ( true ) ;
306+ expect ( uniqueViolationColumn ( err ) ) . toBeUndefined ( ) ;
307+ expect ( await route ( err ) ) . toEqual ( [ 'case_number' ] ) ;
308+ } ) ;
309+
310+ it ( 'state 3 — but an undeterminable violation on someone ELSE’s value is still not ours' , async ( ) => {
311+ const err : any = new Error ( "insert into `crm_case` … - ER_DUP_ENTRY: Duplicate entry 'x' for key 'uniq_crm_case_email'" ) ;
312+ err . errno = 1062 ;
313+ const other = { ...reservation , value : 'CASE-99999' } ; // never written
314+ const colliding = await ( driver as any ) . collidingAutoNumberReservations ( err , [ other ] ) ;
315+ expect ( colliding ) . toEqual ( [ ] ) ;
316+ } ) ;
317+
318+ it ( 'a failure that is not a unique violation at all is never routed here' , async ( ) => {
319+ const err : any = new Error ( 'insert into `crm_case` … - NOT NULL constraint failed: crm_case.title' ) ;
320+ expect ( isUniqueViolationError ( err ) ) . toBe ( false ) ;
321+ expect ( await route ( err ) ) . toEqual ( [ ] ) ;
322+ } ) ;
323+ } ) ;
324+
239325 it ( 'gives the caller the original error when the collision is not the counter’s' , async ( ) => {
240326 // A value the caller supplies explicitly is not a reservation, so no probe
241327 // and no retry can apply to it even though it IS the autonumber column.
0 commit comments