Condition on a map key in update using datastax cassandra driver - java

I want to create a query like
UPDATE foo set map_clm['bar'] = 'biz' where id = 7 if map_clm['boo'] = 'bang';
using QueryBuilder of Datastax's java driver for cassandra. I can create Assignment using something like QueryBuilder.put("map_clm", "bar", "biz"), but I am stuck in creating a clause for IF Condition map_clm['boo'] = 'bang'. Is there anyway to do that ?

IMHO, most straightforward way will be to use raw function and put your if condition into it. But you need to be careful with escaping of arguments if you aren't using bindings.

Related

How do I bind a value for a CQL timestamp column using the Cassandra Java driver?

I am unable to bind the Timestamp value in java. I tried typecasting the and use the bind().set(index, new Timestamp(value), Timestamp.class) but it didn't work. Any other way to achieve this ?
Note: I am using datastax library for prepared statements.
In the Java driver docs for Prepared statements, there is an example for specifying the timestamp in a BoundStatement using the setQueryTimestamp() method:
BoundStatement bound =
ps1
.boundStatementBuilder()
.setString(0, "324378")
.setString(1, "LCD screen")
.setExecutionProfileName("oltp")
.setQueryTimestamp(123456789L)
.build();
If you update your original question and provide an extract of your code with an example of your query and errors you're getting, I'd be happy to look at it. Cheers!

How to store the timestamp in the server side for Cassandra?

I've tried using the code below:
final Session session = connection.getSession();
final String keyspaceName = session.getLoggedKeyspace();
psInsert = session.prepare(QueryBuilder
.insertInto(keyspaceName, CampaignConstants.TABLE_NAME_SAMPLE)
.value("ID", QueryBuilder.bindMarker())
.value("NAME", QueryBuilder.bindMarker())
.value("UPDATE_TIME", QueryBuilder.now()));
The column "UPDATE_TIME" is of type "timestamp". I can't modify it to "TimeUUID" type.
I'm getting this error:
com.datastax.driver.core.exceptions.InvalidQueryException: Type error:
cannot assign result of function system.now (type timeuuid) to
update_time (type timestamp)
The function call QueryBuilder.now() returns a Java instance of class: com.datastax.driver.core.querybuilder.Utils$FCall.
I've searched around, but the documentation doesn't specify how to use this now() function using the driver.
in CQL you need to use following expression: toTimestamp(now()).
For Java driver 4.x it's translated into the following: instead of QueryBuilder.now(), you need to use QueryBuilder.toTimestamp(QueryBuilder.now().
For Java driver 3.x, you need to wrap QueryBuilder.now() into the QueryBuilder.fcall, something like this: QueryBuilder.fcall("toTimestamp", QueryBuilder.now())

Datastore query with IN operator

The new flexible environment datastore interface does not seem to support IN operation when running a query. I hope that I'm wrong, and if so, how can one use an IN operator in the new Java interface of Datastore?
A query like - WHERE color IN('RED', 'BLACK'), it is not supported by the Datastore (server side). Same is the case with OR operator (e.g. WHERE color='RED' OR color='BLACK'). Some client APIs have added this functionality by splitting the query into multiple and then merging the results from each query. The new google-cloud-java API does not support this yet. For now, you would have to run multiple queries for each value in the IN clause and merge the results.
Here’s an example from the documentation:
If you want to set more than one filter on a query, you must use CompositeFilter, which requires at least two filters.
Filter tooShortFilter = new FilterPredicate("height", FilterOperator.LESS_THAN, minHeight);
Filter tooTallFilter = new FilterPredicate("height", FilterOperator.GREATER_THAN, maxHeight);
Filter heightOutOfRangeFilter = CompositeFilterOperator.or(tooShortFilter, tooTallFilter);
Query q = new Query("Person").setFilter(heightOutOfRangeFilter);
You can also use .and(). The code here is for Java 7. For Java 8 you can find a corresponding code in the documentation referenced above. I hope that helps.
Now to IN. While I have not tried it myself recently, the current documentation states that it can still be used as an operator. According to it, something like the code below should work:
Filter propertyFilter = new FilterPredicate("height", FilterOperator.IN, minHeights);
Query q = new Query("Person").setFilter(propertyFilter);
Alternatively, you could use Google GQL. It will allow you to write SQL-like syntax, in which you can use in(...).
I tried using the repository query methods, but I got an error informing that it is not supported.
Only solved for me using the #Query annotation;
Example:
#Query("select * from UserGroup where name IN #names")
List<Company> findAllByName(List<String> names);

