Skip to content

StatementFactory should accept keyspace for statement creation #1275

Closed
@KasperDeng

Description

@KasperDeng

Background

Cassanda introduced a new prepare statement behavior in February 2022. The behavior will makes some incompatible changes and would a prepared statement id mismatch for existing clients in most case of upgrade scenario with traffic requests.
The new prepare statement behavior required the cassandra client to have a fully qualified table name (format: keyspace.table) in CQL for statement preparation.

There is a configuration to force the new behavior of preparing statement, force_new_prepared_statement_behaviour. But from version 3.0.26, 3.11.12, 4.0.2, 4.1, the behavior is enforced forcefully.

If the client is not in such behavior, there are some warning logs in Cassandra service side.

ClientWarn.instance.warn(String.format("`USE <keyspace>` with prepared statements is considered to be an anti-pattern due to ambiguity in non-qualified table names. " + "Please consider removing instances of `Session#setKeyspace(<keyspace>)`, `Session#execute(\"USE <keyspace>\")` and `cluster.newSession(<keyspace>)` from your code, and " + "always use fully qualified table names (e.g. <keyspace>.<table>). " + "Keyspace used: %s, statement keyspace: %s, statement id: %s", getRawKeyspace(),preparedKeyspace, statementId));
state.getClientState().warnAboutUseWithPreparedStatements(statementId, prepared.keyspace);
String msg = String.format("Tried to execute a prepared unqalified statement on a keyspace it was not prepared on. " +
  " Executing the resulting prepared statement will return unexpected results: %s (on keyspace %s, previously prepared on %s)",
statementId, state.getClientState().getRawKeyspace(), prepared.keyspace);
nospam.error(msg);

Problems in spring-data-cassandra

Spring data cassandra provides a highly abstraction to developer to access the Cassandra database, especially the data repository makes the code clean and hide the details of the cassandra driver.
But for the case, it looks the underlay cql is based on the StatementFactory, which creates the StatementBuilder by Cassandra's driver's class QueryBuilder. But only uses its API (selectFrom, insert, insertInto, update, deleteFrom) with table name, not the API with keyspace.
Then the keyspace attribute is null in DefaultSelect, DefaultInsert, DefaultUpdate, DefaultDelete, then the CqlHelper.qualify cannot build the keyspace in the cql in asCql() of above classes.

Candidate Solutions

A possible solution in current our application is to clone such StatementFactory class and use those QueryBuilder APIs with keyspace parameter, and injects such StatementFactory instance to ReactiveCassandraTemplate based on Spring bean wire mechanism.

Can spring-data-cassandra have some mechanism to improve this part?
BTW, should the cassandra entity have @keyspace annotation which is also support the SpEL for runtime rendering mechanism, besides the @table annotation.
And the @keyspace can be integrated with the @query annotation or named queries as well?

Reference

Don't consider current keyspace in prepared statement id when the query is qualified
Fix Prepared Statements behaviours after 15252

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions