21
21
import functools
22
22
import operator
23
23
import typing
24
- from typing import Any , Dict , Iterable , Iterator , List , Optional , Tuple , Union
24
+ from typing import Any , Dict , Iterable , Iterator , List , Optional , Tuple , Union , Sequence
25
+
25
26
import warnings
26
27
27
28
try :
66
67
from google .cloud .bigquery .encryption_configuration import EncryptionConfiguration
67
68
from google .cloud .bigquery .enums import DefaultPandasDTypes
68
69
from google .cloud .bigquery .external_config import ExternalConfig
70
+ from google .cloud .bigquery import schema as _schema
69
71
from google .cloud .bigquery .schema import _build_schema_resource
70
72
from google .cloud .bigquery .schema import _parse_schema_resource
71
73
from google .cloud .bigquery .schema import _to_schema_fields
@@ -398,7 +400,7 @@ class Table(_TableBase):
398
400
"partitioning_type" : "timePartitioning" ,
399
401
"range_partitioning" : "rangePartitioning" ,
400
402
"time_partitioning" : "timePartitioning" ,
401
- "schema" : "schema" ,
403
+ "schema" : [ "schema" , "fields" ] ,
402
404
"snapshot_definition" : "snapshotDefinition" ,
403
405
"clone_definition" : "cloneDefinition" ,
404
406
"streaming_buffer" : "streamingBuffer" ,
@@ -411,6 +413,7 @@ class Table(_TableBase):
411
413
"max_staleness" : "maxStaleness" ,
412
414
"resource_tags" : "resourceTags" ,
413
415
"external_catalog_table_options" : "externalCatalogTableOptions" ,
416
+ "foreign_type_info" : ["schema" , "foreignTypeInfo" ],
414
417
}
415
418
416
419
def __init__ (self , table_ref , schema = None ) -> None :
@@ -451,8 +454,20 @@ def schema(self):
451
454
If ``schema`` is not a sequence, or if any item in the sequence
452
455
is not a :class:`~google.cloud.bigquery.schema.SchemaField`
453
456
instance or a compatible mapping representation of the field.
457
+
458
+ .. Note::
459
+ If you are referencing a schema for an external catalog table such
460
+ as a Hive table, it will also be necessary to populate the foreign_type_info
461
+ attribute. This is not necessary if defining the schema for a BigQuery table.
462
+
463
+ For details, see:
464
+ https://cloud.google.com/bigquery/docs/external-tables
465
+ https://cloud.google.com/bigquery/docs/datasets-intro#external_datasets
466
+
454
467
"""
455
- prop = self ._properties .get (self ._PROPERTY_TO_API_FIELD ["schema" ])
468
+ prop = _helpers ._get_sub_prop (
469
+ self ._properties , self ._PROPERTY_TO_API_FIELD ["schema" ]
470
+ )
456
471
if not prop :
457
472
return []
458
473
else :
@@ -463,10 +478,21 @@ def schema(self, value):
463
478
api_field = self ._PROPERTY_TO_API_FIELD ["schema" ]
464
479
465
480
if value is None :
466
- self ._properties [api_field ] = None
467
- else :
481
+ _helpers ._set_sub_prop (
482
+ self ._properties ,
483
+ api_field ,
484
+ None ,
485
+ )
486
+ elif isinstance (value , Sequence ):
468
487
value = _to_schema_fields (value )
469
- self ._properties [api_field ] = {"fields" : _build_schema_resource (value )}
488
+ value = _build_schema_resource (value )
489
+ _helpers ._set_sub_prop (
490
+ self ._properties ,
491
+ api_field ,
492
+ value ,
493
+ )
494
+ else :
495
+ raise TypeError ("Schema must be a Sequence (e.g. a list) or None." )
470
496
471
497
@property
472
498
def labels (self ):
@@ -1075,6 +1101,43 @@ def external_catalog_table_options(
1075
1101
self ._PROPERTY_TO_API_FIELD ["external_catalog_table_options" ]
1076
1102
] = value
1077
1103
1104
+ @property
1105
+ def foreign_type_info (self ) -> Optional [_schema .ForeignTypeInfo ]:
1106
+ """Optional. Specifies metadata of the foreign data type definition in
1107
+ field schema (TableFieldSchema.foreign_type_definition).
1108
+
1109
+ Returns:
1110
+ Optional[schema.ForeignTypeInfo]:
1111
+ Foreign type information, or :data:`None` if not set.
1112
+
1113
+ .. Note::
1114
+ foreign_type_info is only required if you are referencing an
1115
+ external catalog such as a Hive table.
1116
+ For details, see:
1117
+ https://cloud.google.com/bigquery/docs/external-tables
1118
+ https://cloud.google.com/bigquery/docs/datasets-intro#external_datasets
1119
+ """
1120
+
1121
+ prop = _helpers ._get_sub_prop (
1122
+ self ._properties , self ._PROPERTY_TO_API_FIELD ["foreign_type_info" ]
1123
+ )
1124
+ if prop is not None :
1125
+ return _schema .ForeignTypeInfo .from_api_repr (prop )
1126
+ return None
1127
+
1128
+ @foreign_type_info .setter
1129
+ def foreign_type_info (self , value : Union [_schema .ForeignTypeInfo , dict , None ]):
1130
+ value = _helpers ._isinstance_or_raise (
1131
+ value ,
1132
+ (_schema .ForeignTypeInfo , dict ),
1133
+ none_allowed = True ,
1134
+ )
1135
+ if isinstance (value , _schema .ForeignTypeInfo ):
1136
+ value = value .to_api_repr ()
1137
+ _helpers ._set_sub_prop (
1138
+ self ._properties , self ._PROPERTY_TO_API_FIELD ["foreign_type_info" ], value
1139
+ )
1140
+
1078
1141
@classmethod
1079
1142
def from_string (cls , full_table_id : str ) -> "Table" :
1080
1143
"""Construct a table from fully-qualified table ID.
0 commit comments