You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cassandra.apache.org by "Hiller, Dean" <De...@nrel.gov> on 2013/09/24 14:36:53 UTC

is this correct, thrift unportable to CQL3Š.

Many applications in thrift use the wide row with composite column name and as an example, let's say golf score for instance and we end up with golf score : pk like so

null : pk56
null : pk45
89 : pk90
89: pk87
90: pk101
95: pk17

Notice that there are some who do not have a golf score(zero would not quite make sense and would be interpreted as a golf score).  I am hearing from this post if they are correct that this is not portable to CQL3???  Is this true?  http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3

(This sounds like a major deficit to me as the wide row now can only be used where actual values exist?????).  Is it possible to port this pattern to CQL3?

Thanks,
Dean



Re: is this correct, thrift unportable to CQL3Š.

Posted by Sylvain Lebresne <sy...@datastax.com>.
> Nulls should definitely stay null (that's an old DB debate), but  if this
> is a generic case, we might consider adding an emptyValue() helper method.
> Would that be possible Sylvain?
>

As said previously, debating this is outside the scope of this mailing
list, but to make it short, using empty values for types that don't
naturally support them like Integer is going to be painful (inserting is
one thing, handling them on the read side is another) and confusing no
matter what. So you should avoid it in the first place (and there is *tons*
of way to do that) and consequently adding an helper to do something you
should avoid is a bad idea.

--
Sylvain



>
>
>> --
>> Sylvain
>>
>>
>>>
>>> Ie. This sounds like this solution would be perfect if we can get rid of
>>> the exception piece.
>>>
>>> Thanks much!!!
>>> Dean
>>>
>>> From: Sylvain Lebresne <sylvain@datastax.com<mailto:sylvain@datastax.com
>>> >>
>>> Reply-To: "user@cassandra.apache.org<ma...@cassandra.apache.org>"
>>> <us...@cassandra.apache.org>>
>>> Date: Tuesday, September 24, 2013 10:58 AM
>>> To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <
>>> user@cassandra.apache.org<ma...@cassandra.apache.org>>
>>> Subject: Re: is this correct, thrift unportable to CQL3Š.
>>>
>>> On Tue, Sep 24, 2013 at 6:17 PM, Vikas Goyal <vikas@easility.com<mailto:
>>> vikas@easility.com>> wrote:
>>> Ok. Great. It works for String and Decimal/Float but not for integer
>>> data type..
>>> i.e,, if I am passing "" to the composite key column which is either
>>> text or float, it works..
>>>
>>> session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));
>>>
>>> But not working with bigint, int or varint..and getting following
>>> exception;
>>>
>>> Exception:Invalid type for value 1 of CQL type varint, expecting class
>>> java.math.BigInteger but class java.lang.String provided
>>>
>>> ..I am exploring more though..
>>>
>>> We're getting into details of the java driver at this point. For int,
>>> what you can do is:
>>>   boundStatement.setString("id", rowkey);
>>>   boundStatement.setBytesUnsafe("columnname", ByteBuffer.wrap(new
>>> byte[0]));
>>>   boundStatement.setBytes("columnvalue", ByteBuffer.wrap(value));
>>>
>>> In other words, the shorthand BoundStatement.bind() won't let you insert
>>> an empty value for types
>>> that don't naturally have an empty value (like int; keep in mind that an
>>> empty value is not the same
>>> than null). But you can circumvent that using setBytesUnsafe if you
>>> really want.
>>>
>>> Long story short, my advice would be to avoid using empty values for
>>> type that don't naturally have
>>> one (anything else than text and blob really). If you do, that's going
>>> to be painful (but possible) to
>>> work with, at least with the java driver (but for good reasons, java
>>> just doesn't have a good to
>>> represent an empty int value (again, you can have a null Integer but
>>> that's different)).
>>>
>>> --
>>> Sylvain
>>>
>>>
>>> Thanks a ton,
>>> Vikas Goyal
>>>
>>>
>>> On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sylvain@datastax.com
>>> <ma...@datastax.com>> wrote:
>>>
>>> However,we tried missing the value but it didn't work :(
>>>
>>> Right, because not providing a value is akin to having a null value (in
>>> the CQL3 sense of the term, which is different from what Dean asked about)
>>> and null values are not allowed for primary key columns.
>>> You could however insert an *empty* value if you wanted, which in you
>>> case is just inserting an empty string since colname is a string. Thrift
>>> doesn't allow more or less in that case.
>>>
>>> --
>>> Sylvain
>>>
>>>
>>>
>>> So our code is like below where we are using 3 values if colname is not
>>> null..else 2 values..
>>>
>>>             if (key != null) {
>>>                 PreparedStatement statement = session.prepare("INSERT
>>> INTO keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>>>                 BoundStatement boundStatement = new
>>> BoundStatement(statement);
>>>
>>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>>> rowKey), key, ByteBuffer.wrap(value)));
>>>             } else {
>>>                 PreparedStatement statement = session.prepare("INSERT
>>> INTO " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>>>                 BoundStatement boundStatement = new
>>> BoundStatement(statement);
>>>
>>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>>> rowKey), ByteBuffer.wrap(value)));
>>>           }
>>>
>>> And, I did that and getting this exception:
>>>
>>> Exception:Missing PRIMARY KEY part colname since colvalue is set
>>>
>>> And just FYI. Our Column Family definition is below:
>>>
>>> CREATE TABLE keys.StringIndice (id text,
>>> colname text,
>>> colvalue blob,
>>> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>>>
>>> Thanks again,
>>> Vikas Goyal
>>>
>>>
>>>
>>> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sylvain@datastax.com
>>> <ma...@datastax.com>> wrote:
>>> Short answer: not, this is not correct.
>>>
>>> Longer answer: what you call "null" is actually an empty value (which is
>>> *not* the same thing, unless you consider an empty string is the same thing
>>> than a null string). As it happens, C* always an empty value as a valid
>>> value for any type and that's true of both thrift and CQL3. What is true is
>>> that CQL3 discourage the use of empty values for type for which it doesn't
>>> particularly make sense (integers typically) by not having a particular
>>> easy to use syntax to input them. But that's supported nonetheless. If you
>>> use a prepared statement for instance (where you send values already
>>> serialized), nothing will prevent you from sending an empty value. Even if
>>> you don't want to use a prepared statement, CQL3 has conversion functions (
>>> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to
>>> do it (for instance, "blobAsInt(0x)" will be an empty int value).
>>>
>>> --
>>> Sylvain
>>>
>>>
>>>
>>> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <Dean.Hiller@nrel.gov
>>> <ma...@nrel.gov>> wrote:
>>> Many applications in thrift use the wide row with composite column name
>>> and as an example, let's say golf score for instance and we end up with
>>> golf score : pk like so
>>>
>>> null : pk56
>>> null : pk45
>>> 89 : pk90
>>> 89: pk87
>>> 90: pk101
>>> 95: pk17
>>>
>>> Notice that there are some who do not have a golf score(zero would not
>>> quite make sense and would be interpreted as a golf score).  I am hearing
>>> from this post if they are correct that this is not portable to CQL3???  Is
>>> this true?
>>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>>
>>> (This sounds like a major deficit to me as the wide row now can only be
>>> used where actual values exist?????).  Is it possible to port this pattern
>>> to CQL3?
>>>
>>> Thanks,
>>> Dean
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>
>
>
> --
>
> :- a)
>
>
> Alex Popescu
> Sen. Product Manager @ DataStax
> @al3xandru
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by Alex Popescu <al...@datastax.com>.
On Wed, Sep 25, 2013 at 12:22 AM, Sylvain Lebresne <sy...@datastax.com>wrote:

