You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Alexander Paschenko (JIRA)" <ji...@apache.org> on 2016/12/02 22:31:58 UTC

[jira] [Commented] (IGNITE-4362) DML: the multiplication for SET uses the data type for the result from the right side

    [ https://issues.apache.org/jira/browse/IGNITE-4362?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15716737#comment-15716737 ] 

Alexander Paschenko commented on IGNITE-4362:
---------------------------------------------

[~skozlov], you are misinterpreting the exception. It's not about type of {{shortCol}}, it's about how H2 handles numeric types. And it turns out to be that it handles them just like Java does - for example, when multiplying {{short}} by {{int}}, it promotes {{short}} to {{int}}, but it *does not* promote neither to {{long}} - whatever it is we're going to do with result. So exception is not because {{shortCol * 100000}} does not fit into {{short}}, but because {{(int) shortCol * 100000}} does not fit into {{int}}.

Say, if we have following expression in Java, {{long val = 2300000 * 100000}}, then we *will not* get correct results because of int overflow (because we have {{int * int -> int}} on the right, and *not* {{int * int -> long}} just because we have long on the left.

In order for the right part of expression to be {{long}}, *at least one of the int operands has to be long*. So just cast either {{shortCol}} or {{100000}} in your example to {{BIGINT}},  and you'll be good.

Example:

{code:java}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestSimple {
    public static void main(String... args) throws Exception {
        org.h2.Driver.load();
        Connection conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
        Statement stat = conn.createStatement();
        stat.execute("CREATE MEMORY TABLE IF NOT EXISTS TBL(longCol BIGINT, shortCol SMALLINT) NOT PERSISTENT");
        stat.execute("INSERT INTO TBL (shortCol) VALUES (23000)");
        stat.execute("UPDATE TBL SET longCol = shortCol*100000");
        ResultSet rs = stat.executeQuery("SELECT longCol from TBL");
        rs.next();
        Object o = rs.getObject(1);
        assert o instanceof Long;
        System.out.println((Long) o);
        conn.close();
    }
}
{code}

This fails on {{UPDATE}} with the exception you created this issue about. Just change {{UPDATE}} query to

{code:sql}
UPDATE TBL SET longCol = CAST(shortCol as BIGINT) *100000
{code}

and it will work. So this issue has nothing to do neither with Ignite, nor with its DML, nor with implementation of {{UPDATE}} in particular, it's about H2's internal behavior. Won't fix.

Proof: {{org.h2.expression.Operation#optimize}}, at the very end of the method there's following code computing resulting type of expression, and it reads
{{dataType = Value.getHigherOrder(l, r);}}
So result type cares only about operands, nothing else.

> DML: the multiplication for SET uses the data type for the result from the right side
> -------------------------------------------------------------------------------------
>
>                 Key: IGNITE-4362
>                 URL: https://issues.apache.org/jira/browse/IGNITE-4362
>             Project: Ignite
>          Issue Type: Bug
>            Reporter: Sergey Kozlov
>            Assignee: Alexander Paschenko
>
> Lets run following statement:
> {{update AllTypes set longCol = shortCol*100000 where _key = ?}}
> The exception below has been thrown if {{shortCol*100000}} violates the short integer borders:
> {noformat}
> Caused by: org.h2.jdbc.JdbcSQLException: ... "-46000"
> Numeric value out of range: "-46000"; SQL statement:
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)