@@ -52,9 +52,20 @@ def generate_tests(quirks: model.DriverQuirks, metafunc) -> None:
5252 indirect = ["driver" ],
5353 )
5454 else :
55+ marks = []
56+ if (
57+ enabled := {
58+ "test_get_objects_constraints_check" : quirks .features .get_objects_constraints_check ,
59+ "test_get_objects_constraints_foreign" : quirks .features .get_objects_constraints_foreign ,
60+ "test_get_objects_constraints_primary" : quirks .features .get_objects_constraints_primary ,
61+ "test_get_objects_constraints_unique" : quirks .features .get_objects_constraints_unique ,
62+ }.get (metafunc .definition .name )
63+ ) is not None :
64+ if not enabled :
65+ marks .append (pytest .mark .skip (reason = "not implemented" ))
5566 metafunc .parametrize (
5667 "driver" ,
57- [pytest .param (quirks .name , id = quirks .name )],
68+ [pytest .param (quirks .name , id = quirks .name , marks = marks )],
5869 scope = "module" ,
5970 indirect = ["driver" ],
6071 )
@@ -602,7 +613,8 @@ def test_get_objects_column_xdbc(
602613 elif field == "xdbc_is_nullable" :
603614 assert column [field ] == "YES"
604615
605- def test_get_objects_constraints (
616+ @pytest .fixture (scope = "class" )
617+ def get_objects_constraints (
606618 self ,
607619 driver : model .DriverQuirks ,
608620 conn : adbc_driver_manager .dbapi .Connection ,
@@ -614,6 +626,7 @@ def test_get_objects_constraints(
614626 "constraint_foreign_multi" ,
615627 "constraint_primary" ,
616628 "constraint_primary_multi" ,
629+ "constraint_primary_multi2" ,
617630 )
618631 with conn .cursor () as cursor :
619632 for table in table_names :
@@ -622,12 +635,18 @@ def test_get_objects_constraints(
622635 for stmt in driver .sample_ddl_constraints :
623636 cursor .execute (stmt )
624637
638+ def get_constraints (
639+ self ,
640+ driver : model .DriverQuirks ,
641+ conn : adbc_driver_manager .dbapi .Connection ,
642+ table_filter : str ,
643+ ) -> dict [str , list [dict ]]:
625644 objects = (
626645 conn .adbc_get_objects (
627646 depth = "columns" ,
628647 catalog_filter = driver .features .current_catalog ,
629648 db_schema_filter = driver .features .current_schema ,
630- table_name_filter = "constraint_%" ,
649+ table_name_filter = table_filter ,
631650 )
632651 .read_all ()
633652 .to_pylist ()
@@ -638,11 +657,17 @@ def test_get_objects_constraints(
638657 for schema in obj ["catalog_db_schemas" ]
639658 for table in schema ["db_schema_tables" ]
640659 }
641-
642- assert set (tables ) == set (table_names )
643660 for table , constraints in tables .items ():
644661 assert constraints is not None , table
662+ return tables
645663
664+ def test_get_objects_constraints_check (
665+ self ,
666+ driver : model .DriverQuirks ,
667+ conn : adbc_driver_manager .dbapi .Connection ,
668+ get_objects_constraints : None ,
669+ ) -> None :
670+ tables = self .get_constraints (driver , conn , "constraint_check" )
646671 assert len (tables ["constraint_check" ]) == 2
647672 constraints = list (
648673 sorted (
@@ -667,6 +692,81 @@ def test_get_objects_constraints(
667692 },
668693 )
669694
695+ def test_get_objects_constraints_foreign (
696+ self ,
697+ driver : model .DriverQuirks ,
698+ conn : adbc_driver_manager .dbapi .Connection ,
699+ get_objects_constraints : None ,
700+ ) -> None :
701+ tables = self .get_constraints (driver , conn , "constraint_foreign%" )
702+
703+ assert len (tables ["constraint_foreign" ]) == 1 , repr (tables )
704+ compare .match_fields (
705+ tables ["constraint_foreign" ][0 ],
706+ {
707+ "constraint_type" : "FOREIGN KEY" ,
708+ "constraint_column_names" : ["b" ],
709+ "constraint_column_usage" : [
710+ {
711+ "fk_catalog" : driver .features .current_catalog ,
712+ "fk_db_schema" : driver .features .current_schema ,
713+ "fk_table" : "constraint_primary" ,
714+ "fk_column_name" : "a" ,
715+ }
716+ ],
717+ },
718+ )
719+
720+ # Some databases don't preserve the order of columns in a multi-column
721+ # foreign key
722+ assert len (tables ["constraint_foreign_multi" ]) == 1 , repr (tables )
723+ constraint = tables ["constraint_foreign_multi" ][0 ]
724+ compare .match_fields (
725+ constraint ,
726+ {"constraint_type" : "FOREIGN KEY" },
727+ )
728+ cols = constraint ["constraint_column_names" ]
729+ if driver .features .quirk_get_objects_constraints_foreign_normalized :
730+ assert cols == ["b" , "c" ]
731+ assert constraint ["constraint_column_usage" ] == [
732+ {
733+ "fk_catalog" : driver .features .current_catalog ,
734+ "fk_db_schema" : driver .features .current_schema ,
735+ "fk_table" : "constraint_primary_multi2" ,
736+ "fk_column_name" : "b" ,
737+ },
738+ {
739+ "fk_catalog" : driver .features .current_catalog ,
740+ "fk_db_schema" : driver .features .current_schema ,
741+ "fk_table" : "constraint_primary_multi2" ,
742+ "fk_column_name" : "a" ,
743+ },
744+ ], repr (constraint )
745+ else :
746+ assert cols == ["c" , "b" ]
747+ assert constraint ["constraint_column_usage" ] == [
748+ {
749+ "fk_catalog" : driver .features .current_catalog ,
750+ "fk_db_schema" : driver .features .current_schema ,
751+ "fk_table" : "constraint_primary_multi2" ,
752+ "fk_column_name" : "a" ,
753+ },
754+ {
755+ "fk_catalog" : driver .features .current_catalog ,
756+ "fk_db_schema" : driver .features .current_schema ,
757+ "fk_table" : "constraint_primary_multi2" ,
758+ "fk_column_name" : "b" ,
759+ },
760+ ], repr (constraint )
761+
762+ def test_get_objects_constraints_primary (
763+ self ,
764+ driver : model .DriverQuirks ,
765+ conn : adbc_driver_manager .dbapi .Connection ,
766+ get_objects_constraints : None ,
767+ ) -> None :
768+ tables = self .get_constraints (driver , conn , "constraint_primary%" )
769+
670770 assert len (tables ["constraint_primary" ]) == 1
671771 compare .match_fields (
672772 tables ["constraint_primary" ][0 ],
@@ -678,14 +778,37 @@ def test_get_objects_constraints(
678778 )
679779
680780 assert len (tables ["constraint_primary_multi" ]) == 1
781+ constraint = tables ["constraint_primary_multi" ][0 ]
782+ compare .match_fields (
783+ constraint ,
784+ {
785+ "constraint_type" : "PRIMARY KEY" ,
786+ "constraint_column_usage" : None ,
787+ },
788+ )
789+ if driver .features .quirk_get_objects_constraints_primary_normalized :
790+ assert constraint ["constraint_column_names" ] == ["a" , "b" ]
791+ else :
792+ assert constraint ["constraint_column_names" ] == ["b" , "a" ]
793+
794+ assert len (tables ["constraint_primary_multi2" ]) == 1
795+ constraint = tables ["constraint_primary_multi2" ][0 ]
681796 compare .match_fields (
682- tables [ "constraint_primary_multi" ][ 0 ] ,
797+ constraint ,
683798 {
684799 "constraint_type" : "PRIMARY KEY" ,
685- "constraint_column_names" : ["a" , "b" ],
686800 "constraint_column_usage" : None ,
687801 },
688802 )
803+ assert constraint ["constraint_column_names" ] == ["a" , "b" ]
804+
805+ def test_get_objects_constraints_unique (
806+ self ,
807+ driver : model .DriverQuirks ,
808+ conn : adbc_driver_manager .dbapi .Connection ,
809+ get_objects_constraints : None ,
810+ ) -> None :
811+ tables = self .get_constraints (driver , conn , "constraint_unique%" )
689812
690813 assert len (tables ["constraint_unique" ]) == 2
691814 constraints = list (
@@ -702,54 +825,19 @@ def test_get_objects_constraints(
702825 "constraint_column_usage" : None ,
703826 },
704827 )
828+
829+ # Even if declared as UNIQUE(c, b), some databases return [b, c]
705830 compare .match_fields (
706831 constraints [1 ],
707832 {
708833 "constraint_type" : "UNIQUE" ,
709- "constraint_column_names" : ["b" , "c" ],
710834 "constraint_column_usage" : None ,
711835 },
712836 )
713-
714- assert len (tables ["constraint_foreign" ]) == 1
715- compare .match_fields (
716- tables ["constraint_foreign" ][0 ],
717- {
718- "constraint_type" : "FOREIGN KEY" ,
719- "constraint_column_names" : ["b" ],
720- "constraint_column_usage" : [
721- {
722- "fk_catalog" : "master" ,
723- "fk_db_schema" : "dbo" ,
724- "fk_table" : "constraint_primary" ,
725- "fk_column_name" : "a" ,
726- }
727- ],
728- },
729- )
730-
731- assert len (tables ["constraint_foreign_multi" ]) == 1
732- compare .match_fields (
733- tables ["constraint_foreign_multi" ][0 ],
734- {
735- "constraint_type" : "FOREIGN KEY" ,
736- "constraint_column_names" : ["b" , "c" ],
737- "constraint_column_usage" : [
738- {
739- "fk_catalog" : "master" ,
740- "fk_db_schema" : "dbo" ,
741- "fk_table" : "constraint_primary_multi" ,
742- "fk_column_name" : "a" ,
743- },
744- {
745- "fk_catalog" : "master" ,
746- "fk_db_schema" : "dbo" ,
747- "fk_table" : "constraint_primary_multi" ,
748- "fk_column_name" : "b" ,
749- },
750- ],
751- },
752- )
837+ if driver .features .quirk_get_objects_constraints_unique_normalized :
838+ assert constraints [1 ]["constraint_column_names" ] == ["b" , "c" ]
839+ else :
840+ assert constraints [1 ]["constraint_column_names" ] == ["c" , "b" ]
753841
754842 def test_get_table_schema (
755843 self ,
0 commit comments