> On Tue, Sep 24, 2013 at 7:24 PM, Hiller, Dean <De...@nrel.gov>wrote:
>
>> Java has Integer as opposed to int which is what I represent "golf
>> scores" with so to speak in my example.  In this case, Integer can be null
>> but of course maps to "empty" just fine.  What about querying for all golf
>> scores that are "empty" then?
>>
>
> The DataStax java driver already "maps" a null Integer to a null CQL3
> column, and so it *cannot* also map it to an empty value. And even though
> you cannot have null CQL3 columns in the primary key, mapping a null
> Integer to an empty value would be highly confusing/inconsistent (from the
> point of view of the java driver) because:
> 1) having a null Integer map differently depending on whether the
> receiving column is in the PK or not would be messy/surprising.
> 2) it's not really technically possible because internally the driver does
> not always have the information of whether the receiving column is in the
> PK or not
> 3) what about strings? Should we also map a null String to an empty value
> when the column is in the PK? Because that would mean mapping a null java
> String to an empty CQL3 string value and that just feel wrong. And if we
> don't do it, then it means we treat Integer and String differently with
> respect to null and that's too would be pretty confusing.
>
> But anyway, all of that is pretty specific to the java driver, so maybe if
> you guys want to debate that further we should move to the driver mailing
> list:
> https://groups.google.com/a/lists.datastax.com/forum/#!forum/java-driver-user
>
>
Nulls should definitely stay null (that's an old DB debate), but  if this
is a generic case, we might consider adding an emptyValue() helper method.
Would that be possible Sylvain?


> --
> Sylvain
>
>
>>
>> Ie. This sounds like this solution would be perfect if we can get rid of
>> the exception piece.
>>
>> Thanks much!!!
>> Dean
>>
>> From: Sylvain Lebresne <sylvain@datastax.com<mailto:sylvain@datastax.com
>> >>
>> Reply-To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <
>> user@cassandra.apache.org<ma...@cassandra.apache.org>>
>> Date: Tuesday, September 24, 2013 10:58 AM
>> To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <
>> user@cassandra.apache.org<ma...@cassandra.apache.org>>
>> Subject: Re: is this correct, thrift unportable to CQL3Š.
>>
>> On Tue, Sep 24, 2013 at 6:17 PM, Vikas Goyal <vikas@easility.com<mailto:
>> vikas@easility.com>> wrote:
>> Ok. Great. It works for String and Decimal/Float but not for integer data
>> type..
>> i.e,, if I am passing "" to the composite key column which is either text
>> or float, it works..
>>
>> session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));
>>
>> But not working with bigint, int or varint..and getting following
>> exception;
>>
>> Exception:Invalid type for value 1 of CQL type varint, expecting class
>> java.math.BigInteger but class java.lang.String provided
>>
>> ..I am exploring more though..
>>
>> We're getting into details of the java driver at this point. For int,
>> what you can do is:
>>   boundStatement.setString("id", rowkey);
>>   boundStatement.setBytesUnsafe("columnname", ByteBuffer.wrap(new
>> byte[0]));
>>   boundStatement.setBytes("columnvalue", ByteBuffer.wrap(value));
>>
>> In other words, the shorthand BoundStatement.bind() won't let you insert
>> an empty value for types
>> that don't naturally have an empty value (like int; keep in mind that an
>> empty value is not the same
>> than null). But you can circumvent that using setBytesUnsafe if you
>> really want.
>>
>> Long story short, my advice would be to avoid using empty values for type
>> that don't naturally have
>> one (anything else than text and blob really). If you do, that's going to
>> be painful (but possible) to
>> work with, at least with the java driver (but for good reasons, java just
>> doesn't have a good to
>> represent an empty int value (again, you can have a null Integer but
>> that's different)).
>>
>> --
>> Sylvain
>>
>>
>> Thanks a ton,
>> Vikas Goyal
>>
>>
>> On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sylvain@datastax.com
>> <ma...@datastax.com>> wrote:
>>
>> However,we tried missing the value but it didn't work :(
>>
>> Right, because not providing a value is akin to having a null value (in
>> the CQL3 sense of the term, which is different from what Dean asked about)
>> and null values are not allowed for primary key columns.
>> You could however insert an *empty* value if you wanted, which in you
>> case is just inserting an empty string since colname is a string. Thrift
>> doesn't allow more or less in that case.
>>
>> --
>> Sylvain
>>
>>
>>
>> So our code is like below where we are using 3 values if colname is not
>> null..else 2 values..
>>
>>             if (key != null) {
>>                 PreparedStatement statement = session.prepare("INSERT
>> INTO keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>>                 BoundStatement boundStatement = new
>> BoundStatement(statement);
>>
>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>> rowKey), key, ByteBuffer.wrap(value)));
>>             } else {
>>                 PreparedStatement statement = session.prepare("INSERT
>> INTO " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>>                 BoundStatement boundStatement = new
>> BoundStatement(statement);
>>
>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>> rowKey), ByteBuffer.wrap(value)));
>>           }
>>
>> And, I did that and getting this exception:
>>
>> Exception:Missing PRIMARY KEY part colname since colvalue is set
>>
>> And just FYI. Our Column Family definition is below:
>>
>> CREATE TABLE keys.StringIndice (id text,
>> colname text,
>> colvalue blob,
>> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>>
>> Thanks again,
>> Vikas Goyal
>>
>>
>>
>> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sylvain@datastax.com
>> <ma...@datastax.com>> wrote:
>> Short answer: not, this is not correct.
>>
>> Longer answer: what you call "null" is actually an empty value (which is
>> *not* the same thing, unless you consider an empty string is the same thing
>> than a null string). As it happens, C* always an empty value as a valid
>> value for any type and that's true of both thrift and CQL3. What is true is
>> that CQL3 discourage the use of empty values for type for which it doesn't
>> particularly make sense (integers typically) by not having a particular
>> easy to use syntax to input them. But that's supported nonetheless. If you
>> use a prepared statement for instance (where you send values already
>> serialized), nothing will prevent you from sending an empty value. Even if
>> you don't want to use a prepared statement, CQL3 has conversion functions (
>> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do
>> it (for instance, "blobAsInt(0x)" will be an empty int value).
>>
>> --
>> Sylvain
>>
>>
>>
>> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <Dean.Hiller@nrel.gov
>> <ma...@nrel.gov>> wrote:
>> Many applications in thrift use the wide row with composite column name
>> and as an example, let's say golf score for instance and we end up with
>> golf score : pk like so
>>
>> null : pk56
>> null : pk45
>> 89 : pk90
>> 89: pk87
>> 90: pk101
>> 95: pk17
>>
>> Notice that there are some who do not have a golf score(zero would not
>> quite make sense and would be interpreted as a golf score).  I am hearing
>> from this post if they are correct that this is not portable to CQL3???  Is
>> this true?
>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>
>> (This sounds like a major deficit to me as the wide row now can only be
>> used where actual values exist?????).  Is it possible to port this pattern
>> to CQL3?
>>
>> Thanks,
>> Dean
>>
>>
>>
>>
>>
>>
>>
>>
>


-- 

:- a)


