Roman Puchkovskiy
Roman Puchkovskiy

Reputation: 11875

Cassandra: copy from Row to BoundStatement

I'm trying to write a generic tool for copying Cassandra table contents from one keyspace to another one (probably in a different cluster). All the tables are not too large.

Here is what I do:

Session source = ...
Session destination = ...
TableMetadata table = ...

final ResultSet rs = source.execute("select * from " + table.getName());
String insertCql = ...
PreparedStatement preparedStatement = destination.prepare(insertCql);

for (Row row : rs) {
    final BoundStatement boundStatement = preparedStatement.bind();

    for (int i = 0; i < rs.getColumnDefinitions().size(); i++) {
        // bind column value from row to bountStatement
    }

    session.execute(boundStatement);
}

The problem is how to copy the column value from row to boundStatement. I can read it with row.getObject(i), but there is no corresponding setObject() in BoundStatement.

More precisely, this method exists in version 2.2 of the driver (it's cassandra-driver-dse), but that version does not work with Cassandra 3, and in version 3 of the driver (cassandra-driver-core) setObject() method does not exist. Instead, there are bunch of set() methods, all of them require Class, TypeToken or TypeCodec.

Where can I get those? ColumnDefinition only gives me DataType. It seems a doubtful idea to use row.getObject(i).getClass() to get Class.

Maybe there is a better approach to this task (schema-agnostic copying)?

I can look at DataType if the column and make a case per type to use setString() and so on, but this seems a bit overcomplicated and fragile.

Upvotes: 1

Views: 184

Answers (1)

mikea
mikea

Reputation: 6667

You need to use bind variables in your insert statement and then bind the prepared statement with the column values from the result. Something along the lines of:

String insertCql = "INSERT INTO ks.tb (...) values (?,?,...)";
for (Row row : rs) {
    List bindVariables = new ArrayList();
    for (int i = 0; i < rs.getColumnDefinitions().size(); i++) {
        bindVariables.add(rs.getObject(i));
    }
    final BoundStatement boundStatement = preparedStatement.bind(bindVariables.toArray(new Object[0]));
    session.execute(boundStatement);
}

Upvotes: 4

Related Questions