Can I get the string from preparedStatem.setString()?

I have a problem - I create my SQL queries dynamically and basing on user input options. So the user has 5 parameters (actually it's more) and he can choose to use some of them (all if he wants) or none and specify their value in the query. So I construct my query String (basic the WHERE conditions) by checking if a parameter was selected and if a value was provided. However now there is the problem of special characters like '. I could try to use replaceAll("'", "\\") but this is quite dull and I know that preparedStatement.setString() does the job better. However for me I would need than to check again if the parameter was provided and if the previous one were also (to specify the poison of ? and connect it to the right parameter). This causes a lot of combinations and does not look elegant.
So my question is - can I somehow receive the string preparedStatement.setString() produces? Or is there a similar function that would do the same job and give me the String so I can put it in the query manually.
Maybe the intro was too long but someone might have a better idea and I wanted to explain why I need it.
What you can do is construct the basic, unparameterized SQL query based on whether the parameters were specified, and then use the prepared statement to fill in the parameters.
It could look something like this (rough sketch):
Map<String, Object> parameterValues = /*from user*/;
List<String> parameterNames = Arrays.asList("field1", "field2", "field3");
List<Object> valueList = new ArrayList<Object>();
StringBuilder statementBuilder = new StringBuilder("select * from table where ");
for ( String parameterName : parameterNames ) {
if ( parameterValues.containsKey(parameterName) ) {
statementBuilder.append(parameterName + " = ? AND");
valueList.add(parameterValues.get(parameterName));
}
}
PreparedStatement st = conn.prepareStatement(statementBuilder.toString(),
valueList);
//set each parameter here.
It's only hard the first time; then you can make it generic. That said there are probably query builders that abstract all of this away for you. I use QueryDSL but that does not have bindings for pure JDBC but rather JPA and JDO, etc.
On another forum I was given a different, simpler and cleaner approach that work perfectly.
Here are some links for others with the same problem:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1669972300346534908
http://www.akadia.com/services/dyn_modify_where_clause.html

using squiggle-sql to build dynamic sql with OR clause

I want to build Select fields and Where clause dynamically with OR condition using squiggle-sql api.
Please take more than two fields as an example.
Select field1,filed2,filed3,field4,.....
from t1,t2,t3
where t1.field1 = t2.field1 and t1.field1 = t3.field1
where t1.field=? OR t2.field3=? OR t3.field2=?
Please suggest.
I have just discovered Squiggle recently. It seems to be very similar to jOOQ (of which I am the developer). In jOOQ, you could write (I'm sure Squiggle offers similar functionality)
List<Field<?>> fields = new ArrayList<Field<?>>();
fields.add(field1);
fields.add(field2);
// ... add more fields here
Condition condition = T1.field.equal(...);
condition = condition.or(T2.field3.equal(...));
condition = condition.or(T3.field2.equal(...));
// ... connect more conditions here
DSL.using(configuration)
.select(fields)
.from(t1, t2, t3)
.where(t1.field1.equal(t2.field1))
.and(t2.field1.equal(t3.field1))
.and(condition);
For more information, see http://www.jooq.org
Two WHERE at the same SELECT will produce an error. Do you mean this?
Select field1,filed2,filed3,field4,.....
from t1,t2,t3
where t1.field1 = t2.field1 and t1.field1 = t3.field1
AND (t1.field=? OR t2.field3=? OR t3.field2=?)

Categories