|
22 | 22 | import google.api_core.retry
|
23 | 23 | import freezegun
|
24 | 24 |
|
| 25 | +from google.cloud.bigquery.client import Client |
| 26 | +from google.cloud.bigquery import _job_helpers |
| 27 | +from google.cloud.bigquery.retry import DEFAULT_JOB_RETRY |
| 28 | + |
25 | 29 | from .helpers import make_connection
|
26 | 30 |
|
27 | 31 |
|
@@ -240,3 +244,79 @@ def test_raises_on_job_retry_on_result_with_non_retryable_jobs(client):
|
240 | 244 | ),
|
241 | 245 | ):
|
242 | 246 | job.result(job_retry=google.api_core.retry.Retry())
|
| 247 | + |
| 248 | + |
| 249 | +def test_query_and_wait_retries_job_for_DDL_queries(): |
| 250 | + """ |
| 251 | + Specific test for retrying DDL queries with "jobRateLimitExceeded" error: |
| 252 | + https://github.com/googleapis/python-bigquery/issues/1790 |
| 253 | + """ |
| 254 | + freezegun.freeze_time(auto_tick_seconds=1) |
| 255 | + client = mock.create_autospec(Client) |
| 256 | + client._call_api.__name__ = "_call_api" |
| 257 | + client._call_api.__qualname__ = "Client._call_api" |
| 258 | + client._call_api.__annotations__ = {} |
| 259 | + client._call_api.__type_params__ = () |
| 260 | + client._call_api.side_effect = ( |
| 261 | + { |
| 262 | + "jobReference": { |
| 263 | + "projectId": "response-project", |
| 264 | + "jobId": "abc", |
| 265 | + "location": "response-location", |
| 266 | + }, |
| 267 | + "jobComplete": False, |
| 268 | + }, |
| 269 | + google.api_core.exceptions.InternalServerError( |
| 270 | + "job_retry me", errors=[{"reason": "jobRateLimitExceeded"}] |
| 271 | + ), |
| 272 | + google.api_core.exceptions.BadRequest( |
| 273 | + "retry me", errors=[{"reason": "jobRateLimitExceeded"}] |
| 274 | + ), |
| 275 | + { |
| 276 | + "jobReference": { |
| 277 | + "projectId": "response-project", |
| 278 | + "jobId": "abc", |
| 279 | + "location": "response-location", |
| 280 | + }, |
| 281 | + "jobComplete": True, |
| 282 | + "schema": { |
| 283 | + "fields": [ |
| 284 | + {"name": "full_name", "type": "STRING", "mode": "REQUIRED"}, |
| 285 | + {"name": "age", "type": "INT64", "mode": "NULLABLE"}, |
| 286 | + ], |
| 287 | + }, |
| 288 | + "rows": [ |
| 289 | + {"f": [{"v": "Whillma Phlyntstone"}, {"v": "27"}]}, |
| 290 | + {"f": [{"v": "Bhetty Rhubble"}, {"v": "28"}]}, |
| 291 | + {"f": [{"v": "Phred Phlyntstone"}, {"v": "32"}]}, |
| 292 | + {"f": [{"v": "Bharney Rhubble"}, {"v": "33"}]}, |
| 293 | + ], |
| 294 | + }, |
| 295 | + ) |
| 296 | + rows = _job_helpers.query_and_wait( |
| 297 | + client, |
| 298 | + query="SELECT 1", |
| 299 | + location="request-location", |
| 300 | + project="request-project", |
| 301 | + job_config=None, |
| 302 | + page_size=None, |
| 303 | + max_results=None, |
| 304 | + retry=DEFAULT_JOB_RETRY, |
| 305 | + job_retry=DEFAULT_JOB_RETRY, |
| 306 | + ) |
| 307 | + assert len(list(rows)) == 4 |
| 308 | + |
| 309 | + # Relevant docs for the REST API path: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query |
| 310 | + # and https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/getQueryResults |
| 311 | + query_request_path = "/projects/request-project/queries" |
| 312 | + |
| 313 | + calls = client._call_api.call_args_list |
| 314 | + _, kwargs = calls[0] |
| 315 | + assert kwargs["method"] == "POST" |
| 316 | + assert kwargs["path"] == query_request_path |
| 317 | + |
| 318 | + # TODO: Add assertion statements for response paths after PR#1797 is fixed |
| 319 | + |
| 320 | + _, kwargs = calls[3] |
| 321 | + assert kwargs["method"] == "POST" |
| 322 | + assert kwargs["path"] == query_request_path |
0 commit comments