Skip to content

Disallow duplicate CTE aliases#13664

Merged
gortiz merged 3 commits into
apache:masterfrom
yashmayya:duplicate-cte-alias
Jul 19, 2024
Merged

Disallow duplicate CTE aliases#13664
gortiz merged 3 commits into
apache:masterfrom
yashmayya:duplicate-cte-alias

Conversation

@yashmayya
Copy link
Copy Markdown
Contributor

@yashmayya yashmayya commented Jul 19, 2024

  • Currently, a query like WITH tmp AS (SELECT * FROM a LIMIT 1), tmp AS (SELECT * FROM a LIMIT 2) SELECT * FROM tmp doesn't return an error and runs fine.
  • By default, Calcite just uses the last CTE for the alias in such cases. However, this can lead to confusing and unexpected results in case there was a human error while writing a complex query with many CTEs.
  • In databases like Postgres and MySQL too, such queries return a clear error.
  • Postgres:
ERROR:  WITH query name "tmp" specified more than once
  • MySQL:
ERROR 1066 (42000): Not unique table/alias: 'tmp'
  • Pinot (after this patch):
Duplicate alias in WITH: 'tmp' at line 1, column 40

@yashmayya yashmayya added enhancement Improvement to existing functionality multi-stage Related to the multi-stage query engine labels Jul 19, 2024
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jul 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 61.92%. Comparing base (59551e4) to head (1359261).
Report is 789 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master   #13664      +/-   ##
============================================
+ Coverage     61.75%   61.92%   +0.17%     
- Complexity      207     1321    +1114     
============================================
  Files          2436     2554     +118     
  Lines        133233   140492    +7259     
  Branches      20636    21855    +1219     
============================================
+ Hits          82274    86997    +4723     
- Misses        44911    46848    +1937     
- Partials       6048     6647     +599     
Flag Coverage Δ
custom-integration1 <0.01% <0.00%> (-0.01%) ⬇️
integration <0.01% <0.00%> (-0.01%) ⬇️
integration1 <0.01% <0.00%> (-0.01%) ⬇️
integration2 ?
java-11 61.92% <100.00%> (+0.21%) ⬆️
java-21 <0.01% <0.00%> (-61.63%) ⬇️
skip-bytebuffers-false 61.92% <100.00%> (+0.17%) ⬆️
skip-bytebuffers-true <0.01% <0.00%> (-27.73%) ⬇️
temurin 61.92% <100.00%> (+0.17%) ⬆️
unittests 61.91% <100.00%> (+0.17%) ⬆️
unittests1 46.40% <100.00%> (-0.49%) ⬇️
unittests2 27.73% <0.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@yashmayya yashmayya force-pushed the duplicate-cte-alias branch from d2cd08c to 5fccf83 Compare July 19, 2024 12:46
@yashmayya yashmayya marked this pull request as ready for review July 19, 2024 14:12
@yashmayya yashmayya requested review from Jackie-Jiang and gortiz July 19, 2024 14:12
for (SqlNode sqlWithItem : with.withList) {
for (String name : ((SqlWithItem) sqlWithItem).name.names) {
if (withNames.contains(name)) {
throw new RuntimeException("Duplicate alias in WITH: '" + name + "'");
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.

Can we also provide lines? Given we are at SqlNode here, we should be able to access them

assertEquals(tableNames.get(0), "a");
}

@Test(expectedExceptions = RuntimeException.class)
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.

can we also verify the message is what we expect?

Copy link
Copy Markdown
Contributor Author

@yashmayya yashmayya Jul 19, 2024

Choose a reason for hiding this comment

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

I'd initially tried that with expectedExceptionsMessageRegExp but looks like that only checks the top level exception message (and not nested exceptions) which in our case is the RuntimeException with Error composing query plan for:... from here. I'm not sure why we use TestNG and not JUnit which is a lot more feature rich 🤷

I updated the test to use a more old school style of catching the expected exception and making assertions in the catch block.

Edit: Never mind, looks like TestNG also supports the assertThrows / expectThrows style.

@gortiz gortiz merged commit 2ccfa74 into apache:master Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to existing functionality multi-stage Related to the multi-stage query engine

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants