Skip to content

IGNITE-28899 Calcite. Fix litmus error during join#13389

Open
zstan wants to merge 4 commits into
apache:masterfrom
zstan:ignite-28899
Open

IGNITE-28899 Calcite. Fix litmus error during join#13389
zstan wants to merge 4 commits into
apache:masterfrom
zstan:ignite-28899

Conversation

@zstan

@zstan zstan commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

protected final boolean distributed;

/** Flag indicating that join is in finishing stage (one of the inputs are ended, no more rows will be produced). */
protected boolean finishing;

@zstan zstan Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

how to check this fix : revert all these changes and run : CorrelatesIntegrationTest#testCorrelatesCollision probably need to disable rules:
//NestedLoopJoinConverterRule.INSTANCE,
//HashJoinConverterRule.INSTANCE,
or simply run on master with commented rules

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also seems JoinBuffersExecutionTest need to be expanded somehow, cause it need to catch such a cases but it does not.

public static final double EQUI_COEFF = 0.8;

/** */
public static final double FK_WITH_PK_COEFF = 0.4;

@zstan zstan Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

all these coeffs is kinda hacks which need to be removed after statistics layer will properly work

continue;

// Keys can relate to affinity not pk, just assumption here.
ImmutableIntList distKeys = table.distribution().getKeys();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

of course we need to have 'real pk' here, but fix it right now - seems too huge.

inputRows += mq.getRowCount(input);

double mem = 0.5 * inputRows * aggregateFieldsCount() * IgniteCost.AVERAGE_FIELD_SIZE;
double mem = 0.7 * inputRows * aggregateFieldsCount() * IgniteCost.AVERAGE_FIELD_SIZE;

@zstan zstan Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

empiric constants need to be fixed cause row count estimation is changed for now and some tests (2-3) are fails, all empirics need to be reevaluated during further (i hope) statistics activity changes.


/** Cost of a lookup at the hash. */
public static final double HASH_LOOKUP_COST = 10;
public static final double HASH_LOOKUP_COST = 4;

@zstan zstan Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

'1' greater than ROW_COMPARISON_COST that correlates, in common, with LN complexity search of hash map, all these empirics need to be fixed during real statistics refactoring activity and currently changed only for store as more as possible tests passed and not changed. I think we understand that tests like we expect affinity distribution some kind of fiction for now and coveres just a little scope of variants.

prepareTables();

String sql = "SELECT sum(i.price * i.amount)" +
String sql = "SELECT /*+ MERGE_JOIN */ sum(i.price * i.amount)" +

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sometimes i observe hashJoin here, i really don`t know what algo is more preferably here and i think it need to be discovered more accurate in further activities.

private static final int DATE_DIM_SIZE = 73_049;

/** */
private static final String SELECT = "SELECT /*+ DISABLE_RULE(" +

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Of course it work perfectly well without this disablings, i just afraid about some king of flaky...

* @throws Exception If failed.
*/
@Test
public void testHashTableAndUnnestJoin() throws Exception {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

don`t know here, probably we need to remove this test cause it shows nothing for now and returns to it in further activities ?

@zstan
zstan marked this pull request as ready for review July 24, 2026 12:30
@zstan
zstan requested a review from Copilot July 24, 2026 12:30

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.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Updates Calcite planner metadata/costing and merge-join execution behavior to address a Calcite litmus failure seen during join planning/execution (IGNITE-28899), and adds regression tests to cover the scenario.

Changes:

  • Reworked join row-count estimation and adjusted join cost formulas/constants to influence plan selection.
  • Modified merge-join runtime node control flow around buffering and early termination.
  • Added new planner/integration tests and updated several existing assertions to match the new behavior.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java Registers the new join row-count estimation planner test in the suite.
modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java Adds the new litmus regression integration test to the suite.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/hints/JoinTypeHintPlannerTest.java Relaxes/adjusts hint-related plan assertions (notably around wrong-table hints).
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/UncollectPlannerTest.java Updates plan shape expectations for UNNEST + join planning.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlanSplitterTest.java Refactors colocation assignments setup to reuse a single assignments instance.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/JoinRowCountEstimationTest.java New planner tests validating join row-count estimation logic.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/CorrelatedSubqueryPlannerTest.java Updates plan assertion for table scan condition presence.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AggregatePlannerTest.java Removes an early return that skipped part of a test scenario.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/QueryBlockingTaskExecutorIntegrationTest.java Adds hint to force merge join and simplifies plan matching into a single regex check.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LitmusCheckIntegrationTest.java New integration test meant to catch Calcite litmus exceptions/regressions.
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/DistributedJoinIntegrationTest.java Forces MERGE_JOIN via hint for deterministic join plan coverage.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java Adds a helper to build a target mapping from a projected bitset.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/set/IgniteSetOp.java Adjusts memory estimation coefficient used in set-op costing.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteNestedLoopJoin.java Revises NLJ cost computation to use metadata row-count and applies an additional penalty factor.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteMergeJoin.java Revises merge join cost computation to use metadata row-count.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteHashJoin.java Revises hash join cost computation to use metadata row-count.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteCorrelatedNestedLoopJoin.java Revises CNLJ cost computation to use metadata row-count.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/cost/IgniteCost.java Changes the hash lookup cost constant affecting planner decisions.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdSelectivity.java Updates metadata provider wiring and exposes selectivity constants for tests/consumers.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdRowCount.java Implements custom join row-count estimation with PK/FK heuristics and new metadata provider wiring.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdColumnOrigins.java Updates metadata provider wiring and minor indentation cleanup.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/MergeJoinNode.java Reworks buffering/join scheduling and replaces “finishing” cleanup with immediate downstream end conditions.
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java Removes a previously-added workaround disabling Correlate assertions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +398 to +403
if (requested > 0 && (leftFinished() || rightFinished(true))) {
requested = 0;
downstream().end();

return;
}
Comment on lines 314 to +317
double selectivity = mq.getSelectivity(rel, rel.getCondition());

if (F.isEmpty(leftKeys) || F.isEmpty(rightKeys))
return left * right * selectivity;
return leftRowCnt * rightRowCnt * selectivity;
Comment on lines +298 to +306
static <T extends RelNode> Predicate<RelNode> nodeRowCount(String nodePattern, Matcher<Integer> rowCountMatcher) {
Pattern pattern = Pattern.compile(".*" + nodePattern
+ "\\(.*?rowcount = (?<rowcount>\\d+).*");

return node -> {
String plan = RelOptUtil.dumpPlan("", node, SqlExplainFormat.TEXT, SqlExplainLevel.ALL_ATTRIBUTES);

String sanitized = plan.replace("\n", "");
java.util.regex.Matcher matcher = pattern.matcher(sanitized);
Comment on lines +410 to +413
// Need to be removed after :
// TODO: https://issues.apache.org/jira/browse/IGNITE-28911
assertPlan(String.format(sqlTpl, hintPref + "('UNEXISTING') */"), schema,
nodeOrAnyChild(isInstanceOf(joinRel)), disabledRules);
p -> true, disabledRules);
Comment on lines +455 to +465
/**
* Creates mapping from given projection.
*
* <p>Projection is a list of integers representing an index of element from source
* at desired position.
*
* @param sourceSize Size of the source.
* @param bitSet Desired projection.
* @return Mapping for given projection.
*/
public static Mappings.TargetMapping projectedMapping(ImmutableBitSet bitSet, int sourceSize) {
Comment on lines +52 to +53
* Sets the log level for logger ({@link #log}) to {@link Level#DEBUG}. The log level will be resetted to
* default in {@link #afterTest()}.
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.

2 participants