Skip to content

feat(bigquery): support explicit destination tables in createQueryArrowStream - #9601

Merged
ohmayr merged 4 commits into
feat/bigquery-arrow-jobs-insertfrom
feat/bigquery-arrow-destination-table
Oct 21, 2026
Merged

ohmayr merged 4 commits into
feat/bigquery-arrow-jobs-insertfrom
feat/bigquery-arrow-destination-table

Conversation

@ohmayr

@ohmayr ohmayr commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

A query with an explicit destination table writes its results there instead of to an anonymous table, so there's no streams/_default to read. This reads the destination table through a read session once the job finishes.

  • Calls createReadSession with dataFormat: 'ARROW' and maxStreamCount: 1 (one stream keeps rows in the query's order) and reads streams[0] from offset = 0.
  • Uses the destination table BigQuery echoes in the job's configuration, so the table path has its resolved project. The session is billed to the job's project.
  • An empty destination table returns no streams; that emits one 0-row RecordBatch with the session's schema.
  • Fails with a clear error if no project ID can be resolved for the read session, instead of sending projects/undefined.

@product-auto-label product-auto-label Bot added the api: bigquery Issues related to the BigQuery API. label Oct 13, 2026

@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 adds support for streaming Arrow results from explicit destination tables in createQueryArrowStream using the BigQuery Storage Read API. The review feedback identifies three robustness issues: a potential unhandled exception if getStorageReadClient fails, a missing validation check for parentProjectId which could result in an invalid resource path, and a potential TypeError if query is null during the destination check.

Comment thread handwritten/bigquery/src/arrow.ts Outdated
Comment thread handwritten/bigquery/src/arrow.ts Outdated
Comment thread handwritten/bigquery/src/arrow.ts Outdated
@ohmayr
ohmayr added this pull request to stack #9597 October 13, 2026 07:08
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch from f2edf85 to e70ca28 Compare October 13, 2026 08:41
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch 3 times, most recently from a83abe3 to 566de0a Compare October 13, 2026 10:42
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch 2 times, most recently from 04e682f to a13292a Compare October 13, 2026 12:00
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch from a13292a to a8e1848 Compare October 13, 2026 19:26
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch from a8e1848 to 508a4a2 Compare October 15, 2026 09:55
Comment thread handwritten/bigquery/src/arrow.ts Outdated
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch 2 times, most recently from b4cc0d4 to 4dd87b7 Compare October 15, 2026 18:27
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch 3 times, most recently from bccdb5b to 3e8968a Compare October 16, 2026 02:19
@ohmayr
ohmayr marked this pull request as ready for review October 16, 2026 02:34
@ohmayr
ohmayr requested review from a team as code owners October 16, 2026 02:34
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch from 4d56cd1 to 3e8968a Compare October 16, 2026 21:33
Comment thread handwritten/bigquery/src/arrow.ts Outdated
callback: (err: Error | null, schema?: Uint8Array | string) => void,
): void {
const {bq, storage} = ctx;
const {bq} = ctx;

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.

I'm not sure if destructuring the bigquery client is necessary here

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.

Removed; it uses ctx.bq directly.

Comment thread handwritten/bigquery/src/arrow.ts Outdated

const sessionSchema = session?.arrowSchema?.serializedSchema || undefined;
const readStream = session?.streams?.[0]?.name;
if (!readStream) {

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.

Can we also include a check that session.streams.length === 0?

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.

Added. It checks streams.length === 0 (or a missing stream name) before reading streams[0], and emits the 0-row batch with the session schema.

Comment thread handwritten/bigquery/src/arrow.ts Outdated
ctx: ArrowStreamContext,
parentProjectId: string | undefined,
table: bigquery.ITableReference,
callback: (err: Error | null, session?: IReadSession) => void,

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.

Nit: this is a lot of callback nesting. This function could be refactored to be a Promise instead

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.

Done. createArrowReadSession returns a Promise now, and streamDestinationTable/readDestinationSchema await it, so there's no callback nesting left.

Read results of jobs.insert queries with an explicit destination table
through BigQueryReadClient.createReadSession (dataFormat: ARROW,
maxStreamCount: 1) once the job completes, instead of the job's default
stream, which only serves anonymous destination tables. An empty
destination table returns no streams, so emit one 0-row RecordBatch
with the session's Arrow schema.
@ohmayr
ohmayr force-pushed the feat/bigquery-arrow-destination-table branch from 3e8968a to a32866f Compare October 20, 2026 20:53
@ohmayr

ohmayr commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on the #9598–#9600 changes. Same behavior: the destination-table read goes through the shared streamJobWhenComplete step after the job finishes, and uses async/await throughout.

Throw a clear error instead of creating a read session with parent
"projects/undefined" when no project ID can be resolved. Note in the
createQueryArrowStream JSDoc that an explicit destination table is
read in full through a read session after the query finishes.
@ohmayr
ohmayr merged commit f22e2dd into main Oct 21, 2026
32 checks passed
@ohmayr
ohmayr deleted the feat/bigquery-arrow-destination-table branch October 21, 2026 19:05
@release-please release-please Bot mentioned this pull request Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: bigquery Issues related to the BigQuery API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants