StatementFactory's statement cache is never reset

Description

When running a query, the driver prepares it and stores the prepared statement into a cache (_statementCache) indexed by statement string.

So any CQL query matching one that was already run will be run using the same PreparedStatement class, meaning that it will be in the same Keyspace, and have the same prepared statement Id.
This means that switching KS or cluster won't work since the same prepared statement will be used.

A suggested fix would be to either reset the statement cache when connecting to a new cluster / switching KS or better, using all the significant parameters (KS, CL, etc.) to index the _statementCache.

Environment

None

Activity

Show:
Jorge Bay Gondra
June 2, 2015, 11:25 PM

The session controls the keyspace in which the queries are executed, this is not changed by the Mapper or Linq.

When you are dealing with multiple keyspaces in 1 app, you have 2 options:
1- Create 2 sessions.
2- Use 1 session and fully qualify your table names: SELECT * FROM ks1.tbl1.

If you want to do the second option with Linq, that is possible too by specifying the keyspace when creating the Mapping definition:

KévinL
June 2, 2015, 11:53 PM

I understand and agree with 2.

But concerning 1, if I wanted to use Linq with attributes in this configuration, I would need to specify a different MappingConfiguration so that

is not used for both Keyspaces, right?

Also, what would happen if I ran a query on one cluster using a session, then closed it and created a new session connected to another cluster, and ran the same query string ? Since the cache would contain a PreparedStatement for this query string, would it be used on the wrong cluster, where it is not prepared? (I admit that this is not a common use case, but I want to make sure I understand how the driver behaves).

Jorge Bay Gondra
June 4, 2015, 12:02 AM

In that case, it would be advisable to use 2 MappingConfigurations. As you mention, there can be an (unlikely) issue with the same prepared statement using 2 different sessions.

We created a global MappingConfiguration when we ported CqlPoco, as a way for users to share configuration between any of the mapping components (Linq / Mapper). Additionally, we made instance creation of Table<T> and Mapper cheap, avoiding users to maintain a new instances (Cluster, Session and Mapper or multiple Table<T> instance) in their application code.

We have a couple of options:
A- Add more information about this in the documentation.
B- Create a new ticket to use the session hash code and the current keyspace as part of the key of the statement cache.

KévinL
June 4, 2015, 5:18 AM

Solution B would solve my problem, because for the moment the only global solution solution I have that can be done globally is to call internal void Clear() on GlobalInstance (through reflection, I know, it's quite ugly).
I could pass MappingConfiguration everywhere or use QueryOptions.NoPrepare but I wanted a solution that did not need me to go through all the queries in the code base.

(Also, A could be a good addition I guess).

Jorge Bay Gondra
June 5, 2015, 9:08 PM

I created to fully qualify the statement cache key. Thanks !

Not a Problem

Assignee

Unassigned

Reporter

KévinL

Labels

None

Reproduced in

2.5.2

PM Priority

None

Fix versions

None

External issue ID

None

Doc Impact

None

Reviewer

None

Pull Request

None

Epic Link

None

Sprint

None

Pull Requests

None

Size

None

Components

Affects versions

Priority

Major