Skip to content

bigquery-derive: reject ambiguous and duplicate #[bigquery(...)] attributes at compile time #7450

Open

Description

@coryan

Summary

google-cloud-bigquery-derive (#[derive(FromRow)] and #[derive(FromSql)]) silently accepts ambiguous and invalid #[bigquery(...)] attribute configurations instead of rejecting them with compile-time errors.

Because rejecting input that previously compiled is a breaking change to accepted macro input under the proc-macro compatibility policy (src/bigquery-derive/src/lib.rs), fixing these validation gaps before google-cloud-bigquery 1.0.0 is released (#7424) avoids requiring a major bump of google-cloud-bigquery later.

Problem Details

Per doc/contributor/howto-guide-handwritten-client-api.md:

Ambiguous input (for example, two fields mapping to the same property name after flattening) is an error, never resolved silently.

Currently in src/bigquery-derive/src/lib.rs:

  1. Duplicate target column / STRUCT field names compile silently and exhibit transport-dependent runtime behavior:
    • derive_from_row_impl and derive_from_sql_impl resolve each named field's column/field name independently without checking for duplicates across the struct.
    • For example:
      #[derive(FromRow)]
      struct AmbiguousRow {
          col: Option<String>,
          #[bigquery(rename = "col")]
          other: Option<String>,
      }
      (or two fields both marked #[bigquery(rename = "same")], or r#type colliding with #[bigquery(rename = "type")]).
    • At runtime, FromRow emits two row.take("col")? calls:
      • On JSON-backed rows (RowInner::Json in src/bigquery/src/query/row.rs), the first take replaces cell "col" with SqlValueInner::Null, so other silently receives None (or fails with ConvertError::NotNull for non-optional types).
      • On Arrow-backed rows (RowInner::Arrow in src/bigquery/src/query/row.rs), take reads from the RecordBatch without mutating it, so both col and other receive "col"'s value.
    • FromSql (SqlValue::take) has the same discrepancy between SqlValueInner::Struct (replaces slot with Null) and SqlValueInner::Arrow (reads without mutating).
  2. Multiple #[bigquery(...)] attributes on the same field short-circuit after the first rename:
    • In get_field_name (src/bigquery-derive/src/lib.rs), if let Some(name) = renamed { return Ok(name); } returns inside the for attr in &field.attrs loop.
    • A second #[bigquery(rename = "...")] on the same field is silently ignored instead of reporting a duplicate rename error, and a subsequent invalid attribute (e.g., #[bigquery(rename = "a")] #[bigquery(typo = "b")]) is never parsed at all.
  3. Duplicate rename options inside a single attribute overwrite silently:
    • #[bigquery(rename = "a", rename = "b")] overwrites renamed = Some(lit.value()) without checking if rename was already specified, silently using "b".
  4. Container-level #[bigquery(...)] attributes on structs are silently ignored:
    • Neither derive_from_row_impl nor derive_from_sql_impl inspects input.attrs, so unsupported container attributes such as #[bigquery(rename_all = "camelCase")] on a struct compile without error and have no effect.

Expected Behavior

  • Reject structs where two or more fields resolve to the same BigQuery column / STRUCT field name with a spanned syn::Error.
  • Inspect all #[bigquery(...)] attributes on every field and reject duplicate rename options (whether in one #[bigquery(rename = "a", rename = "b")] list or across multiple #[bigquery(...)] attributes on the same field).
  • Reject #[bigquery(...)] attributes placed on the container (struct/enum/union) itself until/unless container options are explicitly supported.
  • Add unit tests in src/bigquery-derive/src/lib.rs covering each error case, and take a breaking version bump on google-cloud-bigquery-derive if needed per the compatibility policy.

Activity

  1. added
    type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.
    api: bigqueryIssues related to the BigQuery API.
    priority: p2Moderately-important priority. Fix may not be included in next release.
    on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api: bigqueryIssues related to the BigQuery API.priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions