google-cloud-bigquery 3.35.1__tar.gz → 3.37.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 (161) hide show
  1. {google_cloud_bigquery-3.35.1/google_cloud_bigquery.egg-info → google_cloud_bigquery-3.37.0}/PKG-INFO +2 -2
  2. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/README.rst +1 -1
  3. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_job_helpers.py +161 -6
  4. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/client.py +52 -3
  5. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/base.py +50 -3
  6. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/query.py +9 -0
  7. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/query.py +60 -3
  8. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/retry.py +2 -0
  9. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/table.py +34 -6
  10. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/version.py +1 -1
  11. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0/google_cloud_bigquery.egg-info}/PKG-INFO +2 -2
  12. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google_cloud_bigquery.egg-info/SOURCES.txt +6 -0
  13. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/conftest.py +13 -0
  14. google_cloud_bigquery-3.37.0/tests/unit/job/test_async_job_retry.py +139 -0
  15. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_base.py +41 -104
  16. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_query.py +6 -196
  17. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_query_config.py +5 -0
  18. google_cloud_bigquery-3.37.0/tests/unit/job/test_query_job_retry.py +229 -0
  19. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__job_helpers.py +28 -105
  20. google_cloud_bigquery-3.37.0/tests/unit/test__job_helpers_retry.py +122 -0
  21. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_client.py +6 -587
  22. google_cloud_bigquery-3.37.0/tests/unit/test_client_bigframes.py +411 -0
  23. google_cloud_bigquery-3.37.0/tests/unit/test_client_resumable_media_upload.py +433 -0
  24. google_cloud_bigquery-3.37.0/tests/unit/test_client_retry.py +279 -0
  25. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_job_retry.py +10 -8
  26. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_query.py +48 -0
  27. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_table.py +68 -76
  28. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/LICENSE +0 -0
  29. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/MANIFEST.in +0 -0
  30. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/__init__.py +0 -0
  31. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_helpers.py +0 -0
  32. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_http.py +0 -0
  33. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_pandas_helpers.py +0 -0
  34. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_pyarrow_helpers.py +0 -0
  35. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_tqdm_helpers.py +0 -0
  36. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/_versions_helpers.py +0 -0
  37. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dataset.py +0 -0
  38. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/__init__.py +0 -0
  39. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/_helpers.py +0 -0
  40. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/connection.py +0 -0
  41. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/cursor.py +0 -0
  42. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/exceptions.py +0 -0
  43. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/dbapi/types.py +0 -0
  44. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/encryption_configuration.py +0 -0
  45. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/enums.py +0 -0
  46. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/exceptions.py +0 -0
  47. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/external_config.py +0 -0
  48. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/format_options.py +0 -0
  49. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/iam.py +0 -0
  50. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/__init__.py +0 -0
  51. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/copy_.py +0 -0
  52. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/extract.py +0 -0
  53. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/job/load.py +0 -0
  54. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/__init__.py +0 -0
  55. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/line_arg_parser/__init__.py +0 -0
  56. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/line_arg_parser/exceptions.py +0 -0
  57. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/line_arg_parser/lexer.py +0 -0
  58. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/line_arg_parser/parser.py +0 -0
  59. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/line_arg_parser/visitors.py +0 -0
  60. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/magics/magics.py +0 -0
  61. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/model.py +0 -0
  62. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/opentelemetry_tracing.py +0 -0
  63. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/py.typed +0 -0
  64. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/routine/__init__.py +0 -0
  65. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/routine/routine.py +0 -0
  66. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/schema.py +0 -0
  67. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery/standard_sql.py +0 -0
  68. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/__init__.py +0 -0
  69. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/__init__.py +0 -0
  70. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/encryption_config.py +0 -0
  71. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/model.py +0 -0
  72. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/model_reference.py +0 -0
  73. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/standard_sql.py +0 -0
  74. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google/cloud/bigquery_v2/types/table_reference.py +0 -0
  75. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google_cloud_bigquery.egg-info/dependency_links.txt +0 -0
  76. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google_cloud_bigquery.egg-info/requires.txt +0 -0
  77. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/google_cloud_bigquery.egg-info/top_level.txt +0 -0
  78. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/pyproject.toml +0 -0
  79. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/setup.cfg +0 -0
  80. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/setup.py +0 -0
  81. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/__init__.py +0 -0
  82. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/characters.json +0 -0
  83. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/characters.jsonl +0 -0
  84. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/colors.avro +0 -0
  85. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/numeric_38_12.parquet +0 -0
  86. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/people.csv +0 -0
  87. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/scalars.csv +0 -0
  88. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/scalars.jsonl +0 -0
  89. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/scalars_extreme.jsonl +0 -0
  90. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/scalars_schema.json +0 -0
  91. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/scalars_schema_csv.json +0 -0
  92. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/data/schema.json +0 -0
  93. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/scrub_datasets.py +0 -0
  94. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/__init__.py +0 -0
  95. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/conftest.py +0 -0
  96. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/helpers.py +0 -0
  97. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_arrow.py +0 -0
  98. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_client.py +0 -0
  99. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_job_retry.py +0 -0
  100. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_list_rows.py +0 -0
  101. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_magics.py +0 -0
  102. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_pandas.py +0 -0
  103. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_query.py +0 -0
  104. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/system/test_structs.py +0 -0
  105. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/__init__.py +0 -0
  106. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/_helpers/__init__.py +0 -0
  107. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/_helpers/test_cell_data_parser.py +0 -0
  108. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/_helpers/test_data_frame_cell_data_parser.py +0 -0
  109. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/_helpers/test_scalar_query_param_parser.py +0 -0
  110. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/helpers.py +0 -0
  111. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/__init__.py +0 -0
  112. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/helpers.py +0 -0
  113. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_copy.py +0 -0
  114. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_extract.py +0 -0
  115. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_load.py +0 -0
  116. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_load_config.py +0 -0
  117. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_query_pandas.py +0 -0
  118. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/job/test_query_stats.py +0 -0
  119. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/line_arg_parser/__init__.py +0 -0
  120. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/line_arg_parser/test_lexer.py +0 -0
  121. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/line_arg_parser/test_parser.py +0 -0
  122. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/line_arg_parser/test_visitors.py +0 -0
  123. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/model/__init__.py +0 -0
  124. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/model/test_model.py +0 -0
  125. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/model/test_model_reference.py +0 -0
  126. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/routine/__init__.py +0 -0
  127. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/routine/test_remote_function_options.py +0 -0
  128. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/routine/test_routine.py +0 -0
  129. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/routine/test_routine_argument.py +0 -0
  130. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/routine/test_routine_reference.py +0 -0
  131. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__helpers.py +0 -0
  132. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__http.py +0 -0
  133. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__pandas_helpers.py +0 -0
  134. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__pyarrow_helpers.py +0 -0
  135. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test__versions_helpers.py +0 -0
  136. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_create_dataset.py +0 -0
  137. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_dataset.py +0 -0
  138. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_dbapi__helpers.py +0 -0
  139. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_dbapi_connection.py +0 -0
  140. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_dbapi_cursor.py +0 -0
  141. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_dbapi_types.py +0 -0
  142. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_delete_dataset.py +0 -0
  143. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_encryption_configuration.py +0 -0
  144. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_external_config.py +0 -0
  145. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_format_options.py +0 -0
  146. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_legacy_types.py +0 -0
  147. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_datasets.py +0 -0
  148. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_jobs.py +0 -0
  149. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_models.py +0 -0
  150. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_projects.py +0 -0
  151. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_routines.py +0 -0
  152. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_list_tables.py +0 -0
  153. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_magics.py +0 -0
  154. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_opentelemetry_tracing.py +0 -0
  155. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_packaging.py +0 -0
  156. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_retry.py +0 -0
  157. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_schema.py +0 -0
  158. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_signature_compatibility.py +0 -0
  159. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_standard_sql_types.py +0 -0
  160. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_table_arrow.py +0 -0
  161. {google_cloud_bigquery-3.35.1 → google_cloud_bigquery-3.37.0}/tests/unit/test_table_pandas.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-bigquery
