Cassandra Datastax driver not giving error when update fails - cassandra

I have the following table.
CREATE TABLE codingjedi.users (
bucket int,
email text,
authprovider text,
firstname text,
lastname text,
confirmed boolean,
hasher text,
id uuid,
password text,
salt text,
PRIMARY KEY ((bucket, email), authprovider, firstname, lastname)
) WITH CLUSTERING ORDER BY (authprovider ASC, firstname ASC, lastname ASC)
I tried to update a row of the table but I didn't fully qualify the row. I specified only partition key and partially specified the clustering columns
def updateValues(tableName:String, model:User, id:UserKeys):Update.Where = {
QueryBuilder.update(tableName).`with`(QueryBuilder.set("confirmed",model.profile.internalProfileDetails.get.confirmed))/*(QueryBuilder.set("authprovider",model.profile.internalProfileDetails.get.loginInfo.providerID)) //TODOM - remove hardcoding for bucket and also add bucket in User model*/
.and(QueryBuilder.set("id",model.id))
.and(QueryBuilder.set("password",model.profile.internalProfileDetails.get.passwordInfo.get.password))
.and(QueryBuilder.set("hasher",model.profile.internalProfileDetails.get.passwordInfo.get.hasher))
.and(QueryBuilder.set("salt",""/*model.profile.internalProfileDetails.get.passwordInfo.get.salt.get*/)) //salt is empty for BCryptSha256PasswordHasher. The 'hash' method of BCryptSha256PasswordHasher does not return the salt separately because it is embedded in the hashed password.
.where(QueryBuilder.eq("bucket", id.bucket)) //TODOM - pick column names from config/env file
.and(QueryBuilder.eq("email", id.email))
.and(QueryBuilder.eq("authprovider", model.profile.internalProfileDetails.get.loginInfo.providerID))//TODOM - this should come from id
.and(QueryBuilder.eq("firstname",model.profile.externalProfileDetails.firstName))
/*.and(QueryBuilder.eq("lastname",model.profile.externalProfileDetails.lastName))*//*REMOVED a clustering column value*/
}
The above query fails and the row isn't updated but I also don't see any error messages in the console.
But if I try the same in cqlsh, I see error InvalidRequest: Error from server: code=2200 [Invalid query] message="Some clustering keys are missing: lastname".
Why Datastax isn't reporting error and how could I make it show errors?

Related

