Inserting rows in Cassandra table with 3 fields as composite key - exception

I'm a newbie to Cassandra and I need it for a quick and small adhoc job.
However, I'm on a stalemate with a problem. I have a column family created
with the CQL below:
CREATE TABLE dummy_file_test
(
dtPtn INT,
pxID INT,
startTm INT,
endTm INT,
patID BIGINT,
efile BLOB,
PRIMARY KEY(dtPtn, pxID, startTm)
);
I wrote the following method to insert data into the table.
public static void insertDataKey(HashMap nameValuePair, String colFamily) {
try {
Cluster cluster = HFactory.getOrCreateCluster(clusterName, hostPort);
Keyspace keyspace = HFactory.createKeyspace(CASSANDRA_DUMMY_KEY_SPACE, cluster);
Integer dtPtn = (Integer)nameValuePair.get("dtPtn");
Integer pxID = (Integer)nameValuePair.get("pxID");
Integer startTm = (Integer)nameValuePair.get("startTm");
Integer endTm = (Integer)nameValuePair.get("endTm");
Long patID = (Long)nameValuePair.get("patID");
byte[] efile = (byte[])nameValuePair.get("efile");
HColumn<String, Integer> column1 = HFactory.createColumn("dtPtn", dtPtn, new StringSerializer(), IntegerSerializer.get());
HColumn<String, Integer> column2 = HFactory.createColumn("pxID", pxID, new StringSerializer(), IntegerSerializer.get());
HColumn<String, Integer> column3 = HFactory.createColumn("startTm", startTm, new StringSerializer(), IntegerSerializer.get());
HColumn<String, Integer> column4 = HFactory.createColumn("endTm", endTm, new StringSerializer(), IntegerSerializer.get());
HColumn<String, Long> column5 = HFactory.createColumn("patID", patID, new StringSerializer(), LongSerializer.get());
HColumn<String, byte[]> column6 = HFactory.createColumn("efile", efile, new StringSerializer(), BytesArraySerializer.get());
Composite rowKey = new Composite();
rowKey.addComponent("dtPtn", StringSerializer.get());
rowKey.addComponent(dtPtn, IntegerSerializer.get());
rowKey.addComponent("pxID", StringSerializer.get());
rowKey.addComponent(pxID, IntegerSerializer.get());
rowKey.addComponent("startTm", StringSerializer.get());
rowKey.addComponent(startTm, IntegerSerializer.get());
Mutator<Composite> mutator = HFactory.createMutator(keyspace, CompositeSerializer.get());
mutator.addInsertion(rowKey, colFamily, column1);
mutator.addInsertion(rowKey, colFamily, column2);
mutator.addInsertion(rowKey, colFamily, column3);
mutator.addInsertion(rowKey, colFamily, column4);
mutator.addInsertion(rowKey, colFamily, column5);
mutator.addInsertion(rowKey, colFamily, column6);
mutator.execute();
} catch (Exception ex) {
ex.printStackTrace();
}
}
However, when I run the code, I get
InvalidRequestException(why:Expected 4 or 0 byte int (21))
I'm pretty much confused with Hector APIs and can't find any complete tutorial/material that I can fully rely on. Any advice in resolving the above would be of a great help.
Thanks in advance.
ps: I'm on Cassandra 1.2