3
- Version: 3.35.1
3
+ Version: 3.37.0
4
4
  Summary: Google BigQuery API client library
5
5
  Author-email: Google LLC <googleapis-packages@google.com>
6
6
  License: Apache 2.0
@@ -84,7 +84,7 @@ processing power of Google's infrastructure.
84
84
  .. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-bigquery.svg
85
85
  :target: https://pypi.org/project/google-cloud-bigquery/
86
86
  .. _BigQuery: https://cloud.google.com/bigquery/what-is-bigquery
87
- .. _Client Library Documentation: https://googleapis.dev/python/bigquery/latest
87
+ .. _Client Library Documentation: https://cloud.google.com/python/docs/reference/bigquery/latest/summary_overview
88
88
  .. _Product Documentation: https://cloud.google.com/bigquery/docs/reference/v2/
89
89
 
90
90
  Quick Start
@@ -18,7 +18,7 @@ processing power of Google's infrastructure.
18
18
  .. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-bigquery.svg
19
19
  :target: https://pypi.org/project/google-cloud-bigquery/
20
20
  .. _BigQuery: https://cloud.google.com/bigquery/what-is-bigquery
21
- .. _Client Library Documentation: https://googleapis.dev/python/bigquery/latest
21
+ .. _Client Library Documentation: https://cloud.google.com/python/docs/reference/bigquery/latest/summary_overview
22
22
  .. _Product Documentation: https://cloud.google.com/bigquery/docs/reference/v2/
