cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Tyler Hobbs (JIRA)" <>
Subject [jira] [Commented] (CASSANDRA-8779) Able to unintentionally nest tuples during insert
Date Fri, 13 Feb 2015 19:44:12 GMT


Tyler Hobbs commented on CASSANDRA-8779:

So here's what's happening:

The driver serializes the tuple as {{\x00\x01\x00\x00\x00\x13\x00\x00\x00\x03foo\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\{}}.
 The leading {{\x00\x01}} is the number of arguments (1), and then the {{\x00\x00\x00\13}}
is the length of the first (and only) argument.

Cassandra is expecting an AsciiType argument, so it reads the length (16 bytes) and then interprets
the rest of the bytes as the string.  Since tuples can omit elements at the end of the tuple,
the other elements end up as null.

Part of the reason this isn't caught on either end is because it's a Query message with attached
binary query parameters, instead of an Execute message (for a prepared statement) or a Query
with parameters already integrated into the query string.  So, the driver doesn't know what
type it should be targeting.  It's guessing based on the query parameter type (the Ruby or
Java type).  Cassandra does know what type it's expecting, but the serialization format doesn't
include type information, so as long as the parameters can be validated/interpreted as the
expected type, there won't be an error.

One reasonable way to prevent this sort of error would be to include the typecode alongside
the serialized query parameter.  The drivers would set that typecode to whatever type they're
serializing the data as.  Server-side, Cassandra would validate that the typecode matches
the expected type.

We could only require this for Query messages with attached parameters (since drivers can
enforce types for Execute messages), or we could be extra safe and require it for Execute
messages as well (which might be overkill).

[~slebresne] what do you think about the above suggestion?

> Able to unintentionally nest tuples during insert
> -------------------------------------------------
>                 Key: CASSANDRA-8779
>                 URL:
>             Project: Cassandra
>          Issue Type: Bug
>         Environment: Linux Mint 64-bit | ruby-driver 2.1 | java-driver 2.1 | C* 2.1.2
>            Reporter: Kishan Karunaratne
>            Assignee: Tyler Hobbs
> If I insert a tuple using an extra pair of ()'s, C* will let me do the insert, but (incorrectly)
creates a nested tuple as the first tuple value. Upon doing a select statement, the result
is jumbled and has weird binary in it (which I wasn't able to copy into here).
> Example using ruby-driver:
> {noformat}
> session.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen<tuple<ascii,
bigint, boolean>>)")
> complete ='foo', 123, true)
> session.execute("INSERT INTO mytable (a, b) VALUES (0, (?))", arguments: [complete])
           # extra ()'s here
> result = session.execute("SELECT b FROM mytable WHERE a=0").first
> p result['b']
> {noformat}
> Output:
> {noformat}
> #<Cassandra::Tuple:0x97b328 (fo{, , )>
> {noformat}
> Bug also confirmed using java-driver. 
> Example using java-driver:
> {noformat}
> session.execute("CREATE TABLE mytable (a int PRIMARY KEY, b frozen<tuple<ascii,
int, boolean>>)");
> TupleType t = TupleType.of(DataType.ascii(), DataType.cint(), DataType.cboolean());
> TupleValue complete = t.newValue("foo", 123, true);
> session.execute("INSERT INTO mytable (a, b) VALUES (0, (?))", complete); // extra ()'s
> TupleValue r = session.execute("SELECT b FROM mytable WHERE a=0").one().getTupleValue("b");
> System.out.println(r);
> {noformat}
> Output:
> {noformat}
> ('foo{', null, null)
> {noformat}

This message was sent by Atlassian JIRA

View raw message