Alex Popescu
Sen. Product Manager @ DataStax
@al3xandru

Re: is this correct, thrift unportable to CQL3Š.

Posted by Sylvain Lebresne <sy...@datastax.com>.
On Tue, Sep 24, 2013 at 7:24 PM, Hiller, Dean <De...@nrel.gov> wrote:

> Java has Integer as opposed to int which is what I represent "golf scores"
> with so to speak in my example.  In this case, Integer can be null but of
> course maps to "empty" just fine.  What about querying for all golf scores
> that are "empty" then?
>

The DataStax java driver already "maps" a null Integer to a null CQL3
column, and so it *cannot* also map it to an empty value. And even though
you cannot have null CQL3 columns in the primary key, mapping a null
Integer to an empty value would be highly confusing/inconsistent (from the
point of view of the java driver) because:
1) having a null Integer map differently depending on whether the receiving
column is in the PK or not would be messy/surprising.
2) it's not really technically possible because internally the driver does
not always have the information of whether the receiving column is in the
PK or not
3) what about strings? Should we also map a null String to an empty value
when the column is in the PK? Because that would mean mapping a null java
String to an empty CQL3 string value and that just feel wrong. And if we
don't do it, then it means we treat Integer and String differently with
respect to null and that's too would be pretty confusing.

