[ 
https://issues.apache.org/jira/browse/IGNITE-20835?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Iurii Gerzhedovich updated IGNITE-20835:
----------------------------------------
    Epic Link: IGNITE-22700

> Sql. Update statements incorrectly use scalar subqueries in target columns  
> ----------------------------------------------------------------------------
>
>                 Key: IGNITE-20835
>                 URL: https://issues.apache.org/jira/browse/IGNITE-20835
>             Project: Ignite
>          Issue Type: Bug
>          Components: sql
>            Reporter: Maksim Zhuravkov
>            Priority: Minor
>              Labels: ignite-3
>             Fix For: 3.0.0-beta2
>
>
> Update statements incorrectly use scalar subqueries in target columns, the 
> issues stems from the fact that scalar subquery in UPDATE  are not wrapped in 
> `SINGLE_VAL` aggregate. 
> Examples:
> {code:java}
>  @Test
>     public void ddml2() {
>   sql("CREATE TABLE vals (id INTEGER PRIMARY KEY, val INTEGER);");
>         sql("CREATE TABLE other_vals (id INTEGER PRIMARY KEY, other_val 
> INTEGER);");
>         sql("INSERT INTO vals VALUES (1, 0);");
>         sql("INSERT INTO vals VALUES (2, 0);");
>         sql("INSERT INTO other_vals VALUES (1, 1), (2, 2);");
>         // works
>         sql("INSERT INTO other_vals VALUES (3, (SELECT other_val FROM 
> other_vals WHERE id = 1));");
>         // works
>         sql("UPDATE vals SET val = (SELECT other_val FROM other_vals LIMIT 1) 
> WHERE id = 1");
>         // Should fail, because a subquery returns more than 1 result.
>         sql("UPDATE vals SET val = (SELECT other_val FROM other_vals) WHERE 
> id >= 2");
> }
> UPDATEs in MERGE statement are also affect by this issue:
> {code:java}
>  @Test
>     public void ddml2_1() {
>         sql("CREATE TABLE vals (id INTEGER PRIMARY KEY, val INTEGER);");
>         sql("CREATE TABLE other_vals (id INTEGER PRIMARY KEY, other_val 
> INTEGER);");
>         sql("INSERT INTO vals VALUES (1, 0);");
>         sql("INSERT INTO vals VALUES (2, 0);");
>         sql("INSERT INTO other_vals VALUES (1, 1), (2, 2);");
>         // works
>         sql("INSERT INTO other_vals VALUES (3, (SELECT other_val FROM 
> other_vals WHERE id = 1));");
>         // Fails with PK unique constraint is violated 
>         sql("MERGE INTO vals USING other_vals ON vals.id = other_vals.id "
>                 + "WHEN MATCHED THEN UPDATE SET val = (SELECT other_val FROM 
> other_vals WHERE id > 1) "
>                 + "WHEN NOT MATCHED THEN INSERT (id, val) VALUES (100, -1)");
>     }
> {code}
> {code}
> If we change val type to BIGINT we get another error:
> {code:java}
>  @Test
>     public void ddml3() {
>         sql("CREATE TABLE vals (id INTEGER PRIMARY KEY, val INTEGER);");
>         sql("CREATE TABLE other_vals (id INTEGER PRIMARY KEY, other_val 
> BIGINT);");
>         sql("INSERT INTO vals VALUES (1, 0);");
>         sql("INSERT INTO vals VALUES (2, 0);");
>         sql("INSERT INTO other_vals VALUES (1, 1), (2, 2);");
>         // works
>         sql("INSERT INTO other_vals VALUES (3, (SELECT other_val FROM 
> other_vals WHERE id = 1));");
>         // works
>         sql("UPDATE vals SET val = (SELECT other_val FROM other_vals LIMIT 1) 
> WHERE id = 1");
>         // Error
>         sql("UPDATE vals SET val = (SELECT other_val FROM other_vals) WHERE 
> id >= 2");
>     }
> {code}
> Error:
> {code:java}
> Caused by: java.lang.AssertionError
>       at 
> org.apache.calcite.sql.validate.implicit.AbstractTypeCoercion.needToCast(AbstractTypeCoercion.java:297)
>       at 
> org.apache.calcite.sql.validate.implicit.AbstractTypeCoercion.needToCast(AbstractTypeCoercion.java:250)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteTypeCoercion.needToCast(IgniteTypeCoercion.java:294)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteTypeCoercion.doCoerceColumnType(IgniteTypeCoercion.java:453)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteTypeCoercion.coerceColumnType(IgniteTypeCoercion.java:360)
>       at 
> org.apache.calcite.sql.validate.implicit.TypeCoercionImpl.coerceSourceRowType(TypeCoercionImpl.java:676)
>       at 
> org.apache.calcite.sql.validate.implicit.TypeCoercionImpl.querySourceCoercion(TypeCoercionImpl.java:646)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteTypeCoercion.querySourceCoercion(IgniteTypeCoercion.java:241)
>       at 
> org.apache.calcite.sql.validate.SqlValidatorImpl.checkTypeAssignment(SqlValidatorImpl.java:5112)
>       at 
> org.apache.calcite.sql.validate.SqlValidatorImpl.validateUpdate(SqlValidatorImpl.java:5219)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.validateUpdate(IgniteSqlValidator.java:187)
>       at org.apache.calcite.sql.SqlUpdate.validate(SqlUpdate.java:190)
>       at 
> org.apache.calcite.sql.validate.SqlValidatorImpl.validateScopedExpression(SqlValidatorImpl.java:1090)
>       at 
> org.apache.calcite.sql.validate.SqlValidatorImpl.validate(SqlValidatorImpl.java:796)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.validate(IgniteSqlValidator.java:161)
>       at 
> org.apache.ignite.internal.sql.engine.prepare.IgnitePlanner.validate(IgnitePlanner.java:204)
> {code}
> Insert statement behaves correctly:
> {code:java}
>  @Test
>  public void ddml0() {
>    sql("CREATE TABLE vals (id INTEGER PRIMARY KEY, val INTEGER);");
>    sql("CREATE TABLE other_vals (id INTEGER PRIMARY KEY, other_val 
> INTEGER);");
>    sql("INSERT INTO vals VALUES (1, 0);");
>    sql("INSERT INTO vals VALUES (2, 0);");
>    sql("INSERT INTO other_vals VALUES (1, 1), (2, 2);");
>     // Fails with `Subquery returned more than 1 value`
>     sql("INSERT INTO vals VALUES (3, (SELECT other_val FROM other_vals WHERE 
> id > 0));");
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to