xiangfu0 commented on code in PR #19263:
URL: https://github.com/apache/pinot/pull/19263#discussion_r4067182449


##########
pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java:
##########
@@ -129,6 +129,7 @@ public static SqlNodeAndOptions 
compileToSqlNodeAndOptions(String sql)
     try (StringReader inStream = new StringReader(sql)) {
       SqlParserImpl sqlParser = newSqlParser(inStream);
       SqlNodeList sqlNodeList = sqlParser.parseSqlStmtList();
+      sqlNodeList = (SqlNodeList) PostgreSqlCastRewriter.rewrite(sqlNodeList);

Review Comment:
   Thanks. This was a real bug, and your repro matched what I saw: 
`SqlPhysicalExplain` → `SqlExplain`, and `SqlPinotCreateMaterializedView`/DDL → 
`SqlBasicCall`/DQL, including with a nested subquery in the view body.
   
   Fixed in 6e2b49bf8c with a variant of option 1 that doesn't need to know the 
statement types. The rewriter no longer rebuilds anything: it replaces only the 
constant's direct parent in place (`SqlCall.setOperand` / `SqlNodeList.set`), 
so every other node keeps its identity and class. I preferred this to 
classifying first because 13 Pinot node types subclass `SqlCall`, and any of 
them that holds a query would have hit the same bug. It is also smaller than 
option 2.
   
   For it to be safe, every node that can directly hold a bytea constant has to 
support `setOperand`. I checked Calcite 1.42 and the grammar:
   
   - Every node under which Pinot's grammar accepts an arbitrary expression 
supports it: `SqlBasicCall`, `SqlNodeList`, `SqlSelect`, `SqlCase`, `SqlJoin`, 
`SqlWindow`, `SqlExplain`, `SqlWith`, and the rest.
   - The nodes that don't only appear where the grammar is restricted: 
`SqlOrderBy` offset/fetch (numeric only), `SqlHint`, `SqlTableRef`, and star 
`EXCLUDE`/`REPLACE` (disabled).
   - Pinot's own nodes hold queries, identifiers and literals. The one that 
holds an expression, `SqlPinotColumnDeclaration`'s `DEFAULT`, only accepts 
`Literal()`.
   
   If a future node does hold a constant somewhere it can't be replaced, the 
rewriter throws a `SqlCompilationException` naming the node instead of 
rebuilding it.
   
   Regression tests, each of which fails against the previous copy-on-write 
rewriter:
   
   - `CalciteSqlParserTest.testPostgreSqlByteaLiteralPreservesStatementNode` 
checks the node class and `PinotSqlType` for `EXPLAIN IMPLEMENTATION PLAN FOR`, 
`EXPLAIN PLAN FOR`, and `CREATE MATERIALIZED VIEW`, with the constant both 
directly in the body and in a nested subquery. Each case runs with 
`'\x01'::bytea`, `CAST('\x01' AS BYTEA)` and `X'01'`, and asserts the constant 
was still normalized.
   - `QueryCompilationTest.testPostgreSqlByteaLiteralKeepsPhysicalExplain` 
checks the user-visible symptom: the `EXPLAIN IMPLEMENTATION PLAN` output must 
equal the `X'01'` physical plan. Against the old code it gets the logical plan 
back.
   - `DdlCompilerMaterializedViewTest.definedSqlWithPostgreSqlByteaConstant` 
compiles a real materialized view end to end and asserts the stored 
`definedSQL`. Against the old code, the DDL compiler rejects it as an 
unsupported statement.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to