But anyway, all of that is pretty specific to the java driver, so maybe if
you guys want to debate that further we should move to the driver mailing
list:
https://groups.google.com/a/lists.datastax.com/forum/#!forum/java-driver-user

--
Sylvain


>
> Ie. This sounds like this solution would be perfect if we can get rid of
> the exception piece.
>
> Thanks much!!!
> Dean
>
> From: Sylvain Lebresne <sy...@datastax.com>>
> Reply-To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <
> user@cassandra.apache.org<ma...@cassandra.apache.org>>
> Date: Tuesday, September 24, 2013 10:58 AM
> To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <
> user@cassandra.apache.org<ma...@cassandra.apache.org>>
> Subject: Re: is this correct, thrift unportable to CQL3�.
>
> On Tue, Sep 24, 2013 at 6:17 PM, Vikas Goyal <vikas@easility.com<mailto:
> vikas@easility.com>> wrote:
> Ok. Great. It works for String and Decimal/Float but not for integer data
> type..
> i.e,, if I am passing "" to the composite key column which is either text
> or float, it works..
>
> session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));
>
> But not working with bigint, int or varint..and getting following
> exception;
>
> Exception:Invalid type for value 1 of CQL type varint, expecting class
> java.math.BigInteger but class java.lang.String provided
>
> ..I am exploring more though..
>
> We're getting into details of the java driver at this point. For int, what
> you can do is:
>   boundStatement.setString("id", rowkey);
>   boundStatement.setBytesUnsafe("columnname", ByteBuffer.wrap(new
> byte[0]));
>   boundStatement.setBytes("columnvalue", ByteBuffer.wrap(value));
>
> In other words, the shorthand BoundStatement.bind() won't let you insert
> an empty value for types
> that don't naturally have an empty value (like int; keep in mind that an
> empty value is not the same
> than null). But you can circumvent that using setBytesUnsafe if you really
> want.
>
> Long story short, my advice would be to avoid using empty values for type
> that don't naturally have
> one (anything else than text and blob really). If you do, that's going to
> be painful (but possible) to
> work with, at least with the java driver (but for good reasons, java just
> doesn't have a good to
> represent an empty int value (again, you can have a null Integer but
> that's different)).
>
> --
> Sylvain
>
>
> Thanks a ton,
> Vikas Goyal
>
>
> On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sylvain@datastax.com
> <ma...@datastax.com>> wrote:
>
> However,we tried missing the value but it didn't work :(
>
> Right, because not providing a value is akin to having a null value (in
> the CQL3 sense of the term, which is different from what Dean asked about)
> and null values are not allowed for primary key columns.
> You could however insert an *empty* value if you wanted, which in you case
> is just inserting an empty string since colname is a string. Thrift doesn't
> allow more or less in that case.
>
> --
> Sylvain
>
>
>
> So our code is like below where we are using 3 values if colname is not
> null..else 2 values..
>
>             if (key != null) {
>                 PreparedStatement statement = session.prepare("INSERT INTO
> keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>                 BoundStatement boundStatement = new
> BoundStatement(statement);
>
> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
> rowKey), key, ByteBuffer.wrap(value)));
>             } else {
>                 PreparedStatement statement = session.prepare("INSERT INTO
> " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>                 BoundStatement boundStatement = new
> BoundStatement(statement);
>
> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
> rowKey), ByteBuffer.wrap(value)));
>           }
>
> And, I did that and getting this exception:
>
> Exception:Missing PRIMARY KEY part colname since colvalue is set
>
> And just FYI. Our Column Family definition is below:
>
> CREATE TABLE keys.StringIndice (id text,
> colname text,
> colvalue blob,
> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>
> Thanks again,
> Vikas Goyal
>
>
>
> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sylvain@datastax.com
> <ma...@datastax.com>> wrote:
> Short answer: not, this is not correct.
>
> Longer answer: what you call "null" is actually an empty value (which is
> *not* the same thing, unless you consider an empty string is the same thing
> than a null string). As it happens, C* always an empty value as a valid
> value for any type and that's true of both thrift and CQL3. What is true is
> that CQL3 discourage the use of empty values for type for which it doesn't
> particularly make sense (integers typically) by not having a particular
> easy to use syntax to input them. But that's supported nonetheless. If you
> use a prepared statement for instance (where you send values already
> serialized), nothing will prevent you from sending an empty value. Even if
> you don't want to use a prepared statement, CQL3 has conversion functions (
> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do
> it (for instance, "blobAsInt(0x)" will be an empty int value).
>
> --
> Sylvain
>
>
>
> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <Dean.Hiller@nrel.gov
> <ma...@nrel.gov>> wrote:
> Many applications in thrift use the wide row with composite column name
> and as an example, let's say golf score for instance and we end up with
> golf score : pk like so
>
> null : pk56
> null : pk45
> 89 : pk90
> 89: pk87
> 90: pk101
> 95: pk17
>
> Notice that there are some who do not have a golf score(zero would not
> quite make sense and would be interpreted as a golf score).  I am hearing
> from this post if they are correct that this is not portable to CQL3???  Is
> this true?
> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>
> (This sounds like a major deficit to me as the wide row now can only be
> used where actual values exist?????).  Is it possible to port this pattern
> to CQL3?
>
> Thanks,
> Dean
>
>
>
>
>
>
>
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by "Hiller, Dean" <De...@nrel.gov>.
Java has Integer as opposed to int which is what I represent "golf scores" with so to speak in my example.  In this case, Integer can be null but of course maps to "empty" just fine.  What about querying for all golf scores that are "empty" then?

Ie. This sounds like this solution would be perfect if we can get rid of the exception piece.

Thanks much!!!
Dean

From: Sylvain Lebresne <sy...@datastax.com>>
Reply-To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <us...@cassandra.apache.org>>
Date: Tuesday, September 24, 2013 10:58 AM
To: "user@cassandra.apache.org<ma...@cassandra.apache.org>" <us...@cassandra.apache.org>>
Subject: Re: is this correct, thrift unportable to CQL3Š.

On Tue, Sep 24, 2013 at 6:17 PM, Vikas Goyal <vi...@easility.com>> wrote:
Ok. Great. It works for String and Decimal/Float but not for integer data type..
i.e,, if I am passing "" to the composite key column which is either text or float, it works..

session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));

