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

Maksim Zhuravkov updated IGNITE-20835:
--------------------------------------
    Description: 
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}




  was:
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 works 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}





> 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