Skip to content

Conversation

@bestbeforetoday
Copy link
Member

@bestbeforetoday bestbeforetoday commented Jan 15, 2026

Both SQL STRPOS and POSITION functions are modelled by Calcite as Position. Parameters are substring followed by the input to be searched. This maps to the Substrait strpos function, which has the parameters of input to be searched followed by substring. The default mapping retains the argument order, which results in SQL being translated to incorrect Substrait, and correct Substrait translated to incorrect SQL. Round-trip between Substrait and SQL still works since the parameter order is reversed in both directions, resulting in the correct order again.

This change adds a custom function mapper to reverse the order of the first two parameters when converting between Calcite Position and Substrait strpos functions.

Closes #662

@bestbeforetoday bestbeforetoday marked this pull request as ready for review January 15, 2026 17:43
Copy link
Member

@benbellick benbellick left a comment

Choose a reason for hiding this comment

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

Just two minor comments but otherwise LGTM! Thanks for doing that 🚀

}

List<RexNode> operands = new ArrayList<>(call.getOperands());
Collections.swap(operands, 0, 1);
Copy link
Member

Choose a reason for hiding this comment

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

Probably not a bad idea to put a comment here just because we have some naked numbers used to reference parameters.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is the class Javadoc not sufficient?

Copy link
Member

Choose a reason for hiding this comment

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

It's probably fine, just my opinion if we wanted to make it extra clear. Feel free to ignore if you disagree.

}

String query = String.format("SELECT STRPOS(%s, %s) > 0 FROM strings", left, right);
@Test
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@Test
@Test
// Verifies POSITION→strpos parameter swap (#662).
// SQL POSITION(substring IN input) must become Substrait strpos(input, substring).

Just so someone has a reference for the future :)

@bestbeforetoday
Copy link
Member Author

@benbellick I changed the comments in both PositionFunctionMapper and StringFunctionTest to (hopefully) make things clearer, along the lines of your suggestions.

Both SQL STRPOS and POSITION functions are modelled by Calcite as
Position. Parameters are substring followed by the input to be searched.
This maps to the Substrait strpos function, which has the parameters of
input to be searched followed by substring. The default mapping retains
the argument order, which results in SQL being translated to incorrect
Substrait, and correct Substrait translated to incorrect SQL. Round-trip
between Substrait and SQL still works since the parameter order is
reversed in both directions, resulting in the correct order again.

This change adds a custom function mapper to reverse the order of the
first two parameters when converting between Calcite Position and
Substrait strpos functions.

Signed-off-by: Mark S. Lewis <Mark.S.Lewis@outlook.com>
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.

STRPOS and POSITION

2 participants