Converting cassandra blob type to string - java

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:
How do I convert HeapByteBuffer into string?
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..)

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.

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);

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);

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.

Related

convert byte array to java.sql.Clob

Is there any way to convert a byte array into java.sql.Clob ?
I am having this type of issue...
getHibernateTemplate().save(object)
Where object is having a field private Clob docData; and the similar is mapped into oracle table as CLOB
This docData clob is getting formed from somewhere in my java code like Hibernate.createClob(someString)
I tried to save it with type="clob" but getting cann't cast com.sun.proxy$Proxy124 to oracle.sql.CLOB. I have tried many ways to remove this Proxy but finally failed.
So I have decided to go like byte[] data = IOUtils.toByteArray(docData.getCharacterStream()); / byte[] data = IOUtils.toByteArray(docData.getAsciiStream()) and saving it as type="binary" but I am getting Caused by: java.sql.BatchUpdateException: ORA-01461: can bind a LONG value only for insert into a LONG column.
So now I want to create as a Clob from byte[].
Any help welcome.
Note earlier I was using Hibernate 3.3 and it was working fine without any such byte array conversion and etc...now I have upgraded to Hibernate 3.6.10 and getting this issue.
I'm using this method to create Blobs:
org.hibernate.engine.jdbc.NonContextualLobCreator.NonContextualLobCreator.INSTANCE.createBlob( buffer )
where buffer is an array of bytes.
There are 2 similar methods for creating CLOBs:
NonContextualLobCreator.INSTANCE.createClob( reader, length )
NonContextualLobCreator.INSTANCE.createClob( string )
Pick the one that fits better with your data.
Your error message says
cann't cast com.sun.proxy$Proxy124 to oracle.sql.CLOB
In the rest of your text you are referring to java.sql.Clob Check your imports, you might be using the clob from the oracle.sql package instead of the java.sql package somewhere.
Well, issue is resolved. I kept the java data type as 'Clob' only and made the hibernate mapping like type="string". Issue got resolved since my digital sign data does not contain more than 2 MB (that java string max supports).

Error passing java byte array as ColdFusion query parameter: mismatched input 'struct' expecting RIGHTPAREN

