-
Notifications
You must be signed in to change notification settings - Fork 2.5k
[CALCITE-7457] VALUES and SELECT produce different validation results for the same expression #4858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1322,13 +1322,20 @@ void testLikeAndSimilarFails() { | |
| expr("values 1.0 + ^NULL^") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| // SELECT produces DECIMAL(3, 1) because inferUnknownTypes infers | ||
| // NULL as DECIMAL(2, 1) via FIRST_KNOWN, and DECIMAL(2,1) + DECIMAL(2,1) | ||
| // = DECIMAL(3, 1) | ||
| sql("select 1.0 + NULL from (values (0)) as t(x)") | ||
| .columnType("DECIMAL(3, 1)"); | ||
| expr("values 1.0 + NULL") | ||
| .columnType("DECIMAL(2, 1)"); | ||
| .columnType("DECIMAL(3, 1)"); | ||
| expr("1.0 + ^NULL^") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| sql("select 1.0 + NULL from (values (0)) as t(x)") | ||
| .columnType("DECIMAL(3, 1)"); | ||
| expr("1.0 + NULL") | ||
| .columnType("DECIMAL(2, 1)"); | ||
| .columnType("DECIMAL(3, 1)"); | ||
|
|
||
| // FIXME: SQL:2003 does not allow raw NULL in IN clause | ||
| expr("1 in (1, null, 2)").ok(); | ||
|
|
@@ -1581,9 +1588,14 @@ void testLikeAndSimilarFails() { | |
| expr("LOCALTIME").ok(); // fix sqlcontext later. | ||
| wholeExpr("LOCALTIME(1+2)") | ||
| .fails("Argument to function 'LOCALTIME' must be a literal"); | ||
| wholeExpr("LOCALTIME(NULL)") | ||
| // With type coercion disabled, inferUnknownTypes rejects NULL before | ||
| // LOCALTIME can validate. SELECT produces the same error. | ||
| sql("select LOCALTIME(^NULL^) from (values (0)) as t(x)") | ||
| .withTypeCoercion(false) | ||
| .fails("Argument to function 'LOCALTIME' must not be NULL"); | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| expr("LOCALTIME(^NULL^)") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| wholeExpr("LOCALTIME(NULL)") | ||
| .fails("Argument to function 'LOCALTIME' must not be NULL"); | ||
| wholeExpr("LOCALTIME(CAST(NULL AS INTEGER))") | ||
|
|
@@ -7924,6 +7936,35 @@ void testGroupExpressionEquivalenceParams() { | |
| .ok(); | ||
| } | ||
|
|
||
| /** | ||
| * Test case for | ||
| * <a href="https://issues.apache.org/jira/browse/CALCITE-7457">[CALCITE-7457] | ||
| * VALUES and SELECT produce different validation results for the same expression</a>. | ||
| */ | ||
| @Test void testSelectVsValuesValidation() { | ||
| sql("select 1.0 + NULL from (values (0)) as t(x)") | ||
| .columnType("DECIMAL(3, 1)"); | ||
| expr("1.0 + NULL") | ||
| .columnType("DECIMAL(3, 1)"); | ||
|
|
||
| sql("select 1 + ? from (values (0)) as t(x)").ok(); | ||
| expr("1 + ?").ok(); | ||
|
|
||
| sql("select 1 + ^NULL^ from (values (0)) as t(x)") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| expr("1 + ^NULL^") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
|
|
||
| sql("select LOCALTIME(^NULL^) from (values (0)) as t(x)") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| expr("LOCALTIME(^NULL^)") | ||
| .withTypeCoercion(false) | ||
| .fails("(?s).*Illegal use of .NULL.*"); | ||
| } | ||
|
|
||
| @Test void testPercentileFunctionsBigQuery() { | ||
| final SqlOperatorTable opTable = operatorTableFor(SqlLibrary.BIG_QUERY); | ||
| final String sql = "select\n" | ||
|
|
@@ -8104,15 +8145,28 @@ void testGroupExpressionEquivalenceParams() { | |
| + " overlaps (date '1-2-3', date '1-2-3')^\n" | ||
| + "or false") | ||
| .fails("(?s).*Cannot apply 'OVERLAPS' to arguments of type .*"); | ||
| // row with 3 arguments as right argument to overlaps | ||
| // row with 3 arguments as right argument to overlaps. | ||
| // validateValues checks ROW structure before OVERLAPS validates, | ||
| // producing "Unequal number of entries in ROW expressions". | ||
| // SELECT produces the same error. | ||
| sql("select true or" | ||
| + " (date '1-2-3', date '1-2-3')" | ||
| + " overlaps ^(date '1-2-3', date '1-2-3', date '1-2-3')^" | ||
| + " or false from (values (0)) as t(x)") | ||
| .fails("(?s).*Unequal number of entries in ROW expressions.*"); | ||
| expr("true\n" | ||
| + "or ^(date '1-2-3', date '1-2-3')\n" | ||
| + " overlaps (date '1-2-3', date '1-2-3', date '1-2-3')^\n" | ||
| + "or (date '1-2-3', date '1-2-3')\n" | ||
| + " overlaps ^(date '1-2-3', date '1-2-3', date '1-2-3')^\n" | ||
| + "or false") | ||
| .fails("(?s).*Cannot apply 'OVERLAPS' to arguments of type .*"); | ||
| expr("^period (date '1-2-3', date '1-2-3')\n" | ||
| + " overlaps (date '1-2-3', date '1-2-3', date '1-2-3')^") | ||
| .fails("(?s).*Cannot apply 'OVERLAPS' to arguments of type .*"); | ||
| .fails("(?s).*Unequal number of entries in ROW expressions.*"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a regression, there is not ROW expression in the original program. The user will have difficulties finding the location of this error.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are correct that the original query does not contain a ROW. However, during parsing, the OVERLAPS arguments are wrapped inside a ROW prior to any validation Currently, VALUES follows the proper execution order: Operand inference throws an exception, but it probably should not. It should probably simply leave the types unfilled. Operand validation would then fail with something like Regarding the regression, I'm not sure it is regression, since SELECT already had the same behavior. Also
Ironically,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know why no checks were run in CI?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, this is because I add
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please run all the tests to check that there aren't other tests affected by the ROW message?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those all ran before I added the LGTM-will-merge-soon label. Anyway, I made a small tweak based on #4858 (comment). Re-running now |
||
| // SELECT produces the same error for mismatched ROW sizes | ||
| sql("select period (date '1-2-3', date '1-2-3')" | ||
| + " overlaps ^(date '1-2-3', date '1-2-3', date '1-2-3')^" | ||
| + " from (values (0)) as t(x)") | ||
| .fails("(?s).*Unequal number of entries in ROW expressions.*"); | ||
| expr("period (date '1-2-3', date '1-2-3')\n" | ||
| + " overlaps ^(date '1-2-3', date '1-2-3', date '1-2-3')^") | ||
| .fails("(?s).*Unequal number of entries in ROW expressions.*"); | ||
| expr("true\n" | ||
| + "or ^(1, 2) overlaps (2, 3)^\n" | ||
| + "or false") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should this inferred type be different?
Something is off.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I explained above, in the
SELECTsection, why this happens. I'm not saying it's the correct behavior and I would expect that1.0 + NULL = NULLwith typeDECIMAL(2,1)(common not null values type) in this case, but currently it works like thatThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you say SELECT 1.0 + NULL already was DECIMAL(3,1), but when used in VALUES the result was different?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, if you open task description - https://issues.apache.org/jira/browse/CALCITE-7457. You can see test case for main branch