Skip to content

feat(bigquery): skip job creation for ARROW query_and_wait results - #18799

Merged
ohmayr merged 4 commits into
mainfrom
feat/bigquery-arrow-job-creation-optional
Oct 28, 2026
Merged

ohmayr merged 4 commits into
mainfrom
feat/bigquery-arrow-job-creation-optional

Conversation

@ohmayr

@ohmayr ohmayr commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Before, query_and_wait(query_results_format="ARROW") always created a job unless the caller set client.default_job_creation_mode, so small Arrow queries paid about 200 ms for a job they didn't need. Arrow callers want low latency, so ARROW queries now default to JOB_CREATION_OPTIONAL, which is what createQueryArrowStream() in the Node.js client already does.

This changes behavior for existing ARROW callers (Beta since 3.44.0): results that fit in the first response now come back with RowIterator.job_id set to None. location and query_id are still set. To always get a job, set default_job_creation_mode="JOB_CREATION_REQUIRED" on the client or use client.query().

  • query_and_wait() sends jobCreationMode=JOB_CREATION_OPTIONAL when query_results_format is ARROW and the client doesn't set default_job_creation_mode. A client-level mode still wins.
  • Multi-page and long-running ARROW queries still get a job, since BigQuery creates one when rows remain. ARROW queries that need jobs.insert (for example, with a destination table) also still create a job.
  • Queries without ARROW are unchanged.
  • The query_results_format and default_job_creation_mode docstrings describe the new default and how to opt out.
  • Tests: unit tests for the ARROW default, a client-level mode taking precedence, non-ARROW queries sending no mode, and the jobs.insert fallback. Ran the unit suite and tests/system/test_arrow.py against BigQuery. A live single-page ARROW query returned job_id=None, while a multi-page ARROW query, a non-ARROW query and an ARROW query with JOB_CREATION_REQUIRED on the client each returned a job.

Callers who pass query_results_format="ARROW" want low latency, so
query_and_wait() now sends jobCreationMode=JOB_CREATION_OPTIONAL for
them unless the client sets default_job_creation_mode. Single-page
results skip creating a job (about 200 ms faster), so RowIterator.job_id
is None for them. Multi-page results still create a job.

Callers who need a job can set default_job_creation_mode to
JOB_CREATION_REQUIRED or use client.query(). Queries without ARROW are
unchanged. This matches createQueryArrowStream() in the Node.js client.
@ohmayr
ohmayr requested review from a team as code owners October 21, 2026 19:01
@ohmayr
ohmayr requested review from julianxu-goog and tswast and removed request for a team and julianxu-goog October 21, 2026 19:01

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the query_and_wait method to automatically set the jobCreationMode to JOB_CREATION_OPTIONAL when the query results format is set to ARROW and no default mode is specified on the client. It also updates the corresponding docstrings and adds unit tests to verify this behavior. Feedback is provided regarding the handling of the query_results_format Enum parameter, advising that type annotations and input handling for raw string representations should be consistent across all related API methods rather than handled selectively.

request_body["maxResults"] = page_size or max_results
if client.default_job_creation_mode:
request_body["jobCreationMode"] = client.default_job_creation_mode
elif query_results_format == enums.QueryResultsFormat.ARROW:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When supporting raw string representations for an Enum parameter like query_results_format, we must ensure that type annotations and input handling are consistent across all related API methods. We should not selectively support or normalize raw string inputs in only a subset of methods. If we want to support string inputs (including case-insensitive comparisons), this handling should be applied uniformly across all related methods rather than as a localized change here.

References
  1. When a parameter accepts an Enum, ensure its type annotations and input handling are consistent across all related API methods. Do not selectively support raw string representations in only a subset of these methods.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't add any string handling. It's the same == enums.QueryResultsFormat.ARROW check query_and_wait() already uses a few lines up, and QueryResultsFormat is a str enum, so it behaves the same as the existing check.

The unit_noextras session runs without google-cloud-bigquery-storage,
so query_and_wait() raised before building the request. Patch
_arrow_query._check_dependencies like the other ARROW tests do, since
these tests only check the request.
Verify that query_and_wait() sets RowIterator.job_id to None and
populates query_id when the jobs.query response omits jobReference
under JOB_CREATION_OPTIONAL.
@ohmayr
ohmayr marked this pull request as draft October 24, 2026 07:26
@ohmayr ohmayr added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Oct 27, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Oct 27, 2026
@ohmayr
ohmayr marked this pull request as ready for review October 27, 2026 23:43
@ohmayr
ohmayr merged commit ca24f26 into main Oct 28, 2026
54 checks passed
@ohmayr
ohmayr deleted the feat/bigquery-arrow-job-creation-optional branch October 28, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants