Skip to content

impl(bigquery): use arrow format with jobs.query - #6472

Draft
alvarowolfx wants to merge 1 commit into
googleapis:mainfrom
alvarowolfx:impl-bq-arrow-jobs-query
Draft

impl(bigquery): use arrow format with jobs.query#6472
alvarowolfx wants to merge 1 commit into
googleapis:mainfrom
alvarowolfx:impl-bq-arrow-jobs-query

Conversation

@alvarowolfx

Copy link
Copy Markdown
Contributor

Trying out arrow support on jobs.query. This is gonna break on CI because support for it is behind an allowlist.

@product-auto-label product-auto-label Bot added the api: bigquery Issues related to the BigQuery API. label Aug 19, 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 Arrow serialization in BigQuery query results, allowing the SDK to request and process Arrow record batches directly. Key changes include updating the query execution to request Arrow format with Zstd compression, implementing Arrow-to-Value conversion for various data types, and parsing Arrow schemas into BigQuery table schemas. Feedback on the changes suggests using unsigned_abs() to prevent overflow panics when formatting intervals, avoiding unnecessary clones when parsing range objects, and ensuring DataType::Interval is correctly mapped to "INTERVAL" in the schema conversion logic.

Comment on lines +535 to +544
let ym_sign = if v.months < 0 { "-" } else { "" };
let years = v.months.abs() / 12;
let months = v.months.abs() % 12;

// Format Time H:MM:SS[.fffffffff]
let (time_sign, total_nanos) = if v.nanoseconds < 0 {
("-", (-v.nanoseconds) as u64)
} else {
("", v.nanoseconds as u64)
};

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.

high

Using .abs() on v.months and negation -v.nanoseconds can panic with overflow if they contain i32::MIN or i64::MIN respectively. Use unsigned_abs() to safely obtain the absolute value as an unsigned integer without any risk of overflow panics.

Suggested change
let ym_sign = if v.months < 0 { "-" } else { "" };
let years = v.months.abs() / 12;
let months = v.months.abs() % 12;
// Format Time H:MM:SS[.fffffffff]
let (time_sign, total_nanos) = if v.nanoseconds < 0 {
("-", (-v.nanoseconds) as u64)
} else {
("", v.nanoseconds as u64)
};
let ym_sign = if v.months < 0 { "-" } else { "" };
let months_abs = v.months.unsigned_abs();
let years = months_abs / 12;
let months = months_abs % 12;
// Format Time H:MM:SS[.fffffffff]
let (time_sign, total_nanos) = if v.nanoseconds < 0 {
("-", v.nanoseconds.unsigned_abs())
} else {
("", v.nanoseconds as u64)
};

Comment on lines +230 to +240
wkt::Value::Object(obj) => {
let start = match obj.get("start") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val.clone())?),
};
let end = match obj.get("end") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val.clone())?),
};
Ok(Range { start, end })
}

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

Since value is passed by value to from_sql, the matched obj is an owned map. We can bind it mutably as mut obj and use remove instead of get and clone(). This avoids unnecessary cloning of the inner wkt::Values, which can be expensive.

Suggested change
wkt::Value::Object(obj) => {
let start = match obj.get("start") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val.clone())?),
};
let end = match obj.get("end") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val.clone())?),
};
Ok(Range { start, end })
}
wkt::Value::Object(mut obj) => {
let start = match obj.remove("start") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val)?),
};
let end = match obj.remove("end") {
Some(wkt::Value::Null) | None => None,
Some(val) => Some(T::from_sql(val)?),
};
Ok(Range { start, end })
}
References
  1. Avoid unnecessary clones of owned values by taking ownership of the object and removing fields directly. (link)

Comment on lines +83 to +86
DataType::Time32(_) | DataType::Time64(_) => ("TIME", vec![]),
DataType::Timestamp(_, Some(_)) => ("TIMESTAMP", vec![]),
DataType::Timestamp(_, None) => ("DATETIME", vec![]),
DataType::Decimal128(_, _) | DataType::Decimal256(_, _) => ("NUMERIC", vec![]),

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

Map DataType::Interval to "INTERVAL" to ensure consistency with the data conversion logic in row.rs where DataType::Interval is explicitly handled.

        DataType::Time32(_) | DataType::Time64(_) => ("TIME", vec![]),
        DataType::Timestamp(_, Some(_)) => ("TIMESTAMP", vec![]),
        DataType::Timestamp(_, None) => ("DATETIME", vec![]),
        DataType::Decimal128(_, _) | DataType::Decimal256(_, _) => ("NUMERIC", vec![]),
        DataType::Interval(_) => ("INTERVAL", vec![]),

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.92986% with 175 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.17%. Comparing base (8885421) to head (d26657f).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
src/bigquery/src/query/row.rs 56.71% 129 Missing ⚠️
src/bigquery/src/query/schema.rs 69.87% 25 Missing ⚠️
src/bigquery/src/query/query_handle.rs 61.76% 13 Missing ⚠️
src/bigquery/src/datatypes.rs 11.11% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6472      +/-   ##
==========================================
- Coverage   96.36%   96.17%   -0.19%     
==========================================
  Files         295      295              
  Lines       83697    84177     +480     
==========================================
+ Hits        80655    80961     +306     
- Misses       3042     3216     +174     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

1 participant