Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions bigquery/google/cloud/bigquery/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ def __init__(self, name, query, client,
dry_run = _TypedProperty('dry_run', bool)
"""See:
https://cloud.google.com/bigquery/docs/\
reference/v2/jobs#configuration.query.dryRun
reference/rest/v2/jobs#configuration.dryRun
"""

write_disposition = WriteDisposition('write_disposition')
Expand Down Expand Up @@ -1024,8 +1024,6 @@ def _populate_config_resource_booleans(self, configuration):
configuration['useQueryCache'] = self.use_query_cache
if self.use_legacy_sql is not None:
configuration['useLegacySql'] = self.use_legacy_sql
if self.dry_run is not None:
configuration['dryRun'] = self.dry_run

def _populate_config_resource(self, configuration):
"""Helper for _build_resource: copy config properties to resource"""
Expand Down Expand Up @@ -1078,6 +1076,10 @@ def _build_resource(self):
},
},
}

if self.dry_run is not None:
resource['configuration']['dryRun'] = self.dry_run

configuration = resource['configuration'][self._JOB_TYPE]
self._populate_config_resource(configuration)

Expand Down
85 changes: 63 additions & 22 deletions bigquery/unit_tests/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -1331,11 +1331,6 @@ def _verifyBooleanResourceProperties(self, job, config):
config['useLegacySql'])
else:
self.assertIsNone(job.use_legacy_sql)
if 'dryRun' in config:
self.assertEqual(job.dry_run,
config['dryRun'])
else:
self.assertIsNone(job.dry_run)

def _verifyIntegerResourceProperties(self, job, config):
if 'maximumBillingTier' in config:
Expand Down Expand Up @@ -1366,48 +1361,58 @@ def _verifyQueryParameters(self, job, config):
for found, expected in zip(job.query_parameters, query_parameters):
self.assertEqual(found.to_api_repr(), expected)

def _verify_configuration_properties(self, job, configuration):
if 'dryRun' in configuration:
self.assertEqual(job.dry_run,
configuration['dryRun'])
else:
self.assertIsNone(job.dry_run)

def _verifyResourceProperties(self, job, resource):
self._verifyReadonlyResourceProperties(job, resource)

config = resource.get('configuration', {}).get('query')
self._verifyBooleanResourceProperties(job, config)
self._verifyIntegerResourceProperties(job, config)
self._verify_udf_resources(job, config)
self._verifyQueryParameters(job, config)
configuration = resource.get('configuration', {})
self._verify_configuration_properties(job, configuration)

self.assertEqual(job.query, config['query'])
if 'createDisposition' in config:
query_config = resource.get('configuration', {}).get('query')
self._verifyBooleanResourceProperties(job, query_config)
self._verifyIntegerResourceProperties(job, query_config)
self._verify_udf_resources(job, query_config)
self._verifyQueryParameters(job, query_config)

self.assertEqual(job.query, query_config['query'])
if 'createDisposition' in query_config:
self.assertEqual(job.create_disposition,
config['createDisposition'])
query_config['createDisposition'])
else:
self.assertIsNone(job.create_disposition)
if 'defaultDataset' in config:
if 'defaultDataset' in query_config:
dataset = job.default_dataset
ds_ref = {
'projectId': dataset.project,
'datasetId': dataset.name,
}
self.assertEqual(ds_ref, config['defaultDataset'])
self.assertEqual(ds_ref, query_config['defaultDataset'])
else:
self.assertIsNone(job.default_dataset)
if 'destinationTable' in config:
if 'destinationTable' in query_config:
table = job.destination
tb_ref = {
'projectId': table.project,
'datasetId': table.dataset_name,
'tableId': table.name
}
self.assertEqual(tb_ref, config['destinationTable'])
self.assertEqual(tb_ref, query_config['destinationTable'])
else:
self.assertIsNone(job.destination)
if 'priority' in config:
if 'priority' in query_config:
self.assertEqual(job.priority,
config['priority'])
query_config['priority'])
else:
self.assertIsNone(job.priority)
if 'writeDisposition' in config:
if 'writeDisposition' in query_config:
self.assertEqual(job.write_disposition,
config['writeDisposition'])
query_config['writeDisposition'])
else:
self.assertIsNone(job.write_disposition)

Expand Down Expand Up @@ -1575,7 +1580,6 @@ def test_begin_w_alternate_client(self):
'priority': 'INTERACTIVE',
'useQueryCache': True,
'useLegacySql': True,
'dryRun': True,
'writeDisposition': 'WRITE_TRUNCATE',
'maximumBillingTier': 4,
'maximumBytesBilled': 123456
Expand All @@ -1599,6 +1603,7 @@ def test_begin_w_alternate_client(self):
job.use_query_cache = True
job.use_legacy_sql = True
job.dry_run = True
RESOURCE['configuration']['dryRun'] = True
job.write_disposition = 'WRITE_TRUNCATE'
job.maximum_billing_tier = 4
job.maximum_bytes_billed = 123456
Expand All @@ -1616,6 +1621,7 @@ def test_begin_w_alternate_client(self):
'jobId': self.JOB_NAME,
},
'configuration': {
'dryRun': True,
'query': QUERY_CONFIGURATION,
},
}
Expand Down Expand Up @@ -1775,6 +1781,41 @@ def test_begin_w_positional_query_parameter(self):
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(job, RESOURCE)

def test_dry_run_query(self):
PATH = '/projects/%s/jobs' % (self.PROJECT,)
RESOURCE = self._makeResource()
# Ensure None for missing server-set props
del RESOURCE['statistics']['creationTime']
del RESOURCE['etag']
del RESOURCE['selfLink']
del RESOURCE['user_email']
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
job = self._make_one(self.JOB_NAME, self.QUERY, client)
job.dry_run = True
RESOURCE['configuration']['dryRun'] = True

job.begin()
self.assertEqual(job.udf_resources, [])
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], PATH)
SENT = {
'jobReference': {
'projectId': self.PROJECT,
'jobId': self.JOB_NAME,
},
'configuration': {
'query': {
'query': self.QUERY
},
'dryRun': True,
},
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(job, RESOURCE)

def test_exists_miss_w_bound_client(self):
PATH = '/projects/%s/jobs/%s' % (self.PROJECT, self.JOB_NAME)
conn = _Connection()
Expand Down