Skip to content

[CALCITE-7806] Avoid resolving generated CAST calls during array validation - #5280

Open
FrankChen021 wants to merge 1 commit into
apache:mainfrom
FrankChen021:codex/generated-cast-direct-validation
Open

FrankChen021 wants to merge 1 commit into
apache:mainfrom
FrankChen021:codex/generated-cast-direct-validation

Conversation

@FrankChen021

@FrankChen021 FrankChen021 commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Fixes CALCITE-7806.

Why

ARRAY and MAP validation creates CAST calls when operands must be adjusted to a common element type. These calls already contain Calcite's built-in CAST operator, but a later deriveType resolves the same operator by name for every generated CAST, allocating temporary operand and argument-type lists along the way.

In Druid's string-IN planning benchmark, avoiding that repeated lookup reduced allocation by 19.95% at 100,000 literals and 20.48% at 1,000,000 literals. Timing confidence intervals overlapped, so no latency improvement is claimed.

What

Before this change:

Create built-in CAST node
  -> no validated type recorded
  -> later validator.deriveType(cast)
  -> build operand and argument-type lists
  -> resolve "CAST" through the operator table
  -> validate operands and store the type

With this change:

Create built-in CAST node
  -> validate through cast.getOperator()
  -> register the validated type immediately
  -> later validator.deriveType(cast)
  -> return the cached type

This preserves CAST operand validation and return-type inference while avoiding resolution of an operator that is already known.

Verification

  • SqlValidatorTest verifies that a generated CAST is registered and that a later deriveType performs no operator-table lookup.
  • ./gradlew :core:test --tests org.apache.calcite.test.SqlValidatorTest :core:autostyleJavaCheck :core:checkstyleTest (596 completed, 0 failed, 7 skipped)
  • Druid InPlanningBenchmark.queryStringInSqlPlanOnly with -prof gc
Druid benchmark results
String literals Baseline allocation PR allocation Reduction
100,000 1,448.09 MiB/op 1,159.19 MiB/op 288.90 MiB/op (19.95%)
1,000,000 14,653.13 MiB/op 11,651.62 MiB/op 3,001.52 MiB/op (20.48%)

Configuration: 2 forks, 2 one-second warmup iterations, and 5 one-second measurement iterations. Allocation is cumulative bytes per operation, not retained or peak heap.

The performance measurement currently comes from Druid; a Calcite-local ubenchmark is not yet included.

Scope

This change applies only to CAST calls generated while adjusting ARRAY and MAP constructor operands. It does not change CAST semantics or user-written CAST validation.

Copilot AI lite review requested due to automatic review settings September 22, 2026 10:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

@FrankChen021 FrankChen021 changed the title [CALCITE-7805] Avoid resolving generated CAST calls during array validation [CALCITE-7806] Avoid resolving generated CAST calls during array validation Sep 22, 2026

@julianhyde julianhyde 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.

-1 slop

SqlCall cast = (SqlCall) castTo(operands.get(i), elementType);
// This CAST was generated with the built-in operator; validate its
// operands directly instead of resolving the function again by name.
cast.getOperator().validateOperands(

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.

You seem to do strictly more work than before.
This looks correct, but does not seem more efficient.

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.

4 participants