2828from google .cloud .bigquery .table import Table
2929from google .cloud .bigquery .table import _build_schema_resource
3030from google .cloud .bigquery .table import _parse_schema_resource
31+ from google .cloud .bigquery ._helpers import ArrayQueryParameter
3132from google .cloud .bigquery ._helpers import QueryParametersProperty
33+ from google .cloud .bigquery ._helpers import ScalarQueryParameter
34+ from google .cloud .bigquery ._helpers import StructQueryParameter
35+ from google .cloud .bigquery ._helpers import UDFResource
3236from google .cloud .bigquery ._helpers import UDFResourcesProperty
3337from google .cloud .bigquery ._helpers import _EnumProperty
38+ from google .cloud .bigquery ._helpers import _query_param_from_api_repr
3439from google .cloud .bigquery ._helpers import _TypedProperty
3540
3641_DONE_STATE = 'DONE'
5863}
5964
6065
66+ def _bool_or_none (value ):
67+ """Helper: deserialize boolean value from JSON string."""
68+ if isinstance (value , bool ):
69+ return value
70+ if value is not None :
71+ return value .lower () in ['t' , 'true' , '1' ]
72+
73+
74+ def _int_or_none (value ):
75+ """Helper: deserialize int value from JSON string."""
76+ if isinstance (value , int ):
77+ return value
78+ if value is not None :
79+ return int (value )
80+
81+
6182def _error_result_to_exception (error_result ):
6283 """Maps BigQuery error reasons to an exception.
6384
@@ -303,6 +324,10 @@ def _scrub_local_properties(self, cleaned):
303324 """Helper: handle subclass properties in cleaned."""
304325 pass
305326
327+ def _copy_configuration_properties (self , configuration ):
328+ """Helper: assign subclass configuration properties in cleaned."""
329+ raise NotImplementedError ("Abstract" )
330+
306331 def _set_properties (self , api_response ):
307332 """Update properties from resource in body of ``api_response``
308333
@@ -322,6 +347,8 @@ def _set_properties(self, api_response):
322347
323348 self ._properties .clear ()
324349 self ._properties .update (cleaned )
350+ configuration = cleaned ['configuration' ][self ._JOB_TYPE ]
351+ self ._copy_configuration_properties (configuration )
325352
326353 # For Future interface
327354 self ._set_future_result ()
@@ -759,6 +786,28 @@ def _scrub_local_properties(self, cleaned):
759786 schema = cleaned .pop ('schema' , {'fields' : ()})
760787 self .schema = _parse_schema_resource (schema )
761788
789+ def _copy_configuration_properties (self , configuration ):
790+ """Helper: assign subclass configuration properties in cleaned."""
791+ self .allow_jagged_rows = _bool_or_none (
792+ configuration .get ('allowJaggedRows' ))
793+ self .allow_quoted_newlines = _bool_or_none (
794+ configuration .get ('allowQuotedNewlines' ))
795+ self .autodetect = _bool_or_none (
796+ configuration .get ('autodetect' ))
797+ self .create_disposition = configuration .get ('createDisposition' )
798+ self .encoding = configuration .get ('encoding' )
799+ self .field_delimiter = configuration .get ('fieldDelimiter' )
800+ self .ignore_unknown_values = _bool_or_none (
801+ configuration .get ('ignoreUnknownValues' ))
802+ self .max_bad_records = _int_or_none (
803+ configuration .get ('maxBadRecords' ))
804+ self .null_marker = configuration .get ('nullMarker' )
805+ self .quote_character = configuration .get ('quote' )
806+ self .skip_leading_rows = _int_or_none (
807+ configuration .get ('skipLeadingRows' ))
808+ self .source_format = configuration .get ('sourceFormat' )
809+ self .write_disposition = configuration .get ('writeDisposition' )
810+
762811 @classmethod
763812 def from_api_repr (cls , resource , client ):
764813 """Factory: construct a job given its API representation
@@ -869,6 +918,11 @@ def _build_resource(self):
869918
870919 return resource
871920
921+ def _copy_configuration_properties (self , configuration ):
922+ """Helper: assign subclass configuration properties in cleaned."""
923+ self .create_disposition = configuration .get ('createDisposition' )
924+ self .write_disposition = configuration .get ('writeDisposition' )
925+
872926 @classmethod
873927 def from_api_repr (cls , resource , client ):
874928 """Factory: construct a job given its API representation
@@ -1002,6 +1056,14 @@ def _build_resource(self):
10021056
10031057 return resource
10041058
1059+ def _copy_configuration_properties (self , configuration ):
1060+ """Helper: assign subclass configuration properties in cleaned."""
1061+ self .compression = configuration .get ('compression' )
1062+ self .destination_format = configuration .get ('destinationFormat' )
1063+ self .field_delimiter = configuration .get ('fieldDelimiter' )
1064+ self .print_header = _bool_or_none (
1065+ configuration .get ('printHeader' ))
1066+
10051067 @classmethod
10061068 def from_api_repr (cls , resource , client ):
10071069 """Factory: construct a job given its API representation
@@ -1247,6 +1309,24 @@ def _scrub_local_properties(self, cleaned):
12471309 configuration = cleaned ['configuration' ]['query' ]
12481310
12491311 self .query = configuration ['query' ]
1312+
1313+ def _copy_configuration_properties (self , configuration ):
1314+ """Helper: assign subclass configuration properties in cleaned."""
1315+ self .allow_large_results = _bool_or_none (
1316+ configuration .get ('allowLargeResults' ))
1317+ self .flatten_results = _bool_or_none (
1318+ configuration .get ('flattenResults' ))
1319+ self .use_query_cache = _bool_or_none (
1320+ configuration .get ('useQueryCache' ))
1321+ self .use_legacy_sql = _bool_or_none (
1322+ configuration .get ('useLegacySql' ))
1323+
1324+ self .create_disposition = configuration .get ('createDisposition' )
1325+ self .priority = configuration .get ('priority' )
1326+ self .write_disposition = configuration .get ('writeDisposition' )
1327+ self .maximum_billing_tier = configuration .get ('maximumBillingTier' )
1328+ self .maximum_bytes_billed = configuration .get ('maximumBytesBilled' )
1329+
12501330 dest_remote = configuration .get ('destinationTable' )
12511331
12521332 if dest_remote is None :
@@ -1255,9 +1335,30 @@ def _scrub_local_properties(self, cleaned):
12551335 else :
12561336 dest_local = self ._destination_table_resource ()
12571337 if dest_remote != dest_local :
1258- dataset = self ._client .dataset (dest_remote ['datasetId' ])
1338+ project = dest_remote ['projectId' ]
1339+ dataset = self ._client .dataset (
1340+ dest_remote ['datasetId' ], project = project )
12591341 self .destination = dataset .table (dest_remote ['tableId' ])
12601342
1343+ def_ds = configuration .get ('defaultDataset' )
1344+ if def_ds is None :
1345+ if self .default_dataset is not None :
1346+ del self .default_dataset
1347+ else :
1348+ project = def_ds ['projectId' ]
1349+ self .default_dataset = self ._client .dataset (def_ds ['datasetId' ])
1350+
1351+ udf_resources = []
1352+ for udf_mapping in configuration .get (self ._UDF_KEY , ()):
1353+ key_val , = udf_mapping .items ()
1354+ udf_resources .append (UDFResource (key_val [0 ], key_val [1 ]))
1355+ self ._udf_resources = udf_resources
1356+
1357+ self ._query_parameters = [
1358+ _query_param_from_api_repr (mapping )
1359+ for mapping in configuration .get (self ._QUERY_PARAMETERS_KEY , ())
1360+ ]
1361+
12611362 @classmethod
12621363 def from_api_repr (cls , resource , client ):
12631364 """Factory: construct a job given its API representation
0 commit comments