I am trying to convert some CF (version 10) code that was embedded inside a .cfm file into a function of a component as part of a Framework 1 application. The component is in script syntax, and the original code is in tag syntax. I didn't write the original code, and since I am still learning ColdFusion I am only trying to replicate the original code rather than re-write it.
The function reads in a file from the client and chops it up into pieces and stores the pieces in Java ByteArrays. It then makes as many queries as needed to store the byte arrays in a database. I have successfully converted everything up until the actual insertion query.
The problem I'm having is converting this portion of code, mainly the line with #objBuffer.Array()#:
<cfquery name="insertFile" datasource="#Datasource#">
INSERT INTO wt_file (file_data,file_name,file_type,file_part,rec_id)
VALUES (
<cfqueryparam value="#objBuffer.Array()#" cfsqltype="CF_SQL_blob">,
<cfqueryparam value="#rc.fileName#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#rc.fileType#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#i#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#rc.rec_id#" cfsqltype="cf_sql_varchar">)
</cfquery>
objBuffer.Array() is calling the Java method Array() on a java ByteBuffer object. When i try to do the same in script syntax like this:
fileQuery = new Query(
name="insertFile",
datasource = Datasource,
sql = "INSERT INTO wt_file
(file_data, file_name, file_type, file_part, rec_id)
VALUES (:data, :name, :type, :part, :recid)");
fileQuery.addParam(name="data", value = objBuffer.Array(), cfsqltype="CF_SQL_blob");
fileQuery.addParam(name="name", value = rc.fileName, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="type", value=rc.fileType, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="part", value=i, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="recid", value=rc.rec_id, cfsqltype="cf_sql_varchar");
/*execute query*/
fileQuery.execute();
In this syntax, the objBuffer.Array() call breaks the entire function. I have tried calling it before the parameter and passing it via a variable, but it doesn't matter where I call it. I get the same results.
The error message eclipse is giving me is not very helpful, but I'll post it anyway:
mismatched input 'struct' expecting RIGHTPAREN
0cfml.parsing.cfscript.CFParseException
null struct 137org.antlr.runtime.NoViableAltException
null function 52org.antlr.runtime.NoViableAltException
missing SEMICOLON at '(' 0cfml.parsing.cfscript.CFParseException
null function 52org.antlr.runtime.NoViableAltException
Because I am merely converting code, I am sure the is a better way to do this. I am sure there is a way to do this without using java classes but if there is a way to make this work too it would be great. Any help would be appreciated.
Thanks.

Unable to retrive Projection/Multi- Relantion field Requests.Custom_SFDCChangeReqID2 using versionone java sdk

I have been trying to retrieve information from querying a specific Asset(Story/Defect) on V1 using the VersionOne.SDK.Java.APIClient. I have been able to retrieve information like ID.Number, Status.Name but not Requests.Custom_SFDCChangeReqID2 under a Story or a Defect.
I check the metadata for:
https://.../Story?xsl=api.xsl
https://.../meta.V1/Defect?xsl=api.xsl
https://.../meta.V1/Request?xsl=api.xsl
And the naming and information looks right.
Here is my code:
IAssetType type = metaModel.getAssetType("Story");
IAttributeDefinition requestCRIDAttribute = type.getAttributeDefinition("Requests.Custom_SFDCChangeReqID2");
IAttributeDefinition idNumberAttribute = type.getAttributeDefinition("ID.Number")
Query query = new Query(type);
query.getSelection().add(requestCRIDAttribute);
query.getSelection().add(idNumberAttribute);
Asset[] results = v1Api.retrieve(query).getAssets();
String RequestCRID= result.getAttribute(requestCRIDAttribute).getValue().toString();
String IdNumber= result.getAttribute(idNumberAttribute).getValue().toString();
At this point, I can get some values for ID.Number but I am not able to retrieving any information for the value Custom_SFDCChangeReqID2.
When I run the restful query to retrieve information using a browser from a server standpoint it works and it does retrieve the information I am looking for. I used this syntax:
https://.../rest-1.v1/Data/Story?sel=Number,ID,Story.Requests.Custom_SFDCChangeReqID2,Story.
Alex: Remember that Results is an array of Asset´s, so I guess you should be accessing the information using something like
String RequestCRID= results[0].getAttribute(requestCRIDAttribute).getValue().toString();
String IdNumber= results[0].getAttribute(idNumberAttribute).getValue().toString();
or Iterate through the array.
Also notice that you have defined:
Asset[] results and not result
Hi thanks for your answer! I completely forgot about representing the loop, I was too focus on the retriving information part, yes I was actually using a loop and yes I created a temporary variable to check what I was getting from the query in the form
Because I was getting the variables one by one so I was only using the first record. My code works after all. It was just that What I was querying didn't contain any information of my use, that's why I was not finding any. Anyway thanks for your comment and observations

DB2 sql error code -245 for a date

I am reading several sql queries from database inside a loop as below:
{ // start of loop
Map<String, Object> queryRS = this.jdbcTemplate.queryForMap(this.querySql,queryParam);
String query = (String) queryRS.get("QUERY");
// code here as explained below
} // end of loop
The query returned could have any number of parameters. However, in all of them I have to set same date as the parameter.
For this I am counting the number of occurrence of character ? in the query and creating an Object array with same date repeated as below.
String date = '2010-12-31';
int numArgs = StringUtils.countMatches(query, "?");
String[] paramArgs = new String[numArgs];
for (int i = 0; i < numArgs; i++) {
paramArgs[i] = date;
}
After which I am executing the query as below:
SqlRowSet myRowSet = this.jdbcTemplate.queryForRowSet(query,(Object[]) paramArgs);
However, this is giving error when the query has a Date(?) function.
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-245, SQLSTATE=428F5, SQLERRMC=DATE;1, DRIVER=3.64.96
The description of above error is:
An untyped parameter marker is passed to a function and there are two or more possible candidate functions to resolve to during function resolution.
What is the solution to this?
Thanks for reading!
I suppose you are using String jdbcTemplate.
I had not the same but a similar problem: the function was char(?) and I was
passing an integer argument to it.
I was using a Old framework Ibatis 2.x (now I use MyBatis 3.x).
The framework was not the error cause.
On Ibatis I pass the argument so: char(#value:INTEGER#)
On my develop server all was work well but on remote production server I get your same error.
The problem was caused by the JDBC driver version 4.x on develop end 1.x on production.
To solve my problem I have two ways:
change the production driver (but I cannot)
use a different call: char('$value:INTEGER$') (I do this)
In IBATIS/MYBATIS framework, if value is 123, char('$value:INTEGER$') is translate to sql char('123') so solve my problem and when production change driver I can put back to char(#value:INTEGER#).
You have a similar problem. Try to:
look at the driver version
use type like in spring reference, sql type, spring manual
I do not use direct access to jdbcTemplate but I think that you have not to put args in string, you have to create a Date variable end put it in an Object array.
I hope that this can help you.

How to Insert in Oracle using java

I am having CLOB column in Oracle Data Base , I want to insert String .
It works if I use setCharacterStream, but how to insert String by setBytes am getting exception.
Please help me.
String s = "Hello How are you Data for CLOB column";
ps.setCharacterStream(1, new StringReader(s), s.length());
ps.setByte(1,Byte.parseByte(s));
Exception Trace :
java.lang.NumberFormatException: For input string: "Hello How are you Data for CLOB column"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:447)
at java.lang.Byte.parseByte(Byte.java:151)
at java.lang.Byte.parseByte(Byte.java:108)
at colb.test.InertClob.main(InertClob.java:24)
Here are two good examples (with sample code, for select and insert):
Handling CLOBS made easy:
http://rocksolutions.wordpress.com/2010/06/07/handling-clobs-made-easy-with-oracle-jdbc-10g/
Adding large object type to databaase
http://docs.oracle.com/javase/tutorial/jdbc/basics/blob.html
please refer to the Java API DOC
Parses the string argument as a signed decimal byte. The characters in the string must all be decimal digits,
You should:
Turn the String to a byte array by calling s.getBytes() for example or any other.
Call setBytes method, not setByte
When retrieving from the database, don't forget how you got the bytes, in order to restore the String properly.

Categories

Resources