Skip to content

[CALCITE-7420] Convert RelOptRulesTest to Quidem scripts#4815

Draft
julianhyde wants to merge 25 commits intoapache:mainfrom
julianhyde:7420-rule-test
Draft

[CALCITE-7420] Convert RelOptRulesTest to Quidem scripts#4815
julianhyde wants to merge 25 commits intoapache:mainfrom
julianhyde:7420-rule-test

Conversation

@julianhyde
Copy link
Contributor

See [CALCITE-7420].

This is a draft PR. If you have comments on the strategy or design please make them in the Jira case. I do not want comments on the code right now.

julianhyde and others added 14 commits March 1, 2026 16:48
Add infrastructure for rule-based plan tests in Quidem (.iq) files:
- Add SubPlanCommand (!sub-plan) that shows a SQL logical plan before
  and after applying named CoreRules via HepPlanner
- Update data() to recursively walk subdirectories for .iq files
- Add sql/rule/aggregate.iq with testPullAggregateThroughUnion,
  migrated from RelOptRulesTest.testPullAggregateThroughUnion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the following tests from RelOptRulesTest.java/xml to
sql/rule/aggregate.iq:
- testPullAggregateThroughUnion2 (AGGREGATE_UNION_AGGREGATE_SECOND/FIRST)
- testPullAggregateThroughUnionAndAddProjects (AGGREGATE_PROJECT_MERGE,
  AGGREGATE_UNION_AGGREGATE)
- testPullAggregateThroughUnionWithAlias (AGGREGATE_PROJECT_MERGE,
  AGGREGATE_UNION_AGGREGATE)
- testAggregateProjectMerge (AGGREGATE_PROJECT_MERGE)
- testAggregateGroupingSetsProjectMerge (AGGREGATE_PROJECT_MERGE)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrates tests from RelOptRulesTest.java + XML to .iq files:
- filter.iq: testFilterProjectTransposeRule2, testFilterProjectTransposeRule3
- join.iq: testAddRedundantSemiJoinRule, testExtractJoinFilterRule
- sample.iq: testFilterSampleTransposeWithBernoulli,
  testFilterSampleTransposeWithSystem,
  testFilterSampleTransposeWithSystemAndSeed,
  testSampleToFilter, testSampleToFilterWithSeed
- union.iq: testUnionToDistinctRule

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ormat (batch 3)

Migrated tests for:
- JOIN_DERIVE_IS_NOT_NULL_FILTER_RULE (14 tests) → join-derive.iq
- SORT_REMOVE_CONSTANT_KEYS, SORT_REMOVE_REDUNDANT, SORT_REMOVE_DUPLICATE_KEYS
  (18 tests) → sort-remove.iq
- UNION_MERGE, INTERSECT_MERGE, MINUS_MERGE (7 tests) → union.iq
- PROJECT_JOIN_JOIN_REMOVE, PROJECT_JOIN_REMOVE (10 tests) → project-join-remove.iq