If you're creating schemas in CQL you will probably be better off accessing your data through CQL too. But you can still access it through the thrift interface.
When using composite primary keys in CQL as you have specified, the first key is the partition key which becomes the row key. The other keys are part of the column composite.
So for your example, if you did
insert into dummy_file_test (dtPtn, pxID, startTm, endTm, patID, efile) values (1, 2, 3, 4, 5, 0x06);
then list in cassandra-cli:
[default#ks] list dummy_file_test;
RowKey: 1
=> (column=2:3:, value=, timestamp=1366620262555000)
=> (column=2:3:efile, value=06, timestamp=1366620262555000)
=> (column=2:3:endtm, value=00000004, timestamp=1366620262555000)
=> (column=2:3:patid, value=0000000000000005, timestamp=1366620262555000)
you see the row key is simply the integer 1 corresponding to dtPtn. The other columns in the primary key have been prefixed onto the column name.
If you want to use Hector to insert into this you need to use dtPtn for your row key, then a composite column key of pxID:startTm:col_name for your columns.
You can also tell Cassandra to make your partition key a composite of your columns. To do this, you need extra brackets in the primary key clause:
CREATE TABLE dummy_file_test
(
dtPtn INT,
pxID INT,
startTm INT,
endTm INT,
patID BIGINT,
efile BLOB,
PRIMARY KEY((dtPtn, pxID, startTm))
);
Now your row key is a composite of dtPtn, pxID, startTm:
[default#ks] list dummy_file_test;
RowKey: 1:2:3
=> (column=, value=, timestamp=1366620916952000)
=> (column=efile, value=06, timestamp=1366620916952000)
=> (column=endtm, value=00000004, timestamp=1366620916952000)
=> (column=patid, value=0000000000000005, timestamp=1366620916952000)
Note that the column names don't appear in the row key composite, so you don't need to add them. Your code should simply be:
Composite rowKey = new Composite();
rowKey.addComponent(dtPtn, IntegerSerializer.get());
rowKey.addComponent(pxID, IntegerSerializer.get());
rowKey.addComponent(startTm, IntegerSerializer.get());

Related

SQLAlchmemy — get related objects with reflected tables

I am quite new to sqlalchemy, I guess I am missing just a little piece here.
There is this Database (sql):
create table CEO (
id int not null auto_increment,
name char(255) not null,
primary key(id),
unique(name)
);
create table Company (
id int not null auto_increment,
name char (255) not null,
ceo int not null,
primary key(id),
foreign key(ceo) references CEO(id)
);
That code:
from sqlalchemy import create_engine, Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import registry, relationship, Session
engine = create_engine(
"mysql+pymysql:xxxxxxxx",
echo=True,
future=True
)
mapper_registry = registry()
Base = mapper_registry.generate_base()
#####################
## MAPPING CLASSES ##
#####################
class CEO(Base):
__table__ = Table('CEO', mapper_registry.metadata, autoload_with=engine)
companies = relationship('Company', lazy="joined")
class Company(Base):
__table__ = Table('Company', mapper_registry.metadata, autoload_with=engine)
##########################
## FINALLY THE QUESTION ##
##########################
with Session(engine, future=True) as session:
for row in session.query(CEO).all():
for company in row.companies:
## Just the id of the Ceo is yielded here
print(company.ceo)
So CEO.companies works as expected, but Company.ceo does not, even though the FOREIGN KEY is defined.
What is a proper setup for the Company Mapper class, such that Company.ceo yields the related object?
I could figure out, that the automatic setup did not work, because the column Company.ceo exists in the Database and represents the ID of a given row. To make everything work, I needed to rename Company.ceo to Company.ceo_id and add the relation manually like so:
CompanyTable = Table('Company', Base.metadata, autoload_with=engine)
class Company(Base):
__table__ = CompanyTable
ceo_id = CompanyTable.c.ceo
ceo = relationship('CEO')
I would like to know if it would be possible to rename the column within the Table(…) call, such that I could get rid of the extra CompanyTable thing.

Storing a byte array into MySQL binary column with JdbcTemplate

I have a MySQL table (simplified):
CREATE TABLE `tokens` (
`token` BINARY(16) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And I try to insert a row like this:
JdbcTemplate jdbcTemplate; // org.springframework.jdbc.core.JdbcTemplate
...
String sql = "INSERT INTO `tokens` (`token`) VALUES (?)";
String token = "123e4567e89b12d3a456426655440000"; // UUID
jdbcTemplate.update(sql, new Object[]{token.getBytes()});
But I get this exception:
Data truncation: Data too long for column 'token' at row 1
What do I do wrong? Thanks.
Edit: see my answer, I missed the hexadecimal conversion (token is an UUID).
Here is the solution to store the token (which is an UUID):
jdbcTemplate.update(sql, new Object[]{DatatypeConverter.parseHexBinary(token)});
Let us know if there are other ways...

How to use DBNull.Value to check if table column is null; return default value if not null

My current while statement is being used to get all the values from a table (two integer and one string value) and it looks like this:
while (reader.Read())
{
Int16 a = reader.GetInt16("id");
**int b = (reader["nullable_id"] != DBNull.Value) ? Convert.ToInt16(reader["nullable_id"]): 0;**
string c = reader.GetString("string");
Site page = new Site(a, b, c);
list.Add(page);
}
What I am using it to do is to GET all the values in a table. There's a primary key, a foreign key, and a regular string value (a, b, and c respectively). This works fine as is by allowing me to pull the primary and the string value while ignoring the foreign key that currently has null values. However, if I were to alter one of the foreign keys's value to 32 from 'null', the value won't return when I execute the GET method.
So my question is, how do I check whether or not the foreign key is null or not and then, if it is not null, it returns the value stored in the database and if it is null, then it leaves the value as null? I'm relatively new with using DBNull so I may be implementing it incorrectly.
simple change use this
while (reader.Read())
{
Int16 a = Convert.ToInt16(reader["id"]);
int b = (!string.IsNullOrEmpty(Convert.ToString(reader["nullable_id"]))) ? Convert.ToInt16(reader["nullable_id"]): 0;
string c = Convert.ToString(reader["string"]);
Site page = new Site(a, b, c);
list.Add(page);
}

During synchronization Foreign key null (error)

In my database I want to synchronize two tables. I use auth_user(Default table provided by Django) table for registration and there was another table user-profile that contain entities username, email, age etc. During the synchronization how to update Foriegn key?
def get_filename(instance,filename):
return "upload_files/%s_%s" % (str(time()).replace('.','_'),filename)
def create_profile(sender, **kwargs):
if kwargs["created"]:
p = profile(username = kwargs["instance"], email=kwargs["instance"])
p.save()
models.signals.post_save.connect(create_profile, sender=User)
class profile(models.Model):
username = models.CharField(max_length = 30)
email = models.EmailField()
age = models.PositiveIntegerField(default='15')
picture = models.FileField(upload_to='get_filename')
auth_user_id = models.ForeignKey(User)
Here in table profile during synchronization all columns are filled except auth_user_id. and there was an error
Exception Value:
(1048, "Column 'auth_user_id_id' cannot be null")
You have to alter your table and change the column auth_user_id_id datatype attribute that allows null.
Something like this:-
ALTER TABLE mytable MODIFY auth_user_id_id int;
Assuming auth_user_id_id as int datatype.(Columns are nullable by default)

Squeryl: KeyedEntity.id isn't updated on insert

I have a table definition
class Transaction(
val ...
) extends KeyedEntity[Long] {
val id:Long = 0
}
val transaction = table[Transaction]("transactions")
on(transaction) {t =>
declare(
t.id is unique
... (other fields)
)
}
The database table was not generated by Squeryl (I created it manually), but the "ID" column is set to PrimaryKey and AutoIncrement.
Now I'm inserting a row in this table:
val row = new Transaction(...)
val rowResult = transaction.insert(row)
println("Id1="+row.id+"; Id2="+rowResult.id)
The row is correctly inserted into the database and there an ID is assigned (!=0).
But the application prints "ID1=0; ID2=0" on the command line.
Why? And how do I get the assigned ID?
edit:
I did also try the table definition this way
class Transaction(
val id: Long,
...
) extends KeyedEntity[Long]
Didn't make any differences.
When I remove the declaration
t.id is unique
it works. So the problem is solved.
Is this a bug in squeryl?