make sure prepared result metadata is replaced on reprepare
PYTHON-621
This commit is contained in:
@@ -3549,6 +3549,10 @@ class ResponseFuture(object):
|
|||||||
|
|
||||||
if isinstance(response, ResultMessage):
|
if isinstance(response, ResultMessage):
|
||||||
if response.kind == RESULT_KIND_PREPARED:
|
if response.kind == RESULT_KIND_PREPARED:
|
||||||
|
# result metadata is the only thing that could have changed from an alter
|
||||||
|
_, _, _, result_metadata = response.results
|
||||||
|
self.prepared_statement.result_metadata = result_metadata
|
||||||
|
|
||||||
# use self._query to re-use the same host and
|
# use self._query to re-use the same host and
|
||||||
# at the same time properly borrow the connection
|
# at the same time properly borrow the connection
|
||||||
request_id = self._query(self._current_host)
|
request_id = self._query(self._current_host)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from cassandra import InvalidRequest
|
|||||||
|
|
||||||
from cassandra import ConsistencyLevel
|
from cassandra import ConsistencyLevel
|
||||||
from cassandra.cluster import Cluster
|
from cassandra.cluster import Cluster
|
||||||
from cassandra.query import PreparedStatement, UNSET_VALUE
|
from cassandra.query import PreparedStatement, UNSET_VALUE, tuple_factory
|
||||||
from tests.integration import get_server_versions
|
from tests.integration import get_server_versions
|
||||||
|
|
||||||
|
|
||||||
@@ -385,3 +385,39 @@ class PreparedStatementTests(unittest.TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(InvalidRequest):
|
with self.assertRaises(InvalidRequest):
|
||||||
self.session.execute(prepared, [0])
|
self.session.execute(prepared, [0])
|
||||||
|
|
||||||
|
def test_invalidated_result_metadata(self):
|
||||||
|
"""
|
||||||
|
Tests to make sure cached metadata is updated when an invalidated prepared statement is reprepared.
|
||||||
|
|
||||||
|
@since 2.7.0
|
||||||
|
@jira_ticket PYTHON-621
|
||||||
|
|
||||||
|
Prior to this fix, the request would blow up with a protocol error when the result was decoded expecting a different
|
||||||
|
number of columns.
|
||||||
|
"""
|
||||||
|
s = self.session
|
||||||
|
s.result_factory = tuple_factory
|
||||||
|
|
||||||
|
table = "test1rf.%s" % self._testMethodName.lower()
|
||||||
|
|
||||||
|
s.execute("DROP TABLE IF EXISTS %s" % table)
|
||||||
|
s.execute("CREATE TABLE %s (k int PRIMARY KEY, a int, b int, c int)" % table)
|
||||||
|
s.execute("INSERT INTO %s (k, a, b, c) VALUES (0, 0, 0, 0)" % table)
|
||||||
|
|
||||||
|
wildcard_prepared = s.prepare("SELECT * FROM %s" % table)
|
||||||
|
original_result_metadata = wildcard_prepared.result_metadata
|
||||||
|
self.assertEqual(len(original_result_metadata), 4)
|
||||||
|
|
||||||
|
r = s.execute(wildcard_prepared)
|
||||||
|
self.assertEqual(r[0], (0, 0, 0, 0))
|
||||||
|
|
||||||
|
s.execute("ALTER TABLE %s DROP c" % table)
|
||||||
|
|
||||||
|
# Get a bunch of requests in the pipeline with varying states of result_meta, reprepare, resolved
|
||||||
|
futures = set(s.execute_async(wildcard_prepared.bind(None)) for _ in range(200))
|
||||||
|
for f in futures:
|
||||||
|
self.assertEqual(f.result()[0], (0, 0, 0))
|
||||||
|
self.assertIsNot(wildcard_prepared.result_metadata, original_result_metadata)
|
||||||
|
s.execute("DROP TABLE %s" % table)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user