dssysolyatin commented on code in PR #4572:
URL: https://github.com/apache/calcite/pull/4572#discussion_r2416247477


##########
core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java:
##########
@@ -1141,16 +1138,21 @@ public Result visit(TableModify modify) {
       return result(sqlInsert, ImmutableList.of(), modify, null);
     }
     case UPDATE: {
+      final List<String> updateColumnList =
+          requireNonNull(modify.getUpdateColumnList(),
+              () -> "modify.getUpdateColumnList() is null for " + modify);
       final Result input = visitInput(modify, 0);
+      final SqlSelect sourceSelect = input.asSelect();

Review Comment:
   Let's assume we have this input expression:
   ```
   UPDATE `foodmart`.`product` SET `product_name` = `product_name` || 'calcite' 
WHERE `product_id` > 10
   ```
   
   calcite parser will parse it as:
   ```
   SqlUpdate(
       targetColumnList = [product_name], 
       sourceExpressionList = [`product_name` || 'calcite'], 
       condition = `product_id` > 10,
       sourceSelect = null <-- sourceSelect is null
   )
   ```
   
   Then, `ValidatorImpl.createSourceSelectForUpdate` changes it into:
   ```
   SqlUpdate(
       targetColumnList = [product_name], 
       sourceExpressionList = [`product_name` || 'calcite'], 
       condition = `product_id` > 10,
       sourceSelect = "SELECT *, `product_name` || 'calcite' AS `EXPR$0` FROM 
`foodmart`.`product` WHERE `product_id` > 10"
   )
   ```
   
   Next, `SqlToRelConverter` converts it into this logical plan:
   ```
   LogicalTableModify(
     table=[[foodmart, product]], operation=[UPDATE], 
     updateColumnList=[[product_name]], 
     sourceExpressionList=[[CAST(||($3, 'calcite')):VARCHAR(60) NOT NULL]], 
     flattened=[true]
   )
     LogicalProject(product_class_id=[$0], product_id=[$1], <all 14 fields>,  
EXPR$0=[||($3, 'calcite')])
       LogicalFilter(condition=[>($1, 10)])
         LogicalTableScan(table=[[foodmart, product]])
   ```
   
   `LogicalTableModify.sourceExpressionList` is built using the blackboard from 
LogicalProject, but it doesn’t use expressions directly from `LogicalProject`. 
(This is one more reason my previous fix was incorrect. It lost type coercion 
in this case).
   
   Now, answer on your question: "What is this SqlSelect node"
   
   `RelToSqlConverter` transforms `TableModify.input` into:
   ```
   SELECT `product_class_id`, `product_id`, `brand_name`, `product_name`, 
`SKU`, `SRP`, `gross_weight`, `net_weight`, `recyclable_package`, `low_fat`, 
`units_per_case`, `cases_per_pallet`, `shelf_width`, `shelf_height`, 
`shelf_depth`, `product_name` || 'calcite' AS `EXPR$0`
   FROM `foodmart`.`product`
   WHERE `product_id` > 10
   ```
   
   Calcite code takes the WHERE clause for the UPDATE from this SELECT. We also 
need to convert `TableModify.sourceExpressionList` into a SqlNode based on the 
context of this SELECT (as we do when we convert SqlNode to RelNode). My 
current fix use this approach



-- 
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]

Reply via email to