23
23
 
24
24
  Quick Start
@@ -35,17 +35,22 @@ we still need a separate job_retry object because there are different
35
35
  predicates where it is safe to generate a new query ID.
36
36
  """
37
37
 
38
+ from __future__ import annotations
39
+
38
40
  import copy
41
+ import dataclasses
42
+ import datetime
39
43
  import functools
40
44
  import uuid
41
45
  import textwrap
42
- from typing import Any, Dict, Optional, TYPE_CHECKING, Union
46
+ from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union
43
47
  import warnings
44
48
 
45
49
  import google.api_core.exceptions as core_exceptions
46
50
  from google.api_core import retry as retries
47
51
 
48
52
  from google.cloud.bigquery import job
53
+ import google.cloud.bigquery.job.query
49
54
  import google.cloud.bigquery.query
50
55
  from google.cloud.bigquery import table
51
56
  import google.cloud.bigquery.retry
@@ -116,14 +121,21 @@ def query_jobs_insert(
116
121
  retry: Optional[retries.Retry],
117
122
  timeout: Optional[float],
118
123
  job_retry: Optional[retries.Retry],
124
+ *,
125
+ callback: Callable = lambda _: None,
119
126
  ) -> job.QueryJob:
120
127
  """Initiate a query using jobs.insert.
121
128
 
122
129
  See: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/insert
130
+
131
+ Args:
132
+ callback (Callable):
133
+ A callback function used by bigframes to report query progress.
123
134
  """
124
135
  job_id_given = job_id is not None
125
136
  job_id_save = job_id
126
137
  job_config_save = job_config
138
+ query_sent_factory = QuerySentEventFactory()
127
139
 
128
140
  def do_query():
129
141
  # Make a copy now, so that original doesn't get changed by the process
@@ -136,6 +148,16 @@ def query_jobs_insert(
136
148
 
137
149
  try:
138
150
  query_job._begin(retry=retry, timeout=timeout)
151
+ if job_config is not None and not job_config.dry_run:
152
+ callback(
153
+ query_sent_factory(
154
+ query=query,
155
+ billing_project=query_job.project,
156
+ location=query_job.location,
157
+ job_id=query_job.job_id,
158
+ request_id=None,
159
+ )
160
+ )
139
161
  except core_exceptions.Conflict as create_exc:
140
162
  # The thought is if someone is providing their own job IDs and they get
141
163
  # their job ID generation wrong, this could end up returning results for
@@ -396,6 +418,7 @@ def query_and_wait(
396
418
  job_retry: Optional[retries.Retry],
397
419
  page_size: Optional[int] = None,
398
420
  max_results: Optional[int] = None,
421
+ callback: Callable = lambda _: None,
399
422
  ) -> table.RowIterator:
400
423
  """Run the query, wait for it to finish, and return the results.
401
424
 
@@ -415,9 +438,8 @@ def query_and_wait(
415
438
  location (Optional[str]):
416
439
  Location where to run the job. Must match the location of the
417
440
  table used in the query as well as the destination table.
418
- project (Optional[str]):
419
- Project ID of the project of where to run the job. Defaults
420
- to the client's project.
441
+ project (str):
442
+ Project ID of the project of where to run the job.
421
443
  api_timeout (Optional[float]):
422
444
  The number of seconds to wait for the underlying HTTP transport
423
445
  before using ``retry``.
@@ -441,6 +463,8 @@ def query_and_wait(
441
463
  request. Non-positive values are ignored.
442
464
  max_results (Optional[int]):
443
465
  The maximum total number of rows from this request.
466
+ callback (Callable):
467
+ A callback function used by bigframes to report query progress.
444
468
 
445
469
  Returns:
446
470
  google.cloud.bigquery.table.RowIterator:
@@ -479,12 +503,14 @@ def query_and_wait(
479
503
  retry=retry,
480
504
  timeout=api_timeout,
481
505
  job_retry=job_retry,
506
+ callback=callback,
482
507
  ),
483
508
  api_timeout=api_timeout,
484
509
  wait_timeout=wait_timeout,
485
510
  retry=retry,
486
511
  page_size=page_size,
487
512
  max_results=max_results,
513
+ callback=callback,
488
514
  )
489
515
 
490
516
  path = _to_query_path(project)
@@ -496,10 +522,24 @@ def query_and_wait(
496
522
  if client.default_job_creation_mode:
497
523
  request_body["jobCreationMode"] = client.default_job_creation_mode
498
524
 
525
+ query_sent_factory = QuerySentEventFactory()
526
+
499
527
  def do_query():
500
- request_body["requestId"] = make_job_id()
528
+ request_id = make_job_id()
529
+ request_body["requestId"] = request_id
501
530
  span_attributes = {"path": path}
502
531
 
532
+ if "dryRun" not in request_body:
533
+ callback(
534
+ query_sent_factory(
535
+ query=query,
536
+ billing_project=project,
537
+ location=location,
538
+ job_id=None,
539
+ request_id=request_id,
540
+ )
541
+ )
542
+
503
543
  # For easier testing, handle the retries ourselves.
504
544
  if retry is not None:
505
545
  response = retry(client._call_api)(
@@ -542,8 +582,25 @@ def query_and_wait(
542
582
  retry=retry,
543
583
  page_size=page_size,
544
584
  max_results=max_results,
585
+ callback=callback,
545
586
  )
546
587
 
588
+ if "dryRun" not in request_body:
589
+ callback(
590
+ QueryFinishedEvent(
591
+ billing_project=project,
592
+ location=query_results.location,
593
+ query_id=query_results.query_id,
594
+ job_id=query_results.job_id,
595
+ total_rows=query_results.total_rows,
596
+ total_bytes_processed=query_results.total_bytes_processed,
597
+ slot_millis=query_results.slot_millis,
598
+ destination=None,
599
+ created=query_results.created,
600
+ started=query_results.started,
601
+ ended=query_results.ended,
602
+ )
603
+ )
547
604
  return table.RowIterator(
548
605
  client=client,
549
606
  api_request=functools.partial(client._call_api, retry, timeout=api_timeout),
@@ -561,6 +618,9 @@ def query_and_wait(
561
618
  query=query,
562
619
  total_bytes_processed=query_results.total_bytes_processed,
563
620
  slot_millis=query_results.slot_millis,
621
+ created=query_results.created,
622
+ started=query_results.started,
623
+ ended=query_results.ended,
564
624
  )
565
625
 
566
626
  if job_retry is not None:
@@ -598,6 +658,9 @@ def _supported_by_jobs_query(request_body: Dict[str, Any]) -> bool:
598
658
  "requestId",
599
659
  "createSession",
600
660
  "writeIncrementalResults",
661
+ "jobTimeoutMs",
662
+ "reservation",
663
+ "maxSlots",
601
664
  }
602
665
 
603
666
  unsupported_keys = request_keys - keys_allowlist
@@ -611,6 +674,8 @@ def _wait_or_cancel(
611
674
  retry: Optional[retries.Retry],
612
675
  page_size: Optional[int],
613
676
  max_results: Optional[int],
677
+ *,
678
+ callback: Callable = lambda _: None,
614
679
  ) -> table.RowIterator:
615
680
  """Wait for a job to complete and return the results.
616
681
 
@@ -618,12 +683,43 @@ def _wait_or_cancel(
618
683
  the job.
619
684
  """
620
685
  try:
621
- return job.result(
686
+ if not job.dry_run:
687
+ callback(
688
+ QueryReceivedEvent(
689
+ billing_project=job.project,
690
+ location=job.location,
691
+ job_id=job.job_id,
692
+ statement_type=job.statement_type,
693
+ state=job.state,
694
+ query_plan=job.query_plan,
695
+ created=job.created,
696
+ started=job.started,
697
+ ended=job.ended,
698
+ )
699
+ )
700
+ query_results = job.result(
622
701
  page_size=page_size,
623
702
  max_results=max_results,
624
703
  retry=retry,
625
704
  timeout=wait_timeout,
626
705
  )
706
+ if not job.dry_run:
707
+ callback(
708
+ QueryFinishedEvent(
709
+ billing_project=job.project,
710
+ location=query_results.location,
711
+ query_id=query_results.query_id,
712
+ job_id=query_results.job_id,
713
+ total_rows=query_results.total_rows,
714
+ total_bytes_processed=query_results.total_bytes_processed,
715
+ slot_millis=query_results.slot_millis,
716
+ destination=job.destination,
717
+ created=job.created,
718
+ started=job.started,
719
+ ended=job.ended,
720
+ )
721
+ )
722
+ return query_results
627
723
  except Exception:
628
724
  # Attempt to cancel the job since we can't return the results.
629
725
  try:
@@ -632,3 +728,62 @@ def _wait_or_cancel(
632
728
  # Don't eat the original exception if cancel fails.
633
729
  pass
634
730
  raise
731
+
732
+
733
+ @dataclasses.dataclass(frozen=True)
734
+ class QueryFinishedEvent:
735
+ """Query finished successfully."""
736
+
737
+ billing_project: Optional[str]
738
+ location: Optional[str]
739
+ query_id: Optional[str]
740
+ job_id: Optional[str]
741
+ destination: Optional[table.TableReference]
742
+ total_rows: Optional[int]
743
+ total_bytes_processed: Optional[int]
744
+ slot_millis: Optional[int]
745
+ created: Optional[datetime.datetime]
746
+ started: Optional[datetime.datetime]
747
+ ended: Optional[datetime.datetime]
748
+
749
+
750
+ @dataclasses.dataclass(frozen=True)
751
+ class QueryReceivedEvent:
752
+ """Query received and acknowledged by the BigQuery API."""
753
+
754
+ billing_project: Optional[str]
755
+ location: Optional[str]
756
+ job_id: Optional[str]
757
+ statement_type: Optional[str]
758
+ state: Optional[str]
759
+ query_plan: Optional[list[google.cloud.bigquery.job.query.QueryPlanEntry]]
760
+ created: Optional[datetime.datetime]
761
+ started: Optional[datetime.datetime]
762
+ ended: Optional[datetime.datetime]
763
+
764
+
765
+ @dataclasses.dataclass(frozen=True)
766
+ class QuerySentEvent:
767
+ """Query sent to BigQuery."""
768
+
769
+ query: str
770
+ billing_project: Optional[str]
771
+ location: Optional[str]
772
+ job_id: Optional[str]
773
+ request_id: Optional[str]
774
+
775
+
776
+ class QueryRetryEvent(QuerySentEvent):
777
+ """Query sent another time because the previous attempt failed."""
778
+
779
+
780
+ class QuerySentEventFactory:
781
+ """Creates a QuerySentEvent first, then QueryRetryEvent after that."""
782
+
783
+ def __init__(self):
784
+ self._event_constructor = QuerySentEvent
785
+
786
+ def __call__(self, **kwargs):
787
+ result = self._event_constructor(**kwargs)
788
+ self._event_constructor = QueryRetryEvent
789
+ return result
@@ -15,6 +15,7 @@
15
15
  """Client for interacting with the Google BigQuery API."""
16
16
 
17
17
  from __future__ import absolute_import
18
+ from __future__ import annotations
18
19
  from __future__ import division
19
20
 
20
21
  from collections import abc as collections_abc
@@ -31,6 +32,7 @@ import tempfile
31
32
  import typing
32
33
  from typing import (
33
34
  Any,
35
+ Callable,
34
36
  Dict,
35
37
  IO,
36
38
  Iterable,
@@ -3517,7 +3519,8 @@ class Client(ClientWithProject):
3517
3519
  specified here becomes the default ``job_retry`` for
3518
3520
  ``result()``, where it can also be specified.
3519
3521
  api_method (Union[str, enums.QueryApiMethod]):
3520
- Method with which to start the query job.
3522
+ Method with which to start the query job. By default,
3523
+ the jobs.insert API is used for starting a query.
3521
3524
 
3522
3525
  See :class:`google.cloud.bigquery.enums.QueryApiMethod` for
3523
3526
  details on the difference between the query start methods.
@@ -3633,8 +3636,8 @@ class Client(ClientWithProject):
3633
3636
  rate-limit-exceeded errors. Passing ``None`` disables
3634
3637
  job retry. Not all jobs can be retried.
3635
3638
  page_size (Optional[int]):
3636
- The maximum number of rows in each page of results from this
3637
- request. Non-positive values are ignored.
3639
+ The maximum number of rows in each page of results from the
3640
+ initial jobs.query request. Non-positive values are ignored.
3638
3641
  max_results (Optional[int]):
3639
3642
  The maximum total number of rows from this request.
3640
3643
 
@@ -3656,6 +3659,39 @@ class Client(ClientWithProject):
3656
3659
  :class:`~google.cloud.bigquery.job.QueryJobConfig`
3657
3660
  class.
3658
3661
  """
3662
+ return self._query_and_wait_bigframes(
3663
+ query,
3664
+ job_config=job_config,
3665
+ location=location,
3666
+ project=project,
3667
+ api_timeout=api_timeout,
3668
+ wait_timeout=wait_timeout,
3669
+ retry=retry,
3670
+ job_retry=job_retry,
3671
+ page_size=page_size,
3672
+ max_results=max_results,
3673
+ )
3674
+
3675
+ def _query_and_wait_bigframes(
3676
+ self,
3677
+ query,
3678
+ *,
3679
+ job_config: Optional[QueryJobConfig] = None,
3680
+ location: Optional[str] = None,
3681
+ project: Optional[str] = None,
3682
+ api_timeout: TimeoutType = DEFAULT_TIMEOUT,
3683
+ wait_timeout: Union[Optional[float], object] = POLLING_DEFAULT_VALUE,
3684
+ retry: retries.Retry = DEFAULT_RETRY,
3685
+ job_retry: retries.Retry = DEFAULT_JOB_RETRY,
3686
+ page_size: Optional[int] = None,
3687
+ max_results: Optional[int] = None,
3688
+ callback: Callable = lambda _: None,
3689
+ ) -> RowIterator:
3690
+ """See query_and_wait.
3691
+
3692
+ This method has an extra callback parameter, which is used by bigframes
3693
+ to create better progress bars.
3694
+ """
3659
3695
  if project is None:
3660
3696
  project = self.project
3661
3697
 
@@ -3681,6 +3717,7 @@ class Client(ClientWithProject):
3681
3717
  job_retry=job_retry,
3682
3718
  page_size=page_size,
3683
3719
  max_results=max_results,
3720
+ callback=callback,
3684
3721
  )
3685
3722
 
3686
3723
  def insert_rows(
@@ -4145,6 +4182,9 @@ class Client(ClientWithProject):
4145
4182
  query: Optional[str] = None,
4146
4183
  total_bytes_processed: Optional[int] = None,
4147
4184
  slot_millis: Optional[int] = None,
4185
+ created: Optional[datetime.datetime] = None,
4186
+ started: Optional[datetime.datetime] = None,
4187
+ ended: Optional[datetime.datetime] = None,
4148
4188
  ) -> RowIterator:
4149
4189
  """List the rows of a completed query.
4150
4190
  See
@@ -4198,6 +4238,12 @@ class Client(ClientWithProject):
4198
4238
  total bytes processed from job statistics, if present.
4199
4239
  slot_millis (Optional[int]):
4200
4240
  Number of slot ms the user is actually billed for.
4241
+ created (Optional[datetime.datetime]):
4242
+ Datetime at which the job was created.
4243
+ started (Optional[datetime.datetime]):
4244
+ Datetime at which the job was started.
4245
+ ended (Optional[datetime.datetime]):
4246
+ Datetime at which the job finished.
4201
4247
 
4202
4248
  Returns:
4203
4249
  google.cloud.bigquery.table.RowIterator:
@@ -4238,6 +4284,9 @@ class Client(ClientWithProject):
4238
4284
  query=query,
4239
4285
  total_bytes_processed=total_bytes_processed,
4240
4286
  slot_millis=slot_millis,
4287
+ created=created,
4288
+ started=started,
4289
+ ended=ended,
4241
4290
  )
4242
4291
  return row_iterator
4243
4292
 
@@ -224,6 +224,37 @@ class _JobConfig(object):
224
224
  else:
225
225
  self._properties.pop("jobTimeoutMs", None)
226
226
 
227
+ @property
228
+ def max_slots(self) -> Optional[int]:
229
+ """The maximum rate of slot consumption to allow for this job.
230
+
231
+ If set, the number of slots used to execute the job will be throttled
232
+ to try and keep its slot consumption below the requested rate.
233
+ This feature is not generally available.
234
+ """
235
+
236
+ max_slots = self._properties.get("maxSlots")
237
+ if max_slots is not None:
238
+ if isinstance(max_slots, str):
239
+ return int(max_slots)
240
+ if isinstance(max_slots, int):
241
+ return max_slots
242
+ return None
243
+
244
+ @max_slots.setter
245
+ def max_slots(self, value):
246
+ try:
247
+ value = _int_or_none(value)
248
+ except ValueError as err:
249
+ raise ValueError("Pass an int for max slots, e.g. 100").with_traceback(
250
+ err.__traceback__
251
+ )
252
+
253
+ if value is not None:
254
+ self._properties["maxSlots"] = str(value)
255
+ else:
256
+ self._properties.pop("maxSlots", None)
257
+
227
258
  @property
228
259
  def reservation(self):
229
260
  """str: Optional. The reservation that job would use.
@@ -662,7 +693,12 @@ class _AsyncJob(google.api_core.future.polling.PollingFuture):
662
693
 
663
694
  @property
664
695
  def error_result(self):
665
- """Error information about the job as a whole.
696
+ """Output only. Final error result of the job.
697
+
698
+ If present, indicates that the job has completed and was unsuccessful.
699
+
700
+ See:
701
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#JobStatus.FIELDS.error_result
666
702
 
667
703
  Returns:
668
704
  Optional[Mapping]: the error information (None until set from the server).
@@ -673,7 +709,13 @@ class _AsyncJob(google.api_core.future.polling.PollingFuture):
673
709
 
674
710
  @property
675
711
  def errors(self):
676
- """Information about individual errors generated by the job.
712
+ """Output only. The first errors encountered during the running of the job.
713
+
714
+ The final message includes the number of errors that caused the process to stop.
715
+ Errors here do not necessarily mean that the job has not completed or was unsuccessful.
716
+
717
+ See:
718
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#JobStatus.FIELDS.errors
677
719
 
678
720
  Returns:
679
721
  Optional[List[Mapping]]:
@@ -685,7 +727,12 @@ class _AsyncJob(google.api_core.future.polling.PollingFuture):
685
727
 
686
728
  @property
687
729
  def state(self):
688
- """Status of the job.
730
+ """Output only. Running state of the job.
731
+
732
+ Valid states include 'PENDING', 'RUNNING', and 'DONE'.
733
+
734
+ See:
735
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#JobStatus.FIELDS.state
689
736
 
690
737
  Returns:
691
738
  Optional[str]:
@@ -1550,6 +1550,8 @@ class QueryJob(_AsyncJob):
1550
1550
  return _EmptyRowIterator(
1551
1551
  project=self.project,
1552
1552
  location=self.location,
1553
+ schema=self.schema,
1554
+ total_bytes_processed=self.total_bytes_processed,
1553
1555
  # Intentionally omit job_id and query_id since this doesn't
1554
1556
  # actually correspond to a finished query job.
1555
1557
  )
@@ -1737,7 +1739,11 @@ class QueryJob(_AsyncJob):
1737
1739
  project=self.project,
1738
1740
  job_id=self.job_id,
1739
1741
  query_id=self.query_id,
1742
+ schema=self.schema,
1740
1743
  num_dml_affected_rows=self._query_results.num_dml_affected_rows,
1744
+ query=self.query,
1745
+ total_bytes_processed=self.total_bytes_processed,
1746
+ slot_millis=self.slot_millis,
1741
1747
  )
1742
1748
 
1743
1749
  # We know that there's at least 1 row, so only treat the response from
@@ -1767,6 +1773,9 @@ class QueryJob(_AsyncJob):
1767
1773
  query=self.query,
1768
1774
  total_bytes_processed=self.total_bytes_processed,
1769
1775
  slot_millis=self.slot_millis,
1776
+ created=self.created,
1777
+ started=self.started,
1778
+ ended=self.ended,
1770
1779
  **list_rows_kwargs,
1771
1780
  )
1772
1781
  rows._preserve_order = _contains_order_by(self.query)
@@ -1228,11 +1228,18 @@ class _QueryResults(object):
1228
1228
 
1229
1229
  See:
1230
1230
  https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.job_reference
1231
+ or https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.location
1231
1232
 
1232
1233
  Returns:
1233
1234
  str: Job ID of the query job.
1234
1235
  """
1235
- return self._properties.get("jobReference", {}).get("location")
1236
+ location = self._properties.get("jobReference", {}).get("location")
1237
+
1238
+ # Sometimes there's no job, but we still want to get the location
1239
+ # information. Prefer the value from job for backwards compatibilitity.
1240
+ if not location:
1241
+ location = self._properties.get("location")
1242
+ return location
1236
1243
 
1237
1244
  @property
1238
1245
  def query_id(self) -> Optional[str]:
@@ -1287,7 +1294,7 @@ class _QueryResults(object):
1287
1294
  """Total number of slot ms the user is actually billed for.
1288
1295
 
1289
1296
  See:
1290
- https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.slot_millis
1297
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.total_slot_ms
1291
1298
 
1292
1299
  Returns:
1293
1300
  Optional[int]: Count generated on the server (None until set by the server).
@@ -1310,6 +1317,56 @@ class _QueryResults(object):
1310
1317
  if num_dml_affected_rows is not None:
1311
1318
  return int(num_dml_affected_rows)
1312
1319
 
1320
+ @property
1321
+ def created(self):
1322
+ """Creation time of this query.
1323
+
1324
+ See:
1325
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.creation_time
1326
+
1327
+ Returns:
1328
+ Optional[datetime.datetime]:
1329
+ the creation time (None until set from the server).
1330
+ """
1331
+ millis = self._properties.get("creationTime")
1332
+ if millis is not None:
1333
+ return _helpers._datetime_from_microseconds(int(millis) * 1000.0)
1334
+
1335
+ @property
1336
+ def started(self):
1337
+ """Start time of this query.
1338
+
1339
+ This field will be present when the query transitions from the
1340
+ PENDING state to either RUNNING or DONE.
1341
+
1342
+ See:
1343
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.start_time
1344
+
1345
+ Returns:
1346
+ Optional[datetime.datetime]:
1347
+ the start time (None until set from the server).
1348
+ """
1349
+ millis = self._properties.get("startTime")
1350
+ if millis is not None:
1351
+ return _helpers._datetime_from_microseconds(int(millis) * 1000.0)
1352
+
1353
+ @property
1354
+ def ended(self):
1355
+ """End time of this query.
1356
+
1357
+ This field will be present whenever a query is in the DONE state.
1358
+
1359
+ See:
1360
+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.end_time
1361
+
1362
+ Returns:
1363
+ Optional[datetime.datetime]:
1364
+ the end time (None until set from the server).
1365
+ """
1366
+ millis = self._properties.get("endTime")
1367
+ if millis is not None:
1368
+ return _helpers._datetime_from_microseconds(int(millis) * 1000.0)
1369
+
1313
1370
  @property
1314
1371
  def rows(self):
1315
1372
  """Query results.
@@ -1343,7 +1400,7 @@ class _QueryResults(object):
1343
1400
  api_response (Dict): Response returned from an API call
1344
1401
  """
1345
1402
  self._properties.clear()
1346
- self._properties.update(copy.deepcopy(api_response))
1403
+ self._properties.update(api_response)
1347
1404
 
1348
1405
 
1349
1406
  def _query_param_from_api_repr(resource):
@@ -124,6 +124,8 @@ job_retry_reasons = (
124
124
  "rateLimitExceeded",
125
125
  "backendError",
126
126
  "internalError",
127
+ "jobBackendError",
128
+ "jobInternalError",
127
129
  "jobRateLimitExceeded",
128
130
  )
129
131