David Capwell created CASSANDRA-19874:
-----------------------------------------
Summary: Function inference maybe unable to infer the correct
function or chooses one for a smaller type
Key: CASSANDRA-19874
URL: https://issues.apache.org/jira/browse/CASSANDRA-19874
Project: Cassandra
Issue Type: Bug
Components: CQL/Interpreter
Reporter: David Capwell
Here are 2 numeric examples where function inference doesn’t do the right thing
1) varint
Case 1: Wrong Bytes
{code}
BigInteger pk = BigInteger.valueOf(-42 + -42);
BigInteger ck = BigInteger.valueOf(42 + 42);
BigInteger v = BigInteger.valueOf(-8200 + -16990);
createTable("CREATE TABLE %s(pk varint, ck varint, v varint, PRIMARY KEY(pk,
ck))");
execute("INSERT INTO %s(pk, ck, v) VALUES (-42 + -42, 42 + 42, -8200 +
-16990)");
assertRows(execute("SELECT * FROM %s"),
row(pk, ck, v));
assertRows(execute("SELECT * FROM %s WHERE pk=?", pk),
row(pk, ck, v));
assertRows(execute("SELECT * FROM %s WHERE pk=? AND ck=?", pk, ck),
row(pk, ck, v));
{code}
This fails with
{code}
java.lang.AssertionError: Got less rows than expected. Expected 1 but got 0
{code}
The reason is that the "system._add: (int, int) -> int” function works for ints
rather than varint, which means the bytes created do not match the bytes that a
varint would have created!
In the example of -42 + -42 we get -84 which is a single byte for varint and 4
bytes for int. Since the bytes don’t match partition/clustering equality does
not match!
Case 2: Overflow
{code}
BigInteger pk =
BigInteger.valueOf(59463118).multiply(BigInteger.valueOf(-2171));
BigInteger ck = pk;
BigInteger v = pk;
createTable("CREATE TABLE %s(pk varint, ck varint, v varint, PRIMARY KEY(pk,
ck))");
execute("INSERT INTO %s(pk, ck, v) VALUES (59463118 * -2171, 59463118 * -2171,
59463118 * -2171)");
assertRows(execute("SELECT * FROM %s"),
row(pk, ck, v));
{code}
This fails with
{code}
java.lang.AssertionError: Invalid value for row 0 column 0 (pk of type varint),
expected <-129094429178> but got <-245410298>
Invalid value for row 0 column 1 (ck of type varint), expected <-129094429178>
but got <-245410298>
Invalid value for row 0 column 2 (v of type varint), expected <-129094429178>
but got <-245410298>
{code}
The reason for this is the same as above, we selected “system._multiply: (int,
int) -> int”, and if you do 59463118 * -2171 as an int it overflows and
produces -245410298. If you instead upgrade the 2 ints to a BigInteger and
then do the multiple you get -129094429178!
This isn’t a problem for other databases, here is an example with sqlite
{code}
sqlite> create table foo2(pk varint);
sqlite> insert into foo2(pk) values (59463118 * -2171);
sqlite> select * from foo2;
pk = -129094429178
{code}
2) smallint
{code}
createTable("CREATE TABLE %s(pk smallint, ck smallint, v smallint, PRIMARY
KEY(pk, ck)) WITH CLUSTERING ORDER BY (ck DESC)");
execute("INSERT INTO %s(pk, ck, v) VALUES (-42 + -42, 42 + 42, -42 + 42)");
{code}
Here the function selection fails as it can’t find a match
{code}
org.apache.cassandra.exceptions.InvalidRequestException: Ambiguous '+'
operation with args 42 and 42: use type hint to disambiguate, example '(int) ?'
at
org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest(RequestValidations.java:370)
at
org.apache.cassandra.cql3.functions.FunctionResolver.pickBestMatch(FunctionResolver.java:179)
at
org.apache.cassandra.cql3.functions.FunctionResolver.get(FunctionResolver.java:87)
at
org.apache.cassandra.cql3.functions.FunctionCall$Raw.prepare(FunctionCall.java:154)
{code}
The reason here is similar to the above… we think that the numbers “-42”, and
“42” are “int” type rather than “smallint” and we don’t find a function to pick
up!
If instead you just did
{code}
INSERT INTO %s(pk, ck, v) VALUES(-42, 42, 42)
{code}
We would then be able to infer that these are “smallint” rather than upcasting
them to “int”.
This isn’t a problem for other databases, here is an example from sqlite
{code}
sqlite> create table foo(pk smallint);
sqlite> insert into foo(pk) values (-42 + -42);
sqlite> select * from foo;
pk = -84
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]