But not working with bigint, int or varint..and getting following exception;

Exception:Invalid type for value 1 of CQL type varint, expecting class java.math.BigInteger but class java.lang.String provided

..I am exploring more though..

We're getting into details of the java driver at this point. For int, what you can do is:
  boundStatement.setString("id", rowkey);
  boundStatement.setBytesUnsafe("columnname", ByteBuffer.wrap(new byte[0]));
  boundStatement.setBytes("columnvalue", ByteBuffer.wrap(value));

In other words, the shorthand BoundStatement.bind() won't let you insert an empty value for types
that don't naturally have an empty value (like int; keep in mind that an empty value is not the same
than null). But you can circumvent that using setBytesUnsafe if you really want.

Long story short, my advice would be to avoid using empty values for type that don't naturally have
one (anything else than text and blob really). If you do, that's going to be painful (but possible) to
work with, at least with the java driver (but for good reasons, java just doesn't have a good to
represent an empty int value (again, you can have a null Integer but that's different)).

--
Sylvain


Thanks a ton,
Vikas Goyal


On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sy...@datastax.com>> wrote:

However,we tried missing the value but it didn't work :(

Right, because not providing a value is akin to having a null value (in the CQL3 sense of the term, which is different from what Dean asked about) and null values are not allowed for primary key columns.
You could however insert an *empty* value if you wanted, which in you case is just inserting an empty string since colname is a string. Thrift doesn't allow more or less in that case.

--
Sylvain



So our code is like below where we are using 3 values if colname is not null..else 2 values..

            if (key != null) {
                PreparedStatement statement = session.prepare("INSERT INTO keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
                BoundStatement boundStatement = new BoundStatement(statement);
                session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class, rowKey), key, ByteBuffer.wrap(value)));
            } else {
                PreparedStatement statement = session.prepare("INSERT INTO " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
                BoundStatement boundStatement = new BoundStatement(statement);
                session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class, rowKey), ByteBuffer.wrap(value)));
          }

And, I did that and getting this exception:

Exception:Missing PRIMARY KEY part colname since colvalue is set

And just FYI. Our Column Family definition is below:

CREATE TABLE keys.StringIndice (id text,
colname text,
colvalue blob,
PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)

Thanks again,
Vikas Goyal



On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sy...@datastax.com>> wrote:
Short answer: not, this is not correct.

Longer answer: what you call "null" is actually an empty value (which is *not* the same thing, unless you consider an empty string is the same thing than a null string). As it happens, C* always an empty value as a valid value for any type and that's true of both thrift and CQL3. What is true is that CQL3 discourage the use of empty values for type for which it doesn't particularly make sense (integers typically) by not having a particular easy to use syntax to input them. But that's supported nonetheless. If you use a prepared statement for instance (where you send values already serialized), nothing will prevent you from sending an empty value. Even if you don't want to use a prepared statement, CQL3 has conversion functions (http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do it (for instance, "blobAsInt(0x)" will be an empty int value).

--
Sylvain



On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov>> wrote:
Many applications in thrift use the wide row with composite column name and as an example, let's say golf score for instance and we end up with golf score : pk like so

null : pk56
null : pk45
89 : pk90
89: pk87
90: pk101
95: pk17

Notice that there are some who do not have a golf score(zero would not quite make sense and would be interpreted as a golf score).  I am hearing from this post if they are correct that this is not portable to CQL3???  Is this true?  http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3

(This sounds like a major deficit to me as the wide row now can only be used where actual values exist?????).  Is it possible to port this pattern to CQL3?

Thanks,
Dean








Re: is this correct, thrift unportable to CQL3Š.

Posted by Sylvain Lebresne <sy...@datastax.com>.
On Tue, Sep 24, 2013 at 6:17 PM, Vikas Goyal <vi...@easility.com> wrote:

> Ok. Great. It works for String and Decimal/Float but not for integer data
> type..
> i.e,, if I am passing "" to the composite key column which is either text
> or float, it works..
>
> session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));
>
> But not working with bigint, int or varint..and getting following
> exception;
>
> Exception:Invalid type for value 1 of CQL type varint, expecting class
> java.math.BigInteger but class java.lang.String provided
>
> ..I am exploring more though..
>

