You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "Alex Petrov (Jira)" <ji...@apache.org> on 2021/02/26 17:00:00 UTC

[jira] [Assigned] (CASSANDRA-15252) Don't consider current keyspace in prepared statement id when the query is qualified

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

Alex Petrov reassigned CASSANDRA-15252:
---------------------------------------

    Assignee: Alex Petrov

> 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
>            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-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org