SyntaxException: line 2:10 no viable alternative at input 'UNIQUE' > (...NOT EXISTS books ( id [UUID] UNIQUE...)

I am trying the following codes to create a keyspace and a table inside of it:
CREATE KEYSPACE IF NOT EXISTS books WITH REPLICATION = { 'class': 'SimpleStrategy',
'replication_factor': 3 };
CREATE TABLE IF NOT EXISTS books (
id UUID PRIMARY KEY,
user_id TEXT UNIQUE NOT NULL,
scale TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT NOT NULL,
reward map<INT,TEXT> NOT NULL,
image_url TEXT NOT NULL,
video_url TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
But I do get:
SyntaxException: line 2:10 no viable alternative at input 'UNIQUE'
(...NOT EXISTS books ( id [UUID] UNIQUE...)
What is the problem and how can I fix it?
I see three syntax issues. They are mainly related to CQL != SQL.
The first, is that NOT NULL is not valid at column definition time. Cassandra doesn't enforce constraints like that at all, so for this case, just get rid of all of them.
Next, Cassandra CQL does not allow default values, so this won't work:
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
Providing the current timestamp for created_at is something that will need to be done at write-time. Fortunately, CQL has a few of built-in functions to make this easier:
INSERT INTO books (id, user_id, created_at)
VALUES (uuid(), 'userOne', toTimestamp(now()));
In this case, I've invoked the uuid() function to generate a Type-4 UUID. I've also invoked now() for the current time. However now() returns a TimeUUID (Type-1 UUID) so I've nested it inside of the toTimestamp function to convert it to a TIMESTAMP.
Finally, UNIQUE is not valid.
user_id TEXT UNIQUE NOT NULL,
It looks like you're trying to make sure that duplicate user_ids are not stored with each id. You can help to ensure uniqueness of the data in each partition by adding user_id to the end of the primary key definition as a clustering key:
CREATE TABLE IF NOT EXISTS books (
id UUID,
user_id TEXT,
...
PRIMARY KEY (id, user_id));
This PK definition will ensure that data for books will be partitioned by id, containing multiple user_id rows.
Not sure what the relationship is between books and users is, though. If one book can have many users, then this will work. If one user can have many books, then you'll want to switch the order of the keys to this:
PRIMARY KEY (user_id, id));
In summary, a working table definition for this problem looks like this:
CREATE TABLE IF NOT EXISTS books (
id UUID,
user_id TEXT,
scale TEXT,
title TEXT,
description TEXT,
reward map<INT,TEXT>,
image_url TEXT,
video_url TEXT,
created_at TIMESTAMP,
PRIMARY KEY (id, user_id));

Mismatched unique constraint

Why I get this message:
mismatched input 'UNIQUE' expecting ')' (...KEY (user_id),CONSTRAINT email_uq [UNIQUE]...)
I want to create this table:
CREATE TABLE users_by_id (user_id uuid, email text, password text, username text, user_info frozen<user_information>, user_since timestamp, PRIMARY KEY (user_id),CONSTRAINT email_uq UNIQUE (email));
CONSTRAINT is not supported by CQL and Cassandra. Applications have to take care of any constraint which you want to have. Below query will work fine
CREATE TABLE users_by_id (user_id uuid,\
email text,\
password text,\
username text,\
user_info frozen<user_information>,\
user_since timestamp,\
PRIMARY KEY (user_id));

SELECT comment FROM comments_by_video WHERE uuid = 'with id 357c33b4-9054-a5e1- 8da8-d9e38294fac1';

I create table with
CREATE TABLE comments_by_video (
videoid uuid,
userid uuid,
comment text,
PRIMARY KEY(videoid, commentid));
and copy the table.
I excuted this query below
SELECT comment FROM comments_by_video WHERE userid = 'with id 357c33b4-9054-a5e1- 8da8-d9e38294fac1';
and got this error.
InvalidRequest: Error from server: code=2200 [Invalid query] message="Invalid STRING constant (with id 357c33b4-9054-a5e1- 8da8-d9e38294fac1) for "userid" of type uuid"
PLEASE HELP!
First error - UUIDs are written as-is, without quotes: 357c33b4-9054-a5e1- 8da8-d9e38294fac1
Second error - you're having condition on the field that isn't a partition key - this will require full table scan and won't work at scale. In Cassandra table structure is modeled around queries, so you'll need to have a table with partition key for userid
I recommend to read first chapters of this free book to understand how Cassandra works.

com.datastax.driver.core.exceptions.InvalidQueryException: Invalid operator IN for PRIMARY KEY part

I have cassandra 2.1.15.
I have this table
CREATE TABLE ks_mobapp.messages (
pair_id text,
belong_to text,
message_id timeuuid,
cli_time bigint,
sender text,
text text,
time bigint,
PRIMARY KEY ((pair_id, belong_to), message_id)
) WITH CLUSTERING ORDER BY (message_id DESC)
I was trying to delete multiple record as
instances.getCqlSession().execute(QueryBuilder.delete()
.from(AppConstants.KEYSPACE, "messages")
.where(QueryBuilder.eq("pair_id", pairId))
.and(QueryBuilder.eq("belong_to", currentUser.value("userId")))
.and(QueryBuilder.in("message_id", msgId)));
I am getting error:
Caused by: com.datastax.driver.core.exceptions.InvalidQueryException: Invalid operator IN for PRIMARY KEY part message_id
Then I tried:
Session session = instances.getCqlSession();
PreparedStatement statement = session.prepare("DELETE FROM ks_mobApp.messages WHERE pair_id = ? AND belong_to = ? AND message_id = ?;");
Iterator<String> iterator = msgId.iterator();
while(iterator.hasNext()) {
try {
session.executeAsync(statement.bind(pairId, currentUser.value("userId"), UUID.fromString(iterator.next())));
} catch(Exception ex) {
}
}
Its working nice. Is this the correct way? I can't use IN for same partition key ?
DELETE in Query only supported for partition key.
Delete IN relation is only supported for partition key)
There are some WHERE clause restrictions for the UPDATE and DELETE statements in cassandra 2.x
more specifically you can only use the IN operator on the last partition key column. So in your case the last partition column is belong_to. so IN can only be used on that column.
However these limitation are removed in cassandra 3.0. and it will allow
IN to be specified on any partition key column
IN to be specified on any clustering column
Here is the patch https://issues.apache.org/jira/browse/CASSANDRA-6237
Read this also http://www.datastax.com/dev/blog/a-deep-look-to-the-cql-where-clause

Cassandra invalid query "Map-entry equality predicates on frozen map column device_details are not supported"

I have the following table:
CREATE TABLE dove.backend_events (
log_time_local timeuuid,
username text,
log_type text,
log_time timestamp,
device_category text,
log text,
device_details frozen<map<text, text>>,
PRIMARY KEY (log_time_local, username, device_details)
);
I am running this query: SELECT * FROM dove.backend_events WHERE device_details['category'] = 'mobile' ALLOW FILTERING;
I am getting this error: InvalidRequest: code=2200 [Invalid query] message="Map-entry equality predicates on frozen map column device_details are not supported"
What is causing it and how do I fix it? This error is not occurring when device_details is not part of the primary key and is not frozen.
You could add an index for device_details instead of setting it as primary key (and without freezing it):
CREATE TABLE dove.backend_events (
log_time_local timeuuid,
username text,
log_type text,
log_time timestamp,
device_category text,
log text,
device_details map<text, text>,
PRIMARY KEY (log_time_local, username)
);
CREATE INDEX dove.device_details_index ON dove.backend_events (ENTRIES(device_details));
This way you could run your query efficiently and without having to use ALLOW FILTERING:
SELECT * FROM dove.backend_events WHERE device_details['category'] = 'mobile';

Resources