@@ -302,8 +302,8 @@ func Test_DB_TableFields(t *testing.T) {
302302 defer dropTable (table )
303303
304304 var expect = map [string ][]any {
305- //[]string: Index Type Null Key Default Comment
306- //id is bigserial so the default is a pgsql function
305+ // []string: Index Type Null Key Default Comment
306+ // id is bigserial so the default is a pgsql function
307307 "id" : {0 , "int8" , false , "pri" , fmt .Sprintf ("nextval('%s_id_seq'::regclass)" , table ), "" },
308308 "passport" : {1 , "varchar" , false , "" , nil , "" },
309309 "password" : {2 , "varchar" , false , "" , nil , "" },
@@ -384,6 +384,91 @@ int_col INT);`
384384
385385}
386386
387+ func Test_DB_TableFields_DuplicateConstraints (t * testing.T ) {
388+ // Test for the fix of duplicate field results with multiple constraints
389+ // This test verifies that when a field has multiple constraints (e.g., both primary key and unique),
390+ // the TableFields method correctly merges the results with proper priority (pri > uni > others)
391+ gtest .C (t , func (t * gtest.T ) {
392+ tableName := "test_multi_constraint"
393+ createSql := fmt .Sprintf (`
394+ CREATE TABLE %s (
395+ id bigserial NOT NULL PRIMARY KEY,
396+ email varchar(100) NOT NULL UNIQUE,
397+ username varchar(50) NOT NULL,
398+ status int NOT NULL DEFAULT 1
399+ )` , tableName )
400+
401+ _ , err := db .Exec (ctx , createSql )
402+ t .AssertNil (err )
403+ defer dropTable (tableName )
404+
405+ // Get table fields
406+ fields , err := db .TableFields (ctx , tableName )
407+ t .AssertNil (err )
408+
409+ // Verify id field has primary key constraint
410+ t .AssertNE (fields ["id" ], nil )
411+ t .Assert (fields ["id" ].Key , "pri" )
412+ t .Assert (fields ["id" ].Name , "id" )
413+ t .Assert (fields ["id" ].Type , "int8" )
414+
415+ // Verify email field has unique constraint
416+ t .AssertNE (fields ["email" ], nil )
417+ t .Assert (fields ["email" ].Key , "uni" )
418+ t .Assert (fields ["email" ].Name , "email" )
419+ t .Assert (fields ["email" ].Type , "varchar" )
420+
421+ // Verify username field has no constraint
422+ t .AssertNE (fields ["username" ], nil )
423+ t .Assert (fields ["username" ].Key , "" )
424+ t .Assert (fields ["username" ].Name , "username" )
425+
426+ // Verify status field has no constraint and has default value
427+ t .AssertNE (fields ["status" ], nil )
428+ t .Assert (fields ["status" ].Key , "" )
429+ t .Assert (fields ["status" ].Name , "status" )
430+ t .Assert (fields ["status" ].Default , 1 )
431+
432+ // Verify field count is correct (no duplicates)
433+ t .Assert (len (fields ), 4 )
434+ })
435+
436+ // Test table with composite constraints
437+ gtest .C (t , func (t * gtest.T ) {
438+ tableName := "test_composite_constraint"
439+ createSql := fmt .Sprintf (`
440+ CREATE TABLE %s (
441+ user_id bigint NOT NULL,
442+ project_id bigint NOT NULL,
443+ role varchar(50) NOT NULL,
444+ PRIMARY KEY (user_id, project_id)
445+ )` , tableName )
446+
447+ _ , err := db .Exec (ctx , createSql )
448+ t .AssertNil (err )
449+ defer dropTable (tableName )
450+
451+ // Get table fields
452+ fields , err := db .TableFields (ctx , tableName )
453+ t .AssertNil (err )
454+
455+ // In PostgreSQL, composite primary keys may appear in query results
456+ // The first field in the composite key should be marked as 'pri'
457+ t .AssertNE (fields ["user_id" ], nil )
458+ t .Assert (fields ["user_id" ].Name , "user_id" )
459+
460+ t .AssertNE (fields ["project_id" ], nil )
461+ t .Assert (fields ["project_id" ].Name , "project_id" )
462+
463+ t .AssertNE (fields ["role" ], nil )
464+ t .Assert (fields ["role" ].Name , "role" )
465+ t .Assert (fields ["role" ].Key , "" )
466+
467+ // Verify field count is correct (no duplicates)
468+ t .Assert (len (fields ), 3 )
469+ })
470+ }
471+
387472func Test_DB_InsertIgnore (t * testing.T ) {
388473 table := createTable ()
389474 defer dropTable (table )
0 commit comments