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 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
 | 
			
		||||
                # at the same time properly borrow the connection
 | 
			
		||||
                request_id = self._query(self._current_host)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ from cassandra import InvalidRequest
 | 
			
		||||
 | 
			
		||||
from cassandra import ConsistencyLevel
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -385,3 +385,39 @@ class PreparedStatementTests(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
        with self.assertRaises(InvalidRequest):
 | 
			
		||||
            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