Skip to content

IGNITE-28925 SQL Calcite: Fix unexpected downstream().end() call for execution nodes - #13407

Closed
alex-plekhanov wants to merge 3 commits into
apache:masterfrom
alex-plekhanov:ignite-28925
Closed

IGNITE-28925 SQL Calcite: Fix unexpected downstream().end() call for execution nodes#13407
alex-plekhanov wants to merge 3 commits into
apache:masterfrom
alex-plekhanov:ignite-28925

Conversation

@alex-plekhanov

Copy link
Copy Markdown
Contributor

Thank you for submitting the pull request to the Apache Ignite.

In order to streamline the review of the contribution
we ask you to ensure the following steps have been taken:

The Contribution Checklist

  • There is a single JIRA ticket related to the pull request.
  • The web-link to the pull request is attached to the JIRA ticket.
  • The JIRA ticket has the Patch Available state.
  • The pull request body describes changes that have been made.
    The description explains WHAT and WHY was made instead of HOW.
  • The pull request title is treated as the final commit message.
    The following pattern must be used: IGNITE-XXXX Change summary where XXXX - number of JIRA issue.
  • A reviewer has been mentioned through the JIRA comments
    (see the Maintainers list)
  • The pull request has been checked by the Teamcity Bot and
    the green visa attached to the JIRA ticket (see tab PR Check at TC.Bot - Instance 1 or TC.Bot - Instance 2)

Notes

If you need any help, please email dev@ignite.apache.org or ask anу advice on http://asf.slack.com #ignite channel.

* ends exactly when the requested number of rows is satisfied.
*/
@Test
public void testRequestRowsAfterInputEnds() {

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.

It actually works witout fixes in the ALL and RANDOM tx. modes. Maybe we need assumeThat()

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.

For ALL and RANDOM plan is not the same as for NONE, for this reason plan checkers (matches method) are disabled for ALL and RANDOM. But result still should be valid for these tx modes even with another plan, so I think test is also helpful for these modes

/**
* Integration test for collect node.
*/
public class CollectIntegrationTest extends AbstractBasicIntegrationTest {

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.

One dedicated with-join test only for row in-out and buffer processing. Based on a plan which can variate. Maybe we need a special node execution test, WDYT?

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.

But this integration test shows that problem is not artifitial

@@ -114,6 +114,11 @@ public static <Row> CollectNode<Row> createCountCollector(ExecutionContext<Row>

if (waiting == 0)
source().request(waiting = IN_BUFFER_SIZE);

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.

Brw. Why di we reques more than even rowsCnt (in case of few rowsCnt)?

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.

This node always produce one row. But can collect it from unlimited data set, so it's worth to request from input more rows than requested from downstream.


if (waiting == 0)
source().request(waiting = IN_BUFFER_SIZE);
else if (waiting < 0) {

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.

It look like delayed downstream().end(). Why not in own void end()?

@alex-plekhanov alex-plekhanov Jul 29, 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.

Because we must keep invariant: "end downstream only if any rows is requested". If we request initially 1 row, push that row on "end()", we can't futher end downstream, since no rows more requested and it can lead to assertions. This case is shown in the new CollectIntegrationTest


checkState();

requested = rowsCnt;

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.

If we do conditional requested = 0;, probably we should not assignt it here

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.

We need filled requested field before doPush

if (reversed == null ? rows.isEmpty() : reversed.isEmpty()) {
if (requested > 0)
downstream().end();
if (requested > 0) {

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.

The new tests testRequestRowsAfterInputEnds() and CollectIntegrationTest seem to work witout this change. Why? Maybe we should add/fix some executions tests too.

@alex-plekhanov alex-plekhanov Jul 29, 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.

This change is only for code consistency. No bug here.

source().request(IN_BUFFER_SIZE);
}
else if (waiting < 0)
else if (waiting < 0) {

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.

Same. Looks like a delayed end(). Why not in own end(). It it some CLN node behaviour trait?

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.

See https://github.com/apache/ignite/pull/13407/changes#r3674976662 comment. It's common behaviour for all nodes.

break;

case END:
requested = 0;

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.

New testRequestRowsAfterInputEnds() test seems to work without any changes here. Is it an optimization? Do we need extra execution tests or at least comments?

@alex-plekhanov alex-plekhanov Jul 29, 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.

Yes, new tests only cover CollectNode and SortAggregateNode changes. Changes to CNLJ and SortNode are made to be consistent with other code. We have a lot of nodes with:

requested = 0;
downstream().end();

Sequential calls. These 4 nodes are only nodes with different logic. Change in SortNode it's not a bugfix, it's just code consistency, but CNLJ without requested = 0 can lead to the same problems as CollectNode and SortAggregateNode. I think it's possible to write reproducer for CNLJ, but maybe 2 tests is enoght to prove that requested = 0 should always be placed before downstream().end()?

# Conflicts:
#	modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
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