FrankChen021 opened a new pull request, #5280: URL: https://github.com/apache/calcite/pull/5280
## Jira Link [CALCITE-7805](https://issues.apache.org/jira/browse/CALCITE-7805) ## Changes Proposed Large string ARRAY validation creates generated CAST calls for operands whose inferred type differs from the common element type. These calls already use the built-in CAST operator, but the normal validation path resolves the operator again by name for every operand. Validate each generated CAST directly through its existing operator before replacing the operand. This preserves operand checks and validated-node type registration while avoiding repeated function lookup. The regression test also verifies the contract this optimization relies on: after `validateOperands` registers the generated CAST type, a later `deriveType` call reuses that cached type and performs no operator-table lookup. This branch is based directly on `main` at `38413ece6`, which includes the bulk operand replacement from CALCITE-7782. It is independent of the other allocation optimizations. ## Execution Path Before this change, Calcite creates each generated CAST with the built-in operator but does not immediately register its validated type: ```text Create built-in CAST node -> no validated type recorded -> later validator.deriveType(cast) -> SqlOperator.deriveType -> build operand and argument-type lists -> SqlUtil.lookupRoutine(...) -> search the operator table for "CAST" -> find the same built-in CAST operator -> validateOperands(...) -> store the validated type ``` The expensive work is resolving an operator that is already known. For every generated CAST, `SqlOperator.deriveType` constructs temporary operand/type lists and performs routine lookup. With this change, the existing built-in operator validates the generated CAST immediately: ```text Create built-in CAST node -> cast.getOperator().validateOperands(...) -> infer and register the CAST type immediately -> later validator.deriveType(cast) -> validated-type cache hit; return immediately ``` This keeps the same operand validation and return-type inference while removing the redundant operator-resolution path. ## Benchmark Measured with Druid's `InPlanningBenchmark.queryStringInSqlPlanOnly`, comparing Calcite 1.42 plus CALCITE-7782 against the same baseline with only this change. Configuration: 2 warmup iterations, 5 measurement iterations, 2 forks, 1 second per iteration. Allocation is total allocated bytes per planning operation, not retained or peak heap. | String literals | Baseline allocation | This change | 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%) | Average planning time changed from 749.87 to 735.42 ms/op at 100,000 literals and from 7,978.14 to 7,585.11 ms/op at 1,000,000. The timing confidence intervals overlap, so these runs establish the allocation improvement but do not claim a statistically reliable latency improvement. ## Validation - `./gradlew :core:test --tests org.apache.calcite.test.SqlValidatorTest :core:autostyleJavaCheck :core:checkstyleTest` (596 completed, 0 failed, 7 skipped) - Isolated Druid JMH benchmark at 100,000 and 1,000,000 string literals -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
