google-cloud-bigquery 3.20.1__tar.gz → 3.22.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. {google-cloud-bigquery-3.20.1/google_cloud_bigquery.egg-info → google-cloud-bigquery-3.22.0}/PKG-INFO +1 -1
  2. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_helpers.py +39 -0
  3. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_job_helpers.py +5 -4
  4. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_pandas_helpers.py +33 -0
  5. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dataset.py +13 -11
  6. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/_helpers.py +8 -6
  7. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/enums.py +13 -1
  8. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/query.py +177 -60
  9. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/opentelemetry_tracing.py +8 -0
  10. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/query.py +5 -6
  11. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/retry.py +47 -5
  12. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/table.py +137 -1
  13. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/version.py +1 -1
  14. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0/google_cloud_bigquery.egg-info}/PKG-INFO +1 -1
  15. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google_cloud_bigquery.egg-info/SOURCES.txt +2 -0
  16. google-cloud-bigquery-3.22.0/tests/data/scalars.csv +2 -0
  17. google-cloud-bigquery-3.22.0/tests/data/scalars_schema_csv.json +10 -0
  18. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/conftest.py +20 -2
  19. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/helpers.py +5 -0
  20. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_arrow.py +27 -0
  21. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_list_rows.py +14 -0
  22. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_query.py +3 -3
  23. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_extract.py +9 -3
  24. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_query.py +192 -142
  25. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__helpers.py +104 -1
  26. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__job_helpers.py +25 -13
  27. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__pandas_helpers.py +61 -0
  28. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_job_retry.py +167 -5
  29. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_opentelemetry_tracing.py +6 -0
  30. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_table.py +113 -2
  31. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/LICENSE +0 -0
  32. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/MANIFEST.in +0 -0
  33. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/README.rst +0 -0
  34. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/__init__.py +0 -0
  35. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_http.py +0 -0
  36. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_pyarrow_helpers.py +0 -0
  37. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_tqdm_helpers.py +0 -0
  38. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/_versions_helpers.py +0 -0
  39. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/client.py +0 -0
  40. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/__init__.py +0 -0
  41. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/connection.py +0 -0
  42. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/cursor.py +0 -0
  43. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/exceptions.py +0 -0
  44. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/dbapi/types.py +0 -0
  45. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/encryption_configuration.py +0 -0
  46. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/exceptions.py +0 -0
  47. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/external_config.py +0 -0
  48. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/format_options.py +0 -0
  49. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/iam.py +0 -0
  50. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/__init__.py +0 -0
  51. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/base.py +0 -0
  52. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/copy_.py +0 -0
  53. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/extract.py +0 -0
  54. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/job/load.py +0 -0
  55. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/__init__.py +0 -0
  56. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/line_arg_parser/__init__.py +0 -0
  57. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/line_arg_parser/exceptions.py +0 -0
  58. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/line_arg_parser/lexer.py +0 -0
  59. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/line_arg_parser/parser.py +0 -0
  60. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/line_arg_parser/visitors.py +0 -0
  61. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/magics/magics.py +0 -0
  62. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/model.py +0 -0
  63. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/py.typed +0 -0
  64. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/routine/__init__.py +0 -0
  65. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/routine/routine.py +0 -0
  66. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/schema.py +0 -0
  67. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery/standard_sql.py +0 -0
  68. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/__init__.py +0 -0
  69. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/__init__.py +0 -0
  70. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/encryption_config.py +0 -0
  71. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/model.py +0 -0
  72. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/model_reference.py +0 -0
  73. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/standard_sql.py +0 -0
  74. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google/cloud/bigquery_v2/types/table_reference.py +0 -0
  75. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google_cloud_bigquery.egg-info/dependency_links.txt +0 -0
  76. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google_cloud_bigquery.egg-info/not-zip-safe +0 -0
  77. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google_cloud_bigquery.egg-info/requires.txt +0 -0
  78. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/google_cloud_bigquery.egg-info/top_level.txt +0 -0
  79. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/setup.cfg +0 -0
  80. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/setup.py +0 -0
  81. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/__init__.py +0 -0
  82. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/characters.json +0 -0
  83. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/characters.jsonl +0 -0
  84. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/colors.avro +0 -0
  85. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/numeric_38_12.parquet +0 -0
  86. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/people.csv +0 -0
  87. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/scalars.jsonl +0 -0
  88. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/scalars_extreme.jsonl +0 -0
  89. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/scalars_schema.json +0 -0
  90. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/data/schema.json +0 -0
  91. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/scrub_datasets.py +0 -0
  92. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/__init__.py +0 -0
  93. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_client.py +0 -0
  94. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_job_retry.py +0 -0
  95. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_magics.py +0 -0
  96. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_pandas.py +0 -0
  97. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/system/test_structs.py +0 -0
  98. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/__init__.py +0 -0
  99. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/_helpers/__init__.py +0 -0
  100. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/_helpers/test_from_json.py +0 -0
  101. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/conftest.py +0 -0
  102. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/helpers.py +0 -0
  103. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/__init__.py +0 -0
  104. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/helpers.py +0 -0
  105. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_base.py +0 -0
  106. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_copy.py +0 -0
  107. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_load.py +0 -0
  108. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_load_config.py +0 -0
  109. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_query_config.py +0 -0
  110. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_query_pandas.py +0 -0
  111. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/job/test_query_stats.py +0 -0
  112. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/line_arg_parser/__init__.py +0 -0
  113. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/line_arg_parser/test_lexer.py +0 -0
  114. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/line_arg_parser/test_parser.py +0 -0
  115. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/line_arg_parser/test_visitors.py +0 -0
  116. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/model/__init__.py +0 -0
  117. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/model/test_model.py +0 -0
  118. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/model/test_model_reference.py +0 -0
  119. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/routine/__init__.py +0 -0
  120. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/routine/test_remote_function_options.py +0 -0
  121. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/routine/test_routine.py +0 -0
  122. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/routine/test_routine_argument.py +0 -0
  123. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/routine/test_routine_reference.py +0 -0
  124. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__http.py +0 -0
  125. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__pyarrow_helpers.py +0 -0
  126. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test__versions_helpers.py +0 -0
  127. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_client.py +0 -0
  128. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_create_dataset.py +0 -0
  129. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_dataset.py +0 -0
  130. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_dbapi__helpers.py +0 -0
  131. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_dbapi_connection.py +0 -0
  132. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_dbapi_cursor.py +0 -0
  133. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_dbapi_types.py +0 -0
  134. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_delete_dataset.py +0 -0
  135. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_encryption_configuration.py +0 -0
  136. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_external_config.py +0 -0
  137. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_format_options.py +0 -0
  138. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_legacy_types.py +0 -0
  139. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_datasets.py +0 -0
  140. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_jobs.py +0 -0
  141. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_models.py +0 -0
  142. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_projects.py +0 -0
  143. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_routines.py +0 -0
  144. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_list_tables.py +0 -0
  145. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_magics.py +0 -0
  146. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_packaging.py +0 -0
  147. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_query.py +0 -0
  148. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_retry.py +0 -0
  149. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_schema.py +0 -0
  150. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_signature_compatibility.py +0 -0
  151. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_standard_sql_types.py +0 -0
  152. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_table_arrow.py +0 -0
  153. {google-cloud-bigquery-3.20.1 → google-cloud-bigquery-3.22.0}/tests/unit/test_table_pandas.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-cloud-bigquery
3
- Version: 3.20.1
3
+ Version: 3.22.0
4
4
  Summary: Google BigQuery API client library
5
5
  Home-page: https://github.com/googleapis/python-bigquery
6
6
  Author: Google LLC
@@ -66,6 +66,8 @@ _DEFAULT_UNIVERSE = "googleapis.com"
66
66
  _UNIVERSE_DOMAIN_ENV = "GOOGLE_CLOUD_UNIVERSE_DOMAIN"
67
67
  """Environment variable for setting universe domain."""
68
68
 
69
+ _SUPPORTED_RANGE_ELEMENTS = {"TIMESTAMP", "DATETIME", "DATE"}
70
+
69
71
 
70
72
  def _get_client_universe(
71
73
  client_options: Optional[Union[client_options_lib.ClientOptions, dict]]
@@ -309,6 +311,42 @@ def _json_from_json(value, field):
309
311
  return None
310
312
 
311
313
 
314
+ def _range_element_from_json(value, field):
315
+ """Coerce 'value' to a range element value."""
316
+ if value == "UNBOUNDED":
317
+ return None
318
+ if field.element_type in _SUPPORTED_RANGE_ELEMENTS:
319
+ return _CELLDATA_FROM_JSON[field.element_type](value, field.element_type)
320
+ else:
321
+ raise ValueError(f"Unsupported range element type: {field.element_type}")
322
+
323
+
324
+ def _range_from_json(value, field):
325
+ """Coerce 'value' to a range, if set or not nullable.
326
+
327
+ Args:
328
+ value (str): The literal representation of the range.
329
+ field (google.cloud.bigquery.schema.SchemaField):
330
+ The field corresponding to the value.
331
+
332
+ Returns:
333
+ Optional[dict]:
334
+ The parsed range object from ``value`` if the ``field`` is not
335
+ null (otherwise it is :data:`None`).
336
+ """
337
+ range_literal = re.compile(r"\[.*, .*\)")
338
+ if _not_null(value, field):
339
+ if range_literal.match(value):
340
+ start, end = value[1:-1].split(", ")
341
+ start = _range_element_from_json(start, field.range_element_type)
342
+ end = _range_element_from_json(end, field.range_element_type)
343
+ return {"start": start, "end": end}
344
+ else:
345
+ raise ValueError(f"Unknown format for range value: {value}")
346
+ else:
347
+ return None
348
+
349
+
312
350
  # Parse BigQuery API response JSON into a Python representation.
313
351
  _CELLDATA_FROM_JSON = {
314
352
  "INTEGER": _int_from_json,
@@ -329,6 +367,7 @@ _CELLDATA_FROM_JSON = {
329
367
  "TIME": _time_from_json,
330
368
  "RECORD": _record_from_json,
331
369
  "JSON": _json_from_json,
370
+ "RANGE": _range_from_json,
332
371
  }
333
372
 
334
373
  _QUERY_PARAMS_FROM_JSON = dict(_CELLDATA_FROM_JSON)
@@ -258,15 +258,16 @@ def _to_query_job(
258
258
  errors = query_response["errors"]
259
259
  query_job._properties["status"]["errors"] = errors
260
260
 
261
- # Transform job state so that QueryJob doesn't try to restart the query.
261
+ # Avoid an extra call to `getQueryResults` if the query has finished.
262
262
  job_complete = query_response.get("jobComplete")
263
263
  if job_complete:
264
- query_job._properties["status"]["state"] = "DONE"
265
264
  query_job._query_results = google.cloud.bigquery.query._QueryResults(
266
265
  query_response
267
266
  )
268
- else:
269
- query_job._properties["status"]["state"] = "PENDING"
267
+
268
+ # We want job.result() to refresh the job state, so the conversion is
269
+ # always "PENDING", even if the job is finished.
270
+ query_job._properties["status"]["state"] = "PENDING"
270
271
 
271
272
  return query_job
272
273
 
@@ -142,6 +142,17 @@ def bq_to_arrow_struct_data_type(field):
142
142
  return pyarrow.struct(arrow_fields)
143
143
 
144
144
 
145
+ def bq_to_arrow_range_data_type(field):
146
+ if field is None:
147
+ raise ValueError(
148
+ "Range element type cannot be None, must be one of "
149
+ "DATE, DATETIME, or TIMESTAMP"
150
+ )
151
+ element_type = field.element_type.upper()
152
+ arrow_element_type = _pyarrow_helpers.bq_to_arrow_scalars(element_type)()
153
+ return pyarrow.struct([("start", arrow_element_type), ("end", arrow_element_type)])
154
+
155
+
145
156
  def bq_to_arrow_data_type(field):
146
157
  """Return the Arrow data type, corresponding to a given BigQuery column.
147
158
 
@@ -160,6 +171,9 @@ def bq_to_arrow_data_type(field):
160
171
  if field_type_upper in schema._STRUCT_TYPES:
161
172
  return bq_to_arrow_struct_data_type(field)
162
173
 
174
+ if field_type_upper == "RANGE":
175
+ return bq_to_arrow_range_data_type(field.range_element_type)
176
+
163
177
  data_type_constructor = _pyarrow_helpers.bq_to_arrow_scalars(field_type_upper)
164
178
  if data_type_constructor is None:
165
179
  return None
@@ -220,6 +234,9 @@ def default_types_mapper(
220
234
  datetime_dtype: Union[Any, None] = None,
221
235
  time_dtype: Union[Any, None] = None,
222
236
  timestamp_dtype: Union[Any, None] = None,
237
+ range_date_dtype: Union[Any, None] = None,
238
+ range_datetime_dtype: Union[Any, None] = None,
239
+ range_timestamp_dtype: Union[Any, None] = None,
223
240
  ):
224
241
  """Create a mapping from pyarrow types to pandas types.
225
242
 
@@ -274,6 +291,22 @@ def default_types_mapper(
274
291
  elif time_dtype is not None and pyarrow.types.is_time(arrow_data_type):
275
292
  return time_dtype
276
293
 
294
+ elif pyarrow.types.is_struct(arrow_data_type):
295
+ if range_datetime_dtype is not None and arrow_data_type.equals(
296
+ range_datetime_dtype.pyarrow_dtype
297
+ ):
298
+ return range_datetime_dtype
299
+
300
+ elif range_date_dtype is not None and arrow_data_type.equals(
301
+ range_date_dtype.pyarrow_dtype
302
+ ):
303
+ return range_date_dtype
304
+
305
+ elif range_timestamp_dtype is not None and arrow_data_type.equals(
306
+ range_timestamp_dtype.pyarrow_dtype
307
+ ):
308
+ return range_timestamp_dtype
309
+
277
310
  return types_mapper
278
311
 
279
312
 
@@ -92,7 +92,7 @@ class DatasetReference(object):
92
92
  ValueError: If either argument is not of type ``str``.
93
93
  """
94
94
 
95
- def __init__(self, project, dataset_id):
95
+ def __init__(self, project: str, dataset_id: str):
96
96
  if not isinstance(project, str):
97
97
  raise ValueError("Pass a string for project")
98
98
  if not isinstance(dataset_id, str):
@@ -166,22 +166,24 @@ class DatasetReference(object):
166
166
  standard SQL format.
167
167
  """
168
168
  output_dataset_id = dataset_id
169
- output_project_id = default_project
170
169
  parts = _helpers._split_id(dataset_id)
171
170
 
172
- if len(parts) == 1 and not default_project:
173
- raise ValueError(
174
- "When default_project is not set, dataset_id must be a "
175
- "fully-qualified dataset ID in standard SQL format, "
176
- 'e.g., "project.dataset_id" got {}'.format(dataset_id)
177
- )
171
+ if len(parts) == 1:
172
+ if default_project is not None:
173
+ output_project_id = default_project
174
+ else:
175
+ raise ValueError(
176
+ "When default_project is not set, dataset_id must be a "
177
+ "fully-qualified dataset ID in standard SQL format, "
178
+ 'e.g., "project.dataset_id" got {}'.format(dataset_id)
179
+ )
178
180
  elif len(parts) == 2:
179
181
  output_project_id, output_dataset_id = parts
180
- elif len(parts) > 2:
182
+ else:
181
183
  raise ValueError(
182
184
  "Too many parts in dataset_id. Expected a fully-qualified "
183
- "dataset ID in standard SQL format. e.g. "
184
- '"project.dataset_id", got {}'.format(dataset_id)
185
+ "dataset ID in standard SQL format, "
186
+ 'e.g. "project.dataset_id", got {}'.format(dataset_id)
185
187
  )
186
188
 
187
189
  return cls(output_project_id, output_dataset_id)
@@ -277,12 +277,14 @@ def complex_query_parameter(
277
277
  param = query.ArrayQueryParameter(
278
278
  name,
279
279
  sub_type,
280
- value
281
- if isinstance(sub_type, query.ScalarQueryParameterType)
282
- else [
283
- complex_query_parameter(None, v, sub_type._complex__src, base)
284
- for v in value
285
- ],
280
+ (
281
+ value
282
+ if isinstance(sub_type, query.ScalarQueryParameterType)
283
+ else [
284
+ complex_query_parameter(None, v, sub_type._complex__src, base)
285
+ for v in value
286
+ ]
287
+ ),
286
288
  )
287
289
  elif type_type == STRUCT:
288
290
  if not isinstance(value, collections_abc.Mapping):
@@ -22,7 +22,7 @@ class AutoRowIDs(enum.Enum):
22
22
  GENERATE_UUID = enum.auto()
23
23
 
24
24
 
25
- class Compression(object):
25
+ class Compression(str, enum.Enum):
26
26
  """The compression type to use for exported files. The default value is
27
27
  :attr:`NONE`.
28
28
 
@@ -39,6 +39,9 @@ class Compression(object):
39
39
  SNAPPY = "SNAPPY"
40
40
  """Specifies SNAPPY format."""
41
41
 
42
+ ZSTD = "ZSTD"
43
+ """Specifies ZSTD format."""
44
+
42
45
  NONE = "NONE"
43
46
  """Specifies no compression."""
44
47
 
@@ -96,6 +99,15 @@ class DefaultPandasDTypes(enum.Enum):
96
99
  TIME_DTYPE = object()
97
100
  """Specifies default time dtype"""
98
101
 
102
+ RANGE_DATE_DTYPE = object()
103
+ """Specifies default range date dtype"""
104
+
105
+ RANGE_DATETIME_DTYPE = object()
106
+ """Specifies default range datetime dtype"""
107
+
108
+ RANGE_TIMESTAMP_DTYPE = object()
109
+ """Specifies default range timestamp dtype"""
110
+
99
111
 
100
112
  class DestinationFormat(object):
101
113
  """The exported file format. The default value is :attr:`CSV`.
@@ -17,11 +17,11 @@
17
17
  import concurrent.futures
18
18
  import copy
19
19
  import re
20
+ import time
20
21
  import typing
21
22
  from typing import Any, Dict, Iterable, List, Optional, Union
22
23
 
23
24
  from google.api_core import exceptions
24
- from google.api_core.future import polling as polling_future
25
25
  from google.api_core import retry as retries
26
26
  import requests
27
27
 
@@ -1383,7 +1383,7 @@ class QueryJob(_AsyncJob):
1383
1383
  def _reload_query_results(
1384
1384
  self, retry: "retries.Retry" = DEFAULT_RETRY, timeout: Optional[float] = None
1385
1385
  ):
1386
- """Refresh the cached query results.
1386
+ """Refresh the cached query results unless already cached and complete.
1387
1387
 
1388
1388
  Args:
1389
1389
  retry (Optional[google.api_core.retry.Retry]):
@@ -1392,6 +1392,8 @@ class QueryJob(_AsyncJob):
1392
1392
  The number of seconds to wait for the underlying HTTP transport
1393
1393
  before using ``retry``.
1394
1394
  """
1395
+ # Optimization: avoid a call to jobs.getQueryResults if it's already
1396
+ # been fetched, e.g. from jobs.query first page of results.
1395
1397
  if self._query_results and self._query_results.complete:
1396
1398
  return
1397
1399
 
@@ -1430,40 +1432,6 @@ class QueryJob(_AsyncJob):
1430
1432
  timeout=transport_timeout,
1431
1433
  )
1432
1434
 
1433
- def _done_or_raise(self, retry=DEFAULT_RETRY, timeout=None):
1434
- """Check if the query has finished running and raise if it's not.
1435
-
1436
- If the query has finished, also reload the job itself.
1437
- """
1438
- # If an explicit timeout is not given, fall back to the transport timeout
1439
- # stored in _blocking_poll() in the process of polling for job completion.
1440
- transport_timeout = timeout if timeout is not None else self._transport_timeout
1441
-
1442
- try:
1443
- self._reload_query_results(retry=retry, timeout=transport_timeout)
1444
- except exceptions.GoogleAPIError as exc:
1445
- # Reloading also updates error details on self, thus no need for an
1446
- # explicit self.set_exception() call if reloading succeeds.
1447
- try:
1448
- self.reload(retry=retry, timeout=transport_timeout)
1449
- except exceptions.GoogleAPIError:
1450
- # Use the query results reload exception, as it generally contains
1451
- # much more useful error information.
1452
- self.set_exception(exc)
1453
- finally:
1454
- return
1455
-
1456
- # Only reload the job once we know the query is complete.
1457
- # This will ensure that fields such as the destination table are
1458
- # correctly populated.
1459
- if not self._query_results.complete:
1460
- raise polling_future._OperationNotComplete()
1461
- else:
1462
- try:
1463
- self.reload(retry=retry, timeout=transport_timeout)
1464
- except exceptions.GoogleAPIError as exc:
1465
- self.set_exception(exc)
1466
-
1467
1435
  def result( # type: ignore # (incompatible with supertype)
1468
1436
  self,
1469
1437
  page_size: Optional[int] = None,
@@ -1528,6 +1496,10 @@ class QueryJob(_AsyncJob):
1528
1496
  If Non-``None`` and non-default ``job_retry`` is
1529
1497
  provided and the job is not retryable.
1530
1498
  """
1499
+ # Note: Since waiting for a query job to finish is more complex than
1500
+ # refreshing the job state in a loop, we avoid calling the superclass
1501
+ # in this method.
1502
+
1531
1503
  if self.dry_run:
1532
1504
  return _EmptyRowIterator(
1533
1505
  project=self.project,
@@ -1548,46 +1520,124 @@ class QueryJob(_AsyncJob):
1548
1520
  " provided to the query that created this job."
1549
1521
  )
1550
1522
 
1551
- first = True
1523
+ restart_query_job = False
1552
1524
 
1553
- def do_get_result():
1554
- nonlocal first
1525
+ def is_job_done():
1526
+ nonlocal restart_query_job
1555
1527
 
1556
- if first:
1557
- first = False
1558
- else:
1528
+ if restart_query_job:
1529
+ restart_query_job = False
1530
+
1531
+ # The original job has failed. Create a new one.
1532
+ #
1559
1533
  # Note that we won't get here if retry_do_query is
1560
1534
  # None, because we won't use a retry.
1561
-
1562
- # The orinal job is failed. Create a new one.
1563
1535
  job = retry_do_query()
1564
1536
 
1565
- # If it's already failed, we might as well stop:
1566
- if job.done() and job.exception() is not None:
1567
- raise job.exception()
1568
-
1569
1537
  # Become the new job:
1570
1538
  self.__dict__.clear()
1571
1539
  self.__dict__.update(job.__dict__)
1572
1540
 
1573
- # This shouldn't be necessary, because once we have a good
1574
- # job, it should stay good,and we shouldn't have to retry.
1575
- # But let's be paranoid. :)
1541
+ # It's possible the job fails again and we'll have to
1542
+ # retry that too.
1576
1543
  self._retry_do_query = retry_do_query
1577
1544
  self._job_retry = job_retry
1578
1545
 
1579
- super(QueryJob, self).result(retry=retry, timeout=timeout)
1580
-
1581
- # Since the job could already be "done" (e.g. got a finished job
1582
- # via client.get_job), the superclass call to done() might not
1583
- # set the self._query_results cache.
1584
- if self._query_results is None or not self._query_results.complete:
1585
- self._reload_query_results(retry=retry, timeout=timeout)
1546
+ # Refresh the job status with jobs.get because some of the
1547
+ # exceptions thrown by jobs.getQueryResults like timeout and
1548
+ # rateLimitExceeded errors are ambiguous. We want to know if
1549
+ # the query job failed and not just the call to
1550
+ # jobs.getQueryResults.
1551
+ if self.done(retry=retry, timeout=timeout):
1552
+ # If it's already failed, we might as well stop.
1553
+ job_failed_exception = self.exception()
1554
+ if job_failed_exception is not None:
1555
+ # Only try to restart the query job if the job failed for
1556
+ # a retriable reason. For example, don't restart the query
1557
+ # if the call to reload the job metadata within self.done()
1558
+ # timed out.
1559
+ #
1560
+ # The `restart_query_job` must only be called after a
1561
+ # successful call to the `jobs.get` REST API and we
1562
+ # determine that the job has failed.
1563
+ #
1564
+ # The `jobs.get` REST API
1565
+ # (https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/get)
1566
+ # is called via `self.done()` which calls
1567
+ # `self.reload()`.
1568
+ #
1569
+ # To determine if the job failed, the `self.exception()`
1570
+ # is set from `self.reload()` via
1571
+ # `self._set_properties()`, which translates the
1572
+ # `Job.status.errorResult` field
1573
+ # (https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#JobStatus.FIELDS.error_result)
1574
+ # into an exception that can be processed by the
1575
+ # `job_retry` predicate.
1576
+ restart_query_job = True
1577
+ raise job_failed_exception
1578
+ else:
1579
+ # Make sure that the _query_results are cached so we
1580
+ # can return a complete RowIterator.
1581
+ #
1582
+ # Note: As an optimization, _reload_query_results
1583
+ # doesn't make any API calls if the query results are
1584
+ # already cached and have jobComplete=True in the
1585
+ # response from the REST API. This ensures we aren't
1586
+ # making any extra API calls if the previous loop
1587
+ # iteration fetched the finished job.
1588
+ self._reload_query_results(retry=retry, timeout=timeout)
1589
+ return True
1590
+
1591
+ # Call jobs.getQueryResults with max results set to 0 just to
1592
+ # wait for the query to finish. Unlike most methods,
1593
+ # jobs.getQueryResults hangs as long as it can to ensure we
1594
+ # know when the query has finished as soon as possible.
1595
+ self._reload_query_results(retry=retry, timeout=timeout)
1596
+
1597
+ # Even if the query is finished now according to
1598
+ # jobs.getQueryResults, we'll want to reload the job status if
1599
+ # it's not already DONE.
1600
+ return False
1586
1601
 
1587
1602
  if retry_do_query is not None and job_retry is not None:
1588
- do_get_result = job_retry(do_get_result)
1603
+ is_job_done = job_retry(is_job_done)
1604
+
1605
+ # timeout can be a number of seconds, `None`, or a
1606
+ # `google.api_core.future.polling.PollingFuture._DEFAULT_VALUE`
1607
+ # sentinel object indicating a default timeout if we choose to add
1608
+ # one some day. This value can come from our PollingFuture
1609
+ # superclass and was introduced in
1610
+ # https://github.com/googleapis/python-api-core/pull/462.
1611
+ if isinstance(timeout, (float, int)):
1612
+ remaining_timeout = timeout
1613
+ else:
1614
+ # Note: we may need to handle _DEFAULT_VALUE as a separate
1615
+ # case someday, but even then the best we can do for queries
1616
+ # is 72+ hours for hyperparameter tuning jobs:
1617
+ # https://cloud.google.com/bigquery/quotas#query_jobs
1618
+ #
1619
+ # The timeout for a multi-statement query is 24+ hours. See:
1620
+ # https://cloud.google.com/bigquery/quotas#multi_statement_query_limits
1621
+ remaining_timeout = None
1622
+
1623
+ if remaining_timeout is None:
1624
+ # Since is_job_done() calls jobs.getQueryResults, which is a
1625
+ # long-running API, don't delay the next request at all.
1626
+ while not is_job_done():
1627
+ pass
1628
+ else:
1629
+ # Use a monotonic clock since we don't actually care about
1630
+ # daylight savings or similar, just the elapsed time.
1631
+ previous_time = time.monotonic()
1589
1632
 
1590
- do_get_result()
1633
+ while not is_job_done():
1634
+ current_time = time.monotonic()
1635
+ elapsed_time = current_time - previous_time
1636
+ remaining_timeout = remaining_timeout - elapsed_time
1637
+ previous_time = current_time
1638
+
1639
+ if remaining_timeout < 0:
1640
+ raise concurrent.futures.TimeoutError()
1591
1641
 
1592
1642
  except exceptions.GoogleAPICallError as exc:
1593
1643
  exc.message = _EXCEPTION_FOOTER_TEMPLATE.format(
@@ -1734,6 +1784,13 @@ class QueryJob(_AsyncJob):
1734
1784
  datetime_dtype: Union[Any, None] = None,
1735
1785
  time_dtype: Union[Any, None] = DefaultPandasDTypes.TIME_DTYPE,
1736
1786
  timestamp_dtype: Union[Any, None] = None,
1787
+ range_date_dtype: Union[Any, None] = DefaultPandasDTypes.RANGE_DATE_DTYPE,
1788
+ range_datetime_dtype: Union[
1789
+ Any, None
1790
+ ] = DefaultPandasDTypes.RANGE_DATETIME_DTYPE,
1791
+ range_timestamp_dtype: Union[
1792
+ Any, None
1793
+ ] = DefaultPandasDTypes.RANGE_TIMESTAMP_DTYPE,
1737
1794
  ) -> "pandas.DataFrame":
1738
1795
  """Return a pandas DataFrame from a QueryJob
1739
1796
 
@@ -1869,6 +1926,63 @@ class QueryJob(_AsyncJob):
1869
1926
 
1870
1927
  .. versionadded:: 3.10.0
1871
1928
 
1929
+ range_date_dtype (Optional[pandas.Series.dtype, None]):
1930
+ If set, indicate a pandas ExtensionDtype, such as:
1931
+
1932
+ .. code-block:: python
1933
+
1934
+ pandas.ArrowDtype(pyarrow.struct(
1935
+ [("start", pyarrow.date32()), ("end", pyarrow.date32())]
1936
+ ))
1937
+
1938
+ to convert BigQuery RANGE<DATE> type, instead of relying on
1939
+ the default ``object``. If you explicitly set the value to
1940
+ ``None``, the data type will be ``object``. BigQuery Range type
1941
+ can be found at:
1942
+ https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#range_type
1943
+
1944
+ .. versionadded:: 3.21.0
1945
+
1946
+ range_datetime_dtype (Optional[pandas.Series.dtype, None]):
1947
+ If set, indicate a pandas ExtensionDtype, such as:
1948
+
1949
+ .. code-block:: python
1950
+
1951
+ pandas.ArrowDtype(pyarrow.struct(
1952
+ [
1953
+ ("start", pyarrow.timestamp("us")),
1954
+ ("end", pyarrow.timestamp("us")),
1955
+ ]
1956
+ ))
1957
+
1958
+ to convert BigQuery RANGE<DATETIME> type, instead of relying on
1959
+ the default ``object``. If you explicitly set the value to
1960
+ ``None``, the data type will be ``object``. BigQuery Range type
1961
+ can be found at:
1962
+ https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#range_type
1963
+
1964
+ .. versionadded:: 3.21.0
1965
+
1966
+ range_timestamp_dtype (Optional[pandas.Series.dtype, None]):
1967
+ If set, indicate a pandas ExtensionDtype, such as:
1968
+
1969
+ .. code-block:: python
1970
+
1971
+ pandas.ArrowDtype(pyarrow.struct(
1972
+ [
1973
+ ("start", pyarrow.timestamp("us", tz="UTC")),
1974
+ ("end", pyarrow.timestamp("us", tz="UTC")),
1975
+ ]
1976
+ ))
1977
+
1978
+ to convert BigQuery RANGE<TIMESTAMP> type, instead of relying
1979
+ on the default ``object``. If you explicitly set the value to
1980
+ ``None``, the data type will be ``object``. BigQuery Range type
1981
+ can be found at:
1982
+ https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#range_type
1983
+
1984
+ .. versionadded:: 3.21.0
1985
+
1872
1986
  Returns:
1873
1987
  pandas.DataFrame:
1874
1988
  A :class:`~pandas.DataFrame` populated with row data
@@ -1899,6 +2013,9 @@ class QueryJob(_AsyncJob):
1899
2013
  datetime_dtype=datetime_dtype,
1900
2014
  time_dtype=time_dtype,
1901
2015
  timestamp_dtype=timestamp_dtype,
2016
+ range_date_dtype=range_date_dtype,
2017
+ range_datetime_dtype=range_datetime_dtype,
2018
+ range_timestamp_dtype=range_timestamp_dtype,
1902
2019
  )
1903
2020
 
1904
2021
  # If changing the signature of this method, make sure to apply the same
@@ -153,4 +153,12 @@ def _set_job_attributes(job_ref):
153
153
  if job_ref.num_child_jobs is not None:
154
154
  job_attributes["num_child_jobs"] = job_ref.num_child_jobs
155
155
 
156
+ total_bytes_billed = getattr(job_ref, "total_bytes_billed", None)
157
+ if total_bytes_billed is not None:
158
+ job_attributes["total_bytes_billed"] = total_bytes_billed
159
+
160
+ total_bytes_processed = getattr(job_ref, "total_bytes_processed", None)
161
+ if total_bytes_processed is not None:
162
+ job_attributes["total_bytes_processed"] = total_bytes_processed
163
+
156
164
  return job_attributes
@@ -24,14 +24,13 @@ from google.cloud.bigquery.table import _parse_schema_resource
24
24
  from google.cloud.bigquery._helpers import _rows_from_json
25
25
  from google.cloud.bigquery._helpers import _QUERY_PARAMS_FROM_JSON
26
26
  from google.cloud.bigquery._helpers import _SCALAR_VALUE_TO_JSON_PARAM
27
+ from google.cloud.bigquery._helpers import _SUPPORTED_RANGE_ELEMENTS
27
28
 
28
29
 
29
30
  _SCALAR_VALUE_TYPE = Optional[
30
31
  Union[str, int, float, decimal.Decimal, bool, datetime.datetime, datetime.date]
31
32
  ]
32
33
 
33
- _RANGE_ELEMENT_TYPE_STR = {"TIMESTAMP", "DATETIME", "DATE"}
34
-
35
34
 
36
35
  class ConnectionProperty:
37
36
  """A connection-level property to customize query behavior.
@@ -388,14 +387,14 @@ class RangeQueryParameterType(_AbstractQueryParameterType):
388
387
  google.cloud.bigquery.query.ScalarQueryParameterType: Instance
389
388
  """
390
389
  if isinstance(type_, str):
391
- if type_ not in _RANGE_ELEMENT_TYPE_STR:
390
+ if type_ not in _SUPPORTED_RANGE_ELEMENTS:
392
391
  raise ValueError(
393
392
  "If given as a string, range element type must be one of "
394
393
  "'TIMESTAMP', 'DATE', or 'DATETIME'."
395
394
  )
396
395
  return ScalarQueryParameterType(type_)
397
396
  elif isinstance(type_, ScalarQueryParameterType):
398
- if type_._type not in _RANGE_ELEMENT_TYPE_STR:
397
+ if type_._type not in _SUPPORTED_RANGE_ELEMENTS:
399
398
  raise ValueError(
400
399
  "If given as a ScalarQueryParameter object, range element "
401
400
  "type must be one of 'TIMESTAMP', 'DATE', or 'DATETIME' "
@@ -960,14 +959,14 @@ class RangeQueryParameter(_AbstractQueryParameter):
960
959
  @classmethod
961
960
  def _parse_range_element_type(self, range_element_type):
962
961
  if isinstance(range_element_type, str):
963
- if range_element_type not in _RANGE_ELEMENT_TYPE_STR:
962
+ if range_element_type not in _SUPPORTED_RANGE_ELEMENTS:
964
963
  raise ValueError(
965
964
  "If given as a string, range_element_type must be one of "
966
965
  f"'TIMESTAMP', 'DATE', or 'DATETIME'. Got {range_element_type}."
967
966
  )
968
967
  return RangeQueryParameterType(range_element_type)
969
968
  elif isinstance(range_element_type, RangeQueryParameterType):
970
- if range_element_type.type_._type not in _RANGE_ELEMENT_TYPE_STR:
969
+ if range_element_type.type_._type not in _SUPPORTED_RANGE_ELEMENTS:
971
970
  raise ValueError(
972
971
  "If given as a RangeQueryParameterType object, "
973
972
  "range_element_type must be one of 'TIMESTAMP', 'DATE', "