6

I have an old column family which has a column named "value" which was defined as a blob data type. This column usually holds two numbers separated with an underscore, like "421_2".

When im using the python datastax driver and execute the query, the results return with that field parsed as a string:

In [21]: session.execute(q)
Out[21]: 
[Row(column1=4776015, value='145_0'),
 Row(column1=4891778, value='114_0'),
 Row(column1=4891780, value='195_0'),
 Row(column1=4893662, value='105_0'),
 Row(column1=4893664, value='115_0'),
 Row(column1=4898493, value='168_0'),
 Row(column1=4945162, value='148_0'),
 Row(column1=4945163, value='131_0'),
 Row(column1=4945168, value='125_0'),
 Row(column1=4945169, value='211_0'),
 Row(column1=4998426, value='463_0')]

When I use the java driver I get a com.datastax.driver.core.Row object back. When I try to read the value field by, for example, row.getString("value") I get the expected InvalidTypeException: Column value is of type blob. Seems like the only way to read the field is via row.getBytes("value") and then I get back an java.nio.HeapByteBuffer object.

Problem is, I cant seem to convert this object to string in an easy fashion. Googling yielded two answers from 2012 that suggest the following:

String string_value = new String(result.getBytes("value"), "UTF-8");

But such a String constructor doesn't seems to exist anymore. So, my questions are:

  1. How do I convert HeapByteBuffer into string?
  2. How come the python driver converted the blob easily and the java one did not?

Side Note: I could debug the python driver, but currently that seems too much work for something that should be trivial. (and the fact that no one asked about it suggests Im missing something simple here..)

idoda
  • 6,248
  • 10
  • 39
  • 52

4 Answers4

13

Another easier way is to change the CQL statement.

select column1, blobastext(value) from YourTable where key = xxx

The second column would be type of String.

popcorny
  • 1,710
  • 16
  • 16
  • I like this one, but Im not sure how easy it is to incorporate it in the Java driver.. going to check. – idoda Aug 05 '15 at 08:33
  • I didnt find a way to apply a function to a selected column in the Java QueryBuilder object supplied by Datastax. Otherwise that would have been a very elegant solution. – idoda Aug 05 '15 at 12:45
  • Why don't you use `session.execute("select column, ....")` directly? If you need to use QueryBuilder, try [Selection.Selection::fcall](http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/querybuilder/Select.Selection.html#fcall(java.lang.String,%20java.lang.Object...)). I am very sure that blobastext works in java driver, because i used it in my production project. – popcorny Aug 05 '15 at 14:20
  • Do you know how to programatically create a blob from string? the fcall is only available in selection for some reason. What If I need now to update, for example, a blob column? – idoda Aug 10 '15 at 12:25
  • @idoda it should be textAsBlob(?) – Andrew James Ramirez Jun 16 '16 at 08:24
  • @jgmjgm , did you found any way to do it for binary characters ? – monk May 29 '19 at 22:53
  • I found that strangely some python/client versions show it and some don't, though I can't remember which as at this point I've reversed engineered the binary format that was being used for my use case and made a custom client / cli faculty around that. – jgmjgm Jun 03 '19 at 11:01
8

You can also get direct access to the Java driver's serializers. This way you don't have to deal with low-level details, and it also works for other types.

Driver 2.0.x:

String s = (String)DataType.text().deserialize(byteBuffer);

Driver 2.1.x:

ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
String s = (String)DataType.text().deserialize(byteBuffer, protocolVersion);

Driver 2.2.x:

ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
String s = TypeCodec.VarcharCodec.instance.deserialize(byteBuffer, protocolVersion);
Olivier Michallat
  • 2,302
  • 11
  • 13
1

For version 3.1.4 of the datastax java driver the following will convert a blob to a string:

ProtocolVersion proto = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();

String deserialize = TypeCodec.varchar().deserialize(row.getBytes(i), proto);
Jenna
  • 11
  • 1
0

1.) Converting from byte buffer in Java is discussed in this answer.

2.) Assuming you're using Python 2, it's coming back as a string in Python because str is the binary type.

Community
  • 1
  • 1
Adam Holmberg
  • 7,245
  • 3
  • 30
  • 53