@@ -400,9 +400,13 @@ def query_and_wait(
400
400
:class:`~google.cloud.bigquery.job.QueryJobConfig`
401
401
class.
402
402
"""
403
+ request_body = _to_query_request (
404
+ query = query , job_config = job_config , location = location , timeout = api_timeout
405
+ )
406
+
403
407
# Some API parameters aren't supported by the jobs.query API. In these
404
408
# cases, fallback to a jobs.insert call.
405
- if not _supported_by_jobs_query (job_config ):
409
+ if not _supported_by_jobs_query (request_body ):
406
410
return _wait_or_cancel (
407
411
query_jobs_insert (
408
412
client = client ,
@@ -424,9 +428,6 @@ def query_and_wait(
424
428
)
425
429
426
430
path = _to_query_path (project )
427
- request_body = _to_query_request (
428
- query = query , job_config = job_config , location = location , timeout = api_timeout
429
- )
430
431
431
432
if page_size is not None and max_results is not None :
432
433
request_body ["maxResults" ] = min (page_size , max_results )
@@ -506,20 +507,38 @@ def do_query():
506
507
return do_query ()
507
508
508
509
509
- def _supported_by_jobs_query (job_config : Optional [ job . QueryJobConfig ]) -> bool :
510
+ def _supported_by_jobs_query (request_body : Dict [ str , Any ]) -> bool :
510
511
"""True if jobs.query can be used. False if jobs.insert is needed."""
511
- if job_config is None :
512
- return True
513
-
514
- return (
515
- # These features aren't supported by jobs.query.
516
- job_config .clustering_fields is None
517
- and job_config .destination is None
518
- and job_config .destination_encryption_configuration is None
519
- and job_config .range_partitioning is None
520
- and job_config .table_definitions is None
521
- and job_config .time_partitioning is None
522
- )
512
+ request_keys = frozenset (request_body .keys ())
513
+
514
+ # Per issue: https://github.com/googleapis/python-bigquery/issues/1867
515
+ # use an allowlist here instead of a denylist because the backend API allows
516
+ # unsupported parameters without any warning or failure. Instead, keep this
517
+ # set in sync with those in QueryRequest:
518
+ # https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#QueryRequest
519
+ keys_allowlist = {
520
+ "kind" ,
521
+ "query" ,
522
+ "maxResults" ,
523
+ "defaultDataset" ,
524
+ "timeoutMs" ,
525
+ "dryRun" ,
526
+ "preserveNulls" ,
527
+ "useQueryCache" ,
528
+ "useLegacySql" ,
529
+ "parameterMode" ,
530
+ "queryParameters" ,
531
+ "location" ,
532
+ "formatOptions" ,
533
+ "connectionProperties" ,
534
+ "labels" ,
535
+ "maximumBytesBilled" ,
536
+ "requestId" ,
537
+ "createSession" ,
538
+ }
539
+
540
+ unsupported_keys = request_keys - keys_allowlist
541
+ return len (unsupported_keys ) == 0
523
542
524
543
525
544
def _wait_or_cancel (
0 commit comments