We're getting into details of the java driver at this point. For int, what
you can do is:
  boundStatement.setString("id", rowkey);
  boundStatement.setBytesUnsafe("columnname", ByteBuffer.wrap(new byte[0]));
  boundStatement.setBytes("columnvalue", ByteBuffer.wrap(value));

In other words, the shorthand BoundStatement.bind() won't let you insert an
empty value for types
that don't naturally have an empty value (like int; keep in mind that an
empty value is not the same
than null). But you can circumvent that using setBytesUnsafe if you really
want.

Long story short, my advice would be to avoid using empty values for type
that don't naturally have
one (anything else than text and blob really). If you do, that's going to
be painful (but possible) to
work with, at least with the java driver (but for good reasons, java just
doesn't have a good to
represent an empty int value (again, you can have a null Integer but that's
different)).

--
Sylvain


>
> Thanks a ton,
> Vikas Goyal
>
>
> On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sy...@datastax.com>wrote:
>
>>
>> However,we tried missing the value but it didn't work :(
>>>
>>
>> Right, because not providing a value is akin to having a null value (in
>> the CQL3 sense of the term, which is different from what Dean asked about)
>> and null values are not allowed for primary key columns.
>> You could however insert an *empty* value if you wanted, which in you
>> case is just inserting an empty string since colname is a string. Thrift
>> doesn't allow more or less in that case.
>>
>> --
>> Sylvain
>>
>>
>>
>>>
>>> So our code is like below where we are using 3 values if colname is not
>>> null..else 2 values..
>>>
>>>             if (key != null) {
>>>                 PreparedStatement statement = session.prepare("INSERT
>>> INTO keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>>>                 BoundStatement boundStatement = new
>>> BoundStatement(statement);
>>>
>>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>>> rowKey), key, ByteBuffer.wrap(value)));
>>>             } else {
>>>                 PreparedStatement statement = session.prepare("INSERT
>>> INTO " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>>>                 BoundStatement boundStatement = new
>>> BoundStatement(statement);
>>>
>>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>>> rowKey), ByteBuffer.wrap(value)));
>>>           }
>>>
>>> And, I did that and getting this exception:
>>>
>>> Exception:Missing PRIMARY KEY part colname since colvalue is set
>>>
>>> And just FYI. Our Column Family definition is below:
>>>
>>> CREATE TABLE keys.StringIndice (id text,
>>> colname text,
>>>  colvalue blob,
>>> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>>>
>>> Thanks again,
>>> Vikas Goyal
>>>
>>>
>>>
>>> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sy...@datastax.com>wrote:
>>>
>>>> Short answer: not, this is not correct.
>>>>
>>>> Longer answer: what you call "null" is actually an empty value (which
>>>> is *not* the same thing, unless you consider an empty string is the same
>>>> thing than a null string). As it happens, C* always an empty value as a
>>>> valid value for any type and that's true of both thrift and CQL3. What is
>>>> true is that CQL3 discourage the use of empty values for type for which it
>>>> doesn't particularly make sense (integers typically) by not having a
>>>> particular easy to use syntax to input them. But that's supported
>>>> nonetheless. If you use a prepared statement for instance (where you send
>>>> values already serialized), nothing will prevent you from sending an empty
>>>> value. Even if you don't want to use a prepared statement, CQL3 has
>>>> conversion functions (
>>>> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to
>>>> do it (for instance, "blobAsInt(0x)" will be an empty int value).
>>>>
>>>> --
>>>> Sylvain
>>>>
>>>>
>>>>
>>>> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov>wrote:
>>>>
>>>>> Many applications in thrift use the wide row with composite column
>>>>> name and as an example, let's say golf score for instance and we end up
>>>>> with golf score : pk like so
>>>>>
>>>>> null : pk56
>>>>> null : pk45
>>>>> 89 : pk90
>>>>> 89: pk87
>>>>> 90: pk101
>>>>> 95: pk17
>>>>>
>>>>> Notice that there are some who do not have a golf score(zero would not
>>>>> quite make sense and would be interpreted as a golf score).  I am hearing
>>>>> from this post if they are correct that this is not portable to CQL3???  Is
>>>>> this true?
>>>>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>>>>
>>>>> (This sounds like a major deficit to me as the wide row now can only
>>>>> be used where actual values exist?????).  Is it possible to port this
>>>>> pattern to CQL3?
>>>>>
>>>>> Thanks,
>>>>> Dean
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by Vikas Goyal <vi...@easility.com>.
Ok. Great. It works for String and Decimal/Float but not for integer data
type..
i.e,, if I am passing "" to the composite key column which is either text
or float, it works..

session.execute(boundStatement.bind(rowkey, "", ByteBuffer.wrap(value)));

But not working with bigint, int or varint..and getting following exception;

Exception:Invalid type for value 1 of CQL type varint, expecting class
java.math.BigInteger but class java.lang.String provided

..I am exploring more though..

Thanks a ton,
Vikas Goyal


On Tue, Sep 24, 2013 at 9:05 PM, Sylvain Lebresne <sy...@datastax.com>wrote:

>
> However,we tried missing the value but it didn't work :(
>>
>
> Right, because not providing a value is akin to having a null value (in
> the CQL3 sense of the term, which is different from what Dean asked about)
> and null values are not allowed for primary key columns.
> You could however insert an *empty* value if you wanted, which in you case
> is just inserting an empty string since colname is a string. Thrift doesn't
> allow more or less in that case.
>
> --
> Sylvain
>
>
>
>>
>> So our code is like below where we are using 3 values if colname is not
>> null..else 2 values..
>>
>>             if (key != null) {
>>                 PreparedStatement statement = session.prepare("INSERT
>> INTO keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>>                 BoundStatement boundStatement = new
>> BoundStatement(statement);
>>
>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>> rowKey), key, ByteBuffer.wrap(value)));
>>             } else {
>>                 PreparedStatement statement = session.prepare("INSERT
>> INTO " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>>                 BoundStatement boundStatement = new
>> BoundStatement(statement);
>>
>> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
>> rowKey), ByteBuffer.wrap(value)));
>>           }
>>
>> And, I did that and getting this exception:
>>
>> Exception:Missing PRIMARY KEY part colname since colvalue is set
>>
>> And just FYI. Our Column Family definition is below:
>>
>> CREATE TABLE keys.StringIndice (id text,
>> colname text,
>>  colvalue blob,
>> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>>
>> Thanks again,
>> Vikas Goyal
>>
>>
>>
>> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sy...@datastax.com>wrote:
>>
>>> Short answer: not, this is not correct.
>>>
>>> Longer answer: what you call "null" is actually an empty value (which is
>>> *not* the same thing, unless you consider an empty string is the same thing
>>> than a null string). As it happens, C* always an empty value as a valid
>>> value for any type and that's true of both thrift and CQL3. What is true is
>>> that CQL3 discourage the use of empty values for type for which it doesn't
>>> particularly make sense (integers typically) by not having a particular
>>> easy to use syntax to input them. But that's supported nonetheless. If you
>>> use a prepared statement for instance (where you send values already
>>> serialized), nothing will prevent you from sending an empty value. Even if
>>> you don't want to use a prepared statement, CQL3 has conversion functions (
>>> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to
>>> do it (for instance, "blobAsInt(0x)" will be an empty int value).
>>>
>>> --
>>> Sylvain
>>>
>>>
>>>
>>> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov>wrote:
>>>
>>>> Many applications in thrift use the wide row with composite column name
>>>> and as an example, let's say golf score for instance and we end up with
>>>> golf score : pk like so
>>>>
>>>> null : pk56
>>>> null : pk45
>>>> 89 : pk90
>>>> 89: pk87
>>>> 90: pk101
>>>> 95: pk17
>>>>
>>>> Notice that there are some who do not have a golf score(zero would not
>>>> quite make sense and would be interpreted as a golf score).  I am hearing
>>>> from this post if they are correct that this is not portable to CQL3???  Is
>>>> this true?
>>>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>>>
>>>> (This sounds like a major deficit to me as the wide row now can only be
>>>> used where actual values exist?????).  Is it possible to port this pattern
>>>> to CQL3?
>>>>
>>>> Thanks,
>>>> Dean
>>>>
>>>>
>>>>
>>>
>>
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by Sylvain Lebresne <sy...@datastax.com>.
> However,we tried missing the value but it didn't work :(
>

Right, because not providing a value is akin to having a null value (in the
CQL3 sense of the term, which is different from what Dean asked about) and
null values are not allowed for primary key columns.
You could however insert an *empty* value if you wanted, which in you case
is just inserting an empty string since colname is a string. Thrift doesn't
allow more or less in that case.

--
Sylvain



>
> So our code is like below where we are using 3 values if colname is not
> null..else 2 values..
>
>             if (key != null) {
>                 PreparedStatement statement = session.prepare("INSERT INTO
> keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
>                 BoundStatement boundStatement = new
> BoundStatement(statement);
>
> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
> rowKey), key, ByteBuffer.wrap(value)));
>             } else {
>                 PreparedStatement statement = session.prepare("INSERT INTO
> " + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
>                 BoundStatement boundStatement = new
> BoundStatement(statement);
>
> session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
> rowKey), ByteBuffer.wrap(value)));
>           }
>
> And, I did that and getting this exception:
>
> Exception:Missing PRIMARY KEY part colname since colvalue is set
>
> And just FYI. Our Column Family definition is below:
>
> CREATE TABLE keys.StringIndice (id text,
> colname text,
>  colvalue blob,
> PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)
>
> Thanks again,
> Vikas Goyal
>
>
>
> On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sy...@datastax.com>wrote:
>
>> Short answer: not, this is not correct.
>>
>> Longer answer: what you call "null" is actually an empty value (which is
>> *not* the same thing, unless you consider an empty string is the same thing
>> than a null string). As it happens, C* always an empty value as a valid
>> value for any type and that's true of both thrift and CQL3. What is true is
>> that CQL3 discourage the use of empty values for type for which it doesn't
>> particularly make sense (integers typically) by not having a particular
>> easy to use syntax to input them. But that's supported nonetheless. If you
>> use a prepared statement for instance (where you send values already
>> serialized), nothing will prevent you from sending an empty value. Even if
>> you don't want to use a prepared statement, CQL3 has conversion functions (
>> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do
>> it (for instance, "blobAsInt(0x)" will be an empty int value).
>>
>> --
>> Sylvain
>>
>>
>>
>> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov>wrote:
>>
>>> Many applications in thrift use the wide row with composite column name
>>> and as an example, let's say golf score for instance and we end up with
>>> golf score : pk like so
>>>
>>> null : pk56
>>> null : pk45
>>> 89 : pk90
>>> 89: pk87
>>> 90: pk101
>>> 95: pk17
>>>
>>> Notice that there are some who do not have a golf score(zero would not
>>> quite make sense and would be interpreted as a golf score).  I am hearing
>>> from this post if they are correct that this is not portable to CQL3???  Is
>>> this true?
>>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>>
>>> (This sounds like a major deficit to me as the wide row now can only be
>>> used where actual values exist?????).  Is it possible to port this pattern
>>> to CQL3?
>>>
>>> Thanks,
>>> Dean
>>>
>>>
>>>
>>
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by Vikas Goyal <vi...@easility.com>.
Thanks Sylvain,

