@@ -390,6 +390,7 @@ class Table(_TableBase):
390
390
"view_use_legacy_sql" : "view" ,
391
391
"view_query" : "view" ,
392
392
"require_partition_filter" : "requirePartitionFilter" ,
393
+ "table_constraints" : "tableConstraints" ,
393
394
}
394
395
395
396
def __init__ (self , table_ref , schema = None ) -> None :
@@ -973,6 +974,16 @@ def clone_definition(self) -> Optional["CloneDefinition"]:
973
974
clone_info = CloneDefinition (clone_info )
974
975
return clone_info
975
976
977
+ @property
978
+ def table_constraints (self ) -> Optional ["TableConstraints" ]:
979
+ """Tables Primary Key and Foreign Key information."""
980
+ table_constraints = self ._properties .get (
981
+ self ._PROPERTY_TO_API_FIELD ["table_constraints" ]
982
+ )
983
+ if table_constraints is not None :
984
+ table_constraints = TableConstraints .from_api_repr (table_constraints )
985
+ return table_constraints
986
+
976
987
@classmethod
977
988
def from_string (cls , full_table_id : str ) -> "Table" :
978
989
"""Construct a table from fully-qualified table ID.
@@ -2942,6 +2953,123 @@ def __repr__(self):
2942
2953
return "TimePartitioning({})" .format ("," .join (key_vals ))
2943
2954
2944
2955
2956
+ class PrimaryKey :
2957
+ """Represents the primary key constraint on a table's columns.
2958
+
2959
+ Args:
2960
+ columns: The columns that are composed of the primary key constraint.
2961
+ """
2962
+
2963
+ def __init__ (self , columns : List [str ]):
2964
+ self .columns = columns
2965
+
2966
+ def __eq__ (self , other ):
2967
+ if not isinstance (other , PrimaryKey ):
2968
+ raise NotImplementedError
2969
+ return self .columns == other .columns
2970
+
2971
+
2972
+ class ColumnReference :
2973
+ """The pair of the foreign key column and primary key column.
2974
+
2975
+ Args:
2976
+ referencing_column: The column that composes the foreign key.
2977
+ referenced_column: The column in the primary key that are referenced by the referencingColumn.
2978
+ """
2979
+
2980
+ def __init__ (self , referencing_column : str , referenced_column : str ):
2981
+ self .referencing_column = referencing_column
2982
+ self .referenced_column = referenced_column
2983
+
2984
+ def __eq__ (self , other ):
2985
+ if not isinstance (other , ColumnReference ):
2986
+ raise NotImplementedError
2987
+ return (
2988
+ self .referenced_column == other .referencing_column
2989
+ and self .referenced_column == other .referenced_column
2990
+ )
2991
+
2992
+ @classmethod
2993
+ def from_api_repr (cls , api_repr : Dict [str , Any ]) -> "ColumnReference" :
2994
+ """Create an instance from API representation."""
2995
+ return cls (api_repr ["referencingColumn" ], api_repr ["referencedColumn" ])
2996
+
2997
+
2998
+ class ForeignKey :
2999
+ """Represents a foreign key constraint on a table's columns.
3000
+
3001
+ Args:
3002
+ name: Set only if the foreign key constraint is named.
3003
+ referenced_table: The table that holds the primary key and is referenced by this foreign key.
3004
+ column_references: The columns that compose the foreign key.
3005
+ """
3006
+
3007
+ def __init__ (
3008
+ self ,
3009
+ name : str ,
3010
+ referenced_table : TableReference ,
3011
+ column_references : List [ColumnReference ],
3012
+ ):
3013
+ self .name = name
3014
+ self .referenced_table = referenced_table
3015
+ self .column_references = column_references
3016
+
3017
+ def __eq__ (self , other ):
3018
+ if not isinstance (other , ForeignKey ):
3019
+ raise NotImplementedError
3020
+ return (
3021
+ self .name == other .name and self .referenced_table == other .referenced_table
3022
+ )
3023
+
3024
+ @classmethod
3025
+ def from_api_repr (cls , api_repr : Dict [str , Any ]) -> "ForeignKey" :
3026
+ """Create an instance from API representation."""
3027
+ return cls (
3028
+ name = api_repr ["name" ],
3029
+ referenced_table = TableReference .from_api_repr (api_repr ["referencedTable" ]),
3030
+ column_references = [
3031
+ ColumnReference .from_api_repr (column_reference_resource )
3032
+ for column_reference_resource in api_repr ["columnReferences" ]
3033
+ ],
3034
+ )
3035
+
3036
+
3037
+ class TableConstraints :
3038
+ """The TableConstraints defines the primary key and foreign key.
3039
+
3040
+ Args:
3041
+ primary_key:
3042
+ Represents a primary key constraint on a table's columns. Present only if the table
3043
+ has a primary key. The primary key is not enforced.
3044
+ foreign_keys:
3045
+ Present only if the table has a foreign key. The foreign key is not enforced.
3046
+
3047
+ """
3048
+
3049
+ def __init__ (
3050
+ self ,
3051
+ primary_key : Optional [PrimaryKey ],
3052
+ foreign_keys : Optional [List [ForeignKey ]],
3053
+ ):
3054
+ self .primary_key = primary_key
3055
+ self .foreign_keys = foreign_keys
3056
+
3057
+ @classmethod
3058
+ def from_api_repr (cls , resource : Dict [str , Any ]) -> "TableConstraints" :
3059
+ """Create an instance from API representation."""
3060
+ primary_key = None
3061
+ if "primaryKey" in resource :
3062
+ primary_key = PrimaryKey (resource ["primaryKey" ]["columns" ])
3063
+
3064
+ foreign_keys = None
3065
+ if "foreignKeys" in resource :
3066
+ foreign_keys = [
3067
+ ForeignKey .from_api_repr (foreign_key_resource )
3068
+ for foreign_key_resource in resource ["foreignKeys" ]
3069
+ ]
3070
+ return cls (primary_key , foreign_keys )
3071
+
3072
+
2945
3073
def _item_to_row (iterator , resource ):
2946
3074
"""Convert a JSON row to the native object.
2947
3075
0 commit comments