Skip to content

Commit 8f5b4b7

Browse files
Linchintswast
andauthored
fix: create query job in job.result() if doesn't exist (#1944)
* fix: create query job in job.result() if doesn't exist * Apply suggestions from code review --------- Co-authored-by: Tim Sweña (Swast) <[email protected]>
1 parent 3e7a48d commit 8f5b4b7

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

google/cloud/bigquery/job/query.py

+5
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,11 @@ def is_job_done():
15851585
self._retry_do_query = retry_do_query
15861586
self._job_retry = job_retry
15871587

1588+
# If the job hasn't been created, create it now. Related:
1589+
# https://github.com/googleapis/python-bigquery/issues/1940
1590+
if self.state is None:
1591+
self._begin(retry=retry, **done_kwargs)
1592+
15881593
# Refresh the job status with jobs.get because some of the
15891594
# exceptions thrown by jobs.getQueryResults like timeout and
15901595
# rateLimitExceeded errors are ambiguous. We want to know if

tests/unit/job/test_query.py

+83
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,86 @@ def test_result_dry_run(self):
10371037
self.assertIsNone(result.job_id)
10381038
self.assertIsNone(result.query_id)
10391039

1040+
# If the job doesn't exist, create the job first. Issue:
1041+
# https://github.com/googleapis/python-bigquery/issues/1940
1042+
def test_result_begin_job_if_not_exist(self):
1043+
begun_resource = self._make_resource()
1044+
query_running_resource = {
1045+
"jobComplete": True,
1046+
"jobReference": {
1047+
"projectId": self.PROJECT,
1048+
"jobId": self.JOB_ID,
1049+
"location": "US",
1050+
},
1051+
"schema": {"fields": [{"name": "col1", "type": "STRING"}]},
1052+
"status": {"state": "RUNNING"},
1053+
}
1054+
query_done_resource = {
1055+
"jobComplete": True,
1056+
"jobReference": {
1057+
"projectId": self.PROJECT,
1058+
"jobId": self.JOB_ID,
1059+
"location": "US",
1060+
},
1061+
"schema": {"fields": [{"name": "col1", "type": "STRING"}]},
1062+
"status": {"state": "DONE"},
1063+
}
1064+
done_resource = copy.deepcopy(begun_resource)
1065+
done_resource["status"] = {"state": "DONE"}
1066+
connection = make_connection(
1067+
begun_resource,
1068+
query_running_resource,
1069+
query_done_resource,
1070+
done_resource,
1071+
)
1072+
client = _make_client(project=self.PROJECT, connection=connection)
1073+
job = self._make_one(self.JOB_ID, self.QUERY, client)
1074+
job._properties["jobReference"]["location"] = "US"
1075+
1076+
job.result()
1077+
1078+
create_job_call = mock.call(
1079+
method="POST",
1080+
path=f"/projects/{self.PROJECT}/jobs",
1081+
data={
1082+
"jobReference": {
1083+
"jobId": self.JOB_ID,
1084+
"projectId": self.PROJECT,
1085+
"location": "US",
1086+
},
1087+
"configuration": {
1088+
"query": {"useLegacySql": False, "query": self.QUERY},
1089+
},
1090+
},
1091+
timeout=None,
1092+
)
1093+
reload_call = mock.call(
1094+
method="GET",
1095+
path=f"/projects/{self.PROJECT}/jobs/{self.JOB_ID}",
1096+
query_params={"projection": "full", "location": "US"},
1097+
timeout=DEFAULT_GET_JOB_TIMEOUT,
1098+
)
1099+
get_query_results_call = mock.call(
1100+
method="GET",
1101+
path=f"/projects/{self.PROJECT}/queries/{self.JOB_ID}",
1102+
query_params={
1103+
"maxResults": 0,
1104+
"location": "US",
1105+
},
1106+
timeout=None,
1107+
)
1108+
1109+
connection.api_request.assert_has_calls(
1110+
[
1111+
# Make sure we start a job that hasn't started yet. See:
1112+
# https://github.com/googleapis/python-bigquery/issues/1940
1113+
create_job_call,
1114+
reload_call,
1115+
get_query_results_call,
1116+
reload_call,
1117+
]
1118+
)
1119+
10401120
def test_result_with_done_job_calls_get_query_results(self):
10411121
query_resource_done = {
10421122
"jobComplete": True,
@@ -1379,6 +1459,7 @@ def test_result_w_timeout_doesnt_raise(self):
13791459
client = _make_client(project=self.PROJECT, connection=connection)
13801460
job = self._make_one(self.JOB_ID, self.QUERY, client)
13811461
job._properties["jobReference"]["location"] = "US"
1462+
job._properties["status"] = {"state": "RUNNING"}
13821463

13831464
with freezegun.freeze_time("1970-01-01 00:00:00", tick=False):
13841465
job.result(
@@ -1429,6 +1510,7 @@ def test_result_w_timeout_raises_concurrent_futures_timeout(self):
14291510
client = _make_client(project=self.PROJECT, connection=connection)
14301511
job = self._make_one(self.JOB_ID, self.QUERY, client)
14311512
job._properties["jobReference"]["location"] = "US"
1513+
job._properties["status"] = {"state": "RUNNING"}
14321514

14331515
with freezegun.freeze_time(
14341516
"1970-01-01 00:00:00", auto_tick_seconds=1.0
@@ -2319,5 +2401,6 @@ def test_iter(self):
23192401
connection = make_connection(begun_resource, query_resource, done_resource)
23202402
client = _make_client(project=self.PROJECT, connection=connection)
23212403
job = self._make_one(self.JOB_ID, self.QUERY, client)
2404+
job._properties["status"] = {"state": "RUNNING"}
23222405

23232406
self.assertIsInstance(iter(job), types.GeneratorType)

0 commit comments

Comments
 (0)