However,we tried missing the value but it didn't work :(

So our code is like below where we are using 3 values if colname is not
null..else 2 values..

            if (key != null) {
                PreparedStatement statement = session.prepare("INSERT INTO
keys.StringIndice (id, colname, colvalue) VALUES (?, ?, ?)");
                BoundStatement boundStatement = new
BoundStatement(statement);

session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
rowKey), key, ByteBuffer.wrap(value)));
            } else {
                PreparedStatement statement = session.prepare("INSERT INTO
" + keys + "." + table + "(id, colvalue) VALUES (?, ?)");
                BoundStatement boundStatement = new
BoundStatement(statement);

session.execute(boundStatement.bind(StandardConverters.convertFromBytes(String.class,
rowKey), ByteBuffer.wrap(value)));
          }

And, I did that and getting this exception:

Exception:Missing PRIMARY KEY part colname since colvalue is set

And just FYI. Our Column Family definition is below:

CREATE TABLE keys.StringIndice (id text,
colname text,
colvalue blob,
PRIMARY KEY (id,colname, colvalue)) WITH COMPACT STORAGE)

Thanks again,
Vikas Goyal



On Tue, Sep 24, 2013 at 7:02 PM, Sylvain Lebresne <sy...@datastax.com>wrote:

> Short answer: not, this is not correct.
>
> Longer answer: what you call "null" is actually an empty value (which is
> *not* the same thing, unless you consider an empty string is the same thing
> than a null string). As it happens, C* always an empty value as a valid
> value for any type and that's true of both thrift and CQL3. What is true is
> that CQL3 discourage the use of empty values for type for which it doesn't
> particularly make sense (integers typically) by not having a particular
> easy to use syntax to input them. But that's supported nonetheless. If you
> use a prepared statement for instance (where you send values already
> serialized), nothing will prevent you from sending an empty value. Even if
> you don't want to use a prepared statement, CQL3 has conversion functions (
> http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do
> it (for instance, "blobAsInt(0x)" will be an empty int value).
>
> --
> Sylvain
>
>
>
> On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov>wrote:
>
>> Many applications in thrift use the wide row with composite column name
>> and as an example, let's say golf score for instance and we end up with
>> golf score : pk like so
>>
>> null : pk56
>> null : pk45
>> 89 : pk90
>> 89: pk87
>> 90: pk101
>> 95: pk17
>>
>> Notice that there are some who do not have a golf score(zero would not
>> quite make sense and would be interpreted as a golf score).  I am hearing
>> from this post if they are correct that this is not portable to CQL3???  Is
>> this true?
>> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>>
>> (This sounds like a major deficit to me as the wide row now can only be
>> used where actual values exist?????).  Is it possible to port this pattern
>> to CQL3?
>>
>> Thanks,
>> Dean
>>
>>
>>
>