Tests not migrated (require withFactory or withVolcanoPlanner):
- testJoinDeriveIsNotNullFilterRule14 (Oracle NVL)
- testSortRemoveConstantKeyDoesNotRemoveOrderByRandom (PostgreSQL RANDOM)
- testSortRemovalOneKeyConstant (withVolcanoPlanner with collation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ormat (batch 4)

Creates 3 new rule test files and updates 7 existing ones:
* aggregate-join-transpose.iq: 31 tests for AGGREGATE_JOIN_TRANSPOSE_EXTENDED
* project-join-transpose.iq: 24 tests for PROJECT_FILTER_TRANSPOSE, PROJECT_MERGE,
  PROJECT_SET_OP_TRANSPOSE, and related rules
* reduce-expressions.iq: 31 tests for FILTER_REDUCE_EXPRESSIONS,
  PROJECT_REDUCE_EXPRESSIONS, JOIN_REDUCE_EXPRESSIONS

Also adds descriptions and '!ok'/'Not using !ok' explanations to all tests
in rule/*.iq files, per coding standards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…format (batch 5)

Migrate tests from RelOptRulesTest.java and RelOptRulesTest.xml to
Quidem .iq scripts in core/src/test/resources/sql/rule/:

New files:
- aggregate-constants.iq (9 tests):
  AGGREGATE_ANY_PULL_UP_CONSTANTS, AGGREGATE_VALUES
- aggregate-expand-distinct-aggregates.iq (22 tests):
  AGGREGATE_EXPAND_DISTINCT_AGGREGATES, AGGREGATE_EXPAND_DISTINCT_AGGREGATES_TO_JOIN
- aggregate-filter.iq (14 tests):
  FILTER_AGGREGATE_TRANSPOSE, AGGREGATE_FILTER_TRANSPOSE,
  AGGREGATE_CASE_TO_FILTER, AGGREGATE_FILTER_TO_CASE,
  AGGREGATE_REDUCE_FUNCTIONS, AGGREGATE_MERGE,
  AGGREGATE_MIN_MAX_TO_LIMIT, AGGREGATE_GROUPING_SETS_TO_UNION
- filter-into-join.iq (10 tests): FILTER_INTO_JOIN
- filter-project-transpose.iq (9 tests):
  FILTER_PROJECT_TRANSPOSE, PROJECT_WINDOW_TRANSPOSE,
  PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW, PROJECT_CORRELATE_TRANSPOSE,
  FILTER_TABLE_FUNCTION_TRANSPOSE
- join-project-transpose.iq (19 tests):
  JOIN_PROJECT_RIGHT/LEFT/BOTH_TRANSPOSE_INCLUDE_OUTER,
  JOIN_PUSH_EXPRESSIONS, JOIN_EXPAND_OR_TO_UNION_RULE,
  JOIN_CONDITION_EXPAND_IS_NOT_DISTINCT_FROM,
  JOIN_REDUCE_EXPRESSIONS, FULL_TO_LEFT_AND_RIGHT_JOIN
- join-push-transitive-predicates.iq (21 tests):
  JOIN_PUSH_TRANSITIVE_PREDICATES
- join-sub-query-to-correlate.iq (7 tests): JOIN_SUB_QUERY_TO_CORRELATE
- misc-rules.iq (10 tests):
  LIMIT_MERGE, MULTI_JOIN_OPTIMIZE_BUSHY, MULTI_JOIN_OPTIMIZE,
  PROJECT_VALUES_MERGE, PROJECT_JOIN_TRANSPOSE, FILTER_TO_CALC,
  PROJECT_TO_CALC, FILTER_CALC_MERGE, PROJECT_CALC_MERGE,
  JOIN_CONDITION_PUSH
- project-aggregate-merge.iq (7 tests): PROJECT_AGGREGATE_MERGE
- semi-join.iq (4 tests): SEMI_JOIN_REMOVE
- set-op.iq (29 tests):
  INTERSECT_TO_SEMI_JOIN, INTERSECT_TO_EXISTS, MINUS_FILTER_TO_FILTER,
  UNION_FILTER_TO_FILTER, INTERSECT_FILTER_TO_FILTER, MINUS_TO_ANTI_JOIN,
  AGGREGATE_UNION_TRANSPOSE, JOIN_LEFT/RIGHT_UNION_TRANSPOSE
- sort-join-transpose.iq (15 tests):
  SORT_JOIN_TRANSPOSE, SORT_JOIN_COPY, SORT_PROJECT_TRANSPOSE
- unnest.iq (5 tests): UNNEST_DECORRELATE, UNNEST_PROJECT_DECORRELATE

Modified existing files:
- aggregate-join-transpose.iq: +2 tests
- reduce-expressions.iq: +13 tests

Tests testReduceCase, testSimplifyItemIsNotNull, testSimplifyItemIsNull
are kept in RelOptRulesTest.java because they use withRelBuilderSimplify(false)
or withDynamicTable() which are not supported in Quidem .iq format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… and testPushAggregateThroughJoin3

Add config tokens to SubPlanCommand in QuidemTest, allowing !sub-plan
directives to configure SQL-to-RelNode conversion and RelBuilder behavior.
Tokens starting with a lowercase letter are config options; UPPERCASE tokens
are CoreRules field names. Supported tokens: aggregateUnique=true, bloat=N,
expand=true, relBuilderSimplify=false, simplifyValues=false, subQueryRules,
trim=true.

Use new tokens to migrate testReduceCase (relBuilderSimplify=false) and
testPushAggregateThroughJoin3/testPushAggregateThroughOuterJoin11
(aggregateUnique=true) from RelOptRulesTest.java + XML to
reduce-expressions.iq and aggregate-join-transpose.iq respectively.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…q format

Use the config tokens added in the previous commit to migrate tests from
RelOptRulesTest.java to new and existing .iq files:

- reduce-expressions.iq: testReduceCaseNullabilityChange, testReduceCasts
  (relBuilderSimplify=false), testReduceConstants2 (simplifyValues=false)
- aggregate.iq: testAggregateRemove2 (aggregateUnique=true)
- join-push-transitive-predicates.iq: testInferringPredicatesWithNotOperator
  InJoinCondition (relBuilderSimplify=false)
- filter-sub-query-to-correlate.iq (new): testExpandFilter* and
  testExpandWhereComparisonCorrelated and testWhereInJoinCorrelated
  (subQueryRules, relBuilderSimplify=false, trim=true tokens)
- project-sub-query-to-correlate.iq (new): testExpandProject* and
  testSomeWithTwo* (subQueryRules, relBuilderSimplify=false, trim=true)
- join-sub-query-to-correlate.iq: testExpandJoinExists, testExpandJoinScalar
  (subQueryRules)

Also fix SubPlanCommand: trim=true must set withTrimUnusedFields on the
factory config so that converter.trimUnusedFields() is not a no-op, and must
also call flattenTypes then trimUnusedFields after conversion (matching
AbstractSqlTester.convertSqlToRel2 behavior).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, tests using sales-schema tables (e.g., sales.emp) or
focusing on plan transformation had comments like:
  # Not using !ok: query uses the sales schema, which is not in the scott database.
  # Not using !ok: this test focuses on plan transformation (see !sub-plan).

This commit enables !ok for all such tests that are compatible with the
scott HSQLDB database, adding the expected query results. Sales-schema
references (sales.emp, sales.dept, etc.) are converted to unqualified
names (emp, dept, etc.) so they run against the scott catalog.

Tests that remain disabled are those using non-scott tables
(empnullables, deptnullables, DEPT_NESTED), non-deterministic functions
(RAND, RAND_INTEGER, CURRENT_TIMESTAMP), or queries that fail in H2
due to implementation limits (very large LIMIT/OFFSET values, EXCEPT
with correlated subqueries, ORDER BY null, SINGLE_VALUE aggregation
with multiple rows).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e mismatches against scott HSQLDB

For tests where running SQL against scott HSQLDB causes exceptions
(TINYINT overflow, type mismatches, dynamic parameters, internal
AssertionErrors), use !error, !type, or fix the SQL.

- aggregate-expand-distinct-aggregates.iq: SUM(deptno) overflows in
  some groups (Value 150 out of range)
- aggregate-filter.iq: SMALLINT overflow; count(distinct cast(...))
  projects as anonymous column
- aggregate-join-transpose.iq, filter-sub-query-to-correlate.iq:
  Remove captured exception stack traces (tests now pass)
- filter-project-transpose.iq: Internal AssertionError
  (type mismatch SMALLINT/TINYINT in windowed aggregate)
- join-project-transpose.iq: Type mismatches in joins (cast x to
  varchar, join on deptno instead of dname for rank comparison)
- project-aggregate-merge.iq: TINYINT overflow
  (Value 7902 out of range for cast(mgr as tinyint))
- project-join-remove.iq: slacker column not in scott database
- project-join-transpose.iq: slacker column not in scott database
- reduce-expressions.iq: Wrong plan (VARCHAR(20)->VARCHAR(10), EMP->DEPT)
- set-op.iq: TINYINT nullability mismatch in INTERSECT
- sort-join-transpose.iq: Dynamic parameters (?) cause NPE

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…em .iq format

Adds lateDecorrelate=true and operatorTable=BIG_QUERY config tokens to
!sub-plan, enabling migration of tests that require these configurations.

- reduce-expressions.iq: testDoubleReduction, testDoubleReduction2
  (POWER and division constant folding); testSplit, testSplitNull,
  testSplitNull1, testSplitNull2 (BigQuery SPLIT function reduction)
- project-sub-query-to-correlate.iq: testDecorrelationWithProject
  (EXISTS in project expanded to left join, then late decorrelation)

RelOptRulesTest.java and RelOptRulesTest.xml are now empty of tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
julianhyde and others added 3 commits March 2, 2026 16:50
Migrate tests from RelOptRulesTest.java + XML to Quidem .iq scripts.
Remove preRule= token from SubPlanCommand; use a single HepPlanner
pass instead.

New .iq files: limit-merge.iq, union-to-values.iq
Updated .iq files: aggregate.iq, aggregate-distinct-test.iq,
  aggregate-expand-distinct-aggregates.iq, aggregate-join-remove.iq,
  filter.iq, filter-into-join.iq, filter-project-transpose.iq,
  reduce-expressions.iq, semi-join.iq, set-op.iq

QuidemTest.java: add inSubQueryThreshold=N token; remove preRule= token.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate 15 tests from RelOptRulesTest.java + XML to Quidem .iq scripts:

- reduce-expressions.iq: testReduceNestedCaseWhen, testReduceNot
- aggregate.iq: testDigestOfApproximateDistinctAggregateCall,
  testRemoveDistinctOnAgg
- aggregate-within-distinct.iq (new file): testWithinDistinct,
  testWithinDistinctNoThrow, testWithinDistinctUniformDistinctKeys,
  testWithinDistinctUniformDistinctKeysNoThrow,
  testWithinDistinctCountDistinct, testWithinDistinctFilteredAggs,
  testWithinDistinctPreservesNonDistinctAggFilters,
  testWithinDistinctPreservesNonDistinctCollation,
  testWithinDistinctFilteredAggsUniformDistinctKeys,
  testWithinDistinctFilteredAggsUniformDistinctKeysNoThrow,
  testWithinDistinctFilteredAggsSameFilter

Also adds 'throwIfNotUnique=false' config token to SubPlanCommand in
QuidemTest.java, which applies
AggregateExpandWithinDistinctRule.config.withThrowIfNotUnique(false)
when the token precedes AGGREGATE_EXPAND_WITHIN_DISTINCT in the rule
list.

Also carries forward earlier-session changes:
- filter-into-join.iq: testStrengthenJoinType
- filter-project-transpose.iq (new): testFilterProjectTransposePreventedByCorrelation,
  testProjectCorrelateTransposeRuleLeftCorrelate
- filter.iq: testPushFilterPastAggWithGroupingSets1/2
  (with correct pre-rules PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE)
- project-filter-transpose.iq (new): testPushProjectPastFilter3b/3c

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
julianhyde and others added 2 commits March 3, 2026 10:51
…use on its own line

For SQL fragments in rule/*.iq files where any line exceeded 80 characters,
reformat the entire query: put each clause (select, from, join, where) on its
own line, indent subqueries 4 spaces, and keep 'on' on the same line as
'join'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate 6 SQL-based filter tests from RelOptRulesTest.java + XML to
Quidem .iq scripts:

- testFilterIntoJoinMissingVariableCor → filter-into-join.iq
- testExpandFilterDisjunctionForJoinInput → misc-rules.iq
- testManyFiltersOnTopOfMultiJoinShouldCollapse → misc-rules.iq
- testMergeFilterWithJoinCondition → misc-rules.iq
- testPullConstantIntoFilter → misc-rules.iq
- testSimplifyFilter → misc-rules.iq

RelBuilder-based filter tests (testFilterSortTranspose*,
testFilterRemoveIsNotDistinctFromRule, etc.) are not migrated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrated 16 tests from RelOptRulesTest.java + XML to Quidem .iq scripts:

In reduce-expressions.iq (6 tests):
- testCasePushIsAlwaysWorking
- testProjectOverWithAvg
- testReduceConstantsWindow
- testReduceConstantsWithMultipleOrderByWindow
- testReduceNullableToNotNull
- testReduceValuesToEmpty

New prune-empty.iq (10 tests):
- testEmptyAggregate
- testEmptyAggregateEmptyKey
- testEmptyIntersect
- testEmptyMinus, testEmptyMinus2, testEmptyMinus3
- testEmptyProject, testEmptyProject2
- testEmptySort
- testEmptySortLimitZero

PruneEmptyRules fields are referenced as "PruneEmptyRules.INSTANCE_NAME"
in !sub-plan arguments (already supported by getCoreRule()).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 3, 2026

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.

1 participant