[ 
https://issues.apache.org/jira/browse/CASSANDRA-15252?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Alex Petrov updated CASSANDRA-15252:
------------------------------------
    Reviewers: Marcus Eriksson  (was: David Capwell, Marcus Eriksson)

> Don't consider current keyspace in prepared statement id when the query is 
> qualified
> ------------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-15252
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-15252
>             Project: Cassandra
>          Issue Type: Bug
>          Components: Messaging/Client
>            Reporter: Olivier Michallat
>            Assignee: Alex Petrov
>            Priority: Normal
>
> {{QueryProcessor.computeId}} takes into account the session's current 
> keyspace in the MD5 digest.
> {code}
> String toHash = keyspace == null ? queryString : keyspace + queryString;
> {code}
> This is desirable for unqualified queries, because switching to a different 
> keyspace produces a different statement. However, for a qualified query, the 
> current keyspace makes no difference, the prepared id should always be the 
> same.
> This can lead to an infinite reprepare loop on the client. Consider this 
> example (Java driver 3.x):
> {code}
>     Cluster cluster = null;
>     try {
>       cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
>       Session session = cluster.connect();
>       session.execute(
>           "CREATE KEYSPACE IF NOT EXISTS test WITH replication = {'class': 
> 'SimpleStrategy', 'replication_factor': 1}");
>       session.execute("CREATE TABLE IF NOT EXISTS test.foo(k int PRIMARY 
> KEY)");
>       PreparedStatement pst = session.prepare("SELECT * FROM test.foo WHERE 
> k=?");
>       // Drop and recreate the table to invalidate the prepared statement 
> server-side
>       session.execute("DROP TABLE test.foo");
>       session.execute("CREATE TABLE test.foo(k int PRIMARY KEY)");
>       session.execute("USE test");
>       // This will try to reprepare on the fly
>       session.execute(pst.bind(0));
>     } finally {
>       if (cluster != null) cluster.close();
>     }
> {code}
> When the driver goes to execute the bound statement (last line before the 
> finally block), it will get an UNPREPARED response because the statement was 
> evicted from the server cache (as a result of dropping the table earlier).
> In those cases, the driver recovers transparently by sending another PREPARE 
> message and retrying the bound statement.
> However, that second PREPARE cached the statement under a different id, 
> because we switched to another keyspace. Yet the driver is still using the 
> original id (stored in {{pst}}) when it retries, so it will get UNPREPARED 
> again, etc.
> I would consider this low priority because issuing a {{USE}} statement after 
> having prepared statements is a bad idea to begin with. And even if we fix 
> the generated id for qualified query strings, the issue will remain for 
> unqualified ones.
> We'll add a check in the driver to fail fast and avoid the infinite loop if 
> the id returned by the second PREPARE doesn't match the original one. That 
> might be enough to cover this issue.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to