Re: is this correct, thrift unportable to CQL3Š.

Posted by Sylvain Lebresne <sy...@datastax.com>.
Short answer: not, this is not correct.

Longer answer: what you call "null" is actually an empty value (which is
*not* the same thing, unless you consider an empty string is the same thing
than a null string). As it happens, C* always an empty value as a valid
value for any type and that's true of both thrift and CQL3. What is true is
that CQL3 discourage the use of empty values for type for which it doesn't
particularly make sense (integers typically) by not having a particular
easy to use syntax to input them. But that's supported nonetheless. If you
use a prepared statement for instance (where you send values already
serialized), nothing will prevent you from sending an empty value. Even if
you don't want to use a prepared statement, CQL3 has conversion functions (
http://cassandra.apache.org/doc/cql3/CQL.html#blobFun) that allows to do it
(for instance, "blobAsInt(0x)" will be an empty int value).

--
Sylvain



On Tue, Sep 24, 2013 at 2:36 PM, Hiller, Dean <De...@nrel.gov> wrote:

> Many applications in thrift use the wide row with composite column name
> and as an example, let's say golf score for instance and we end up with
> golf score : pk like so
>
> null : pk56
> null : pk45
> 89 : pk90
> 89: pk87
> 90: pk101
> 95: pk17
>
> Notice that there are some who do not have a golf score(zero would not
> quite make sense and would be interpreted as a golf score).  I am hearing
> from this post if they are correct that this is not portable to CQL3???  Is
> this true?
> http://stackoverflow.com/questions/18963248/how-can-i-have-null-column-value-for-a-composite-key-column-in-cql3
>
> (This sounds like a major deficit to me as the wide row now can only be
> used where actual values exist?????).  Is it possible to port this pattern
> to CQL3?
>
> Thanks,
> Dean
>
>
>