I am seeing a regression in Calcite 1.41.0 on a SQL UPDATE call that worked in
Calcite 1.40.0. For example, using the TPC-DS schema, the following query:
UPDATE customer SET c_first_name = 'Alice' WHERE c_customer_sk = 'some_key'
fails with:
java.lang.AssertionError: Unexpected select list size. Select list should
contain both target table columns and set expressions
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertUpdate(SqlToRelConverter.java:4472)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertQueryRecursive(SqlToRelConverter.java:3997)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertQuery(SqlToRelConverter.java:631)
It is failing on this check, introduced in commit
95350ed1a449bbb2f008fcf2b704544e7d95c410:
https://github.com/apache/calcite/blob/42ff295d6e28672a2ad81b1c30abfbdf44544212/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java#L4469-L4475
If I take the current state of the Calcite main branch (which also exhibits the
same failure) and revert commit 95350ed1a449bbb2f008fcf2b704544e7d95c410, the
resulting code allows the SQL UPDATE above to run successfully.
Looking in the debugger t the failing case, the SqlNode passed into
SqlRelConverter.convertQuery() (with needsValidation=true, top=true) contains:
UPDATE `CUSTOMER` SET `C_FIRST_NAME` = 'Alice'
WHERE `C_CUSTOMER_SK` = 'some_key'
The sourceSelect for the SqlNode is null. Once execution passes the line:
query = validator().validate(query);
The SqlNode (query) has a sourceSelect of:
SELECT *, CAST('Alice' AS CHAR(16) CHARACTER SET `ISO-8859-1`) AS `EXPR$0`
FROM `CUSTOMER`
WHERE `CUSTOMER`.`C_CUSTOMER_SK` = CAST('some_key' AS BIGINT)
This means that its selectList has size 2. When it reaches the check linked
above, this size is expected to equal the sum of the targetTable rowType
fieldCount (18) and call sourceExpressionList size (1). 2 != 19 so the
assertion fails.
Should I open a new Jira and add this information?
Perhaps there is a different way I can be driving the SQL-to-Rel conversion
that avoids the problem? I notice some UPDATE unit tests included with the
commit that introduces the problem pass. A (very) quick glance at these cases
suggests that the query hitting the assertion has been expanded so that the
SELECT includes all the target column names rather than '*', allowing the
assertion check to pass. I don't know why.