From 598c0628d743826ad4e052f091215e4de71ca2f7 Mon Sep 17 00:00:00 2001 From: Dan Tracy Date: Mon, 13 Jul 2015 13:08:21 -0400 Subject: [PATCH 1/2] Add prepared statement --- sprockets/clients/cassandra/__init__.py | 30 ++++++++++++++++++++++--- tests.py | 10 +++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/sprockets/clients/cassandra/__init__.py b/sprockets/clients/cassandra/__init__.py index 5785956..8120171 100644 --- a/sprockets/clients/cassandra/__init__.py +++ b/sprockets/clients/cassandra/__init__.py @@ -47,6 +47,8 @@ class CassandraConnection(object): """ + _prepared_statement_cache = {} + def __init__(self, ioloop=None): self._config = self._get_cassandra_config() self._cluster = Cluster(contact_points=self._config['contact_points'], @@ -80,6 +82,29 @@ class CassandraConnection(object): self._session = None self._cluster = None + def prepare(self, query, name=None): + """Create and cache a prepared statement using the provided query. + + This function will take a ``query`` and optional ``name`` parameter + and will create a new prepared statement for the provided ``query``. + The resulting statement object will be cached so future invocations + of this function will not incur the overhead or recreating the + statement. If ``name`` is provided it will be used as the key for + the cache, so you'll be able to call ``execute`` using the name. + + :pram str query: The query to prepare. + :pram str name: (Optional) name to use as a key in the cache. + + """ + key = name or query + stmt = CassandraConnection._prepared_statement_cache.get(key, None) + if stmt is not None: + return stmt + + stmt = self._session.prepare(query) + CassandraConnection._prepared_statement_cache[key] = stmt + return stmt + def execute(self, query, *args, **kwargs): """Asynchronously execute the specified CQL query. @@ -87,10 +112,9 @@ class CassandraConnection(object): keyword arguments. See cassandra-python documentation for definition of those parameters. """ - + stmt = CassandraConnection._prepared_statement_cache.get(query, query) tornado_future = Future() - cassandra_future = self._session.execute_async( - query, *args, **kwargs) + cassandra_future = self._session.execute_async(stmt, *args, **kwargs) self._ioloop.add_callback( self._callback, cassandra_future, tornado_future) return tornado_future diff --git a/tests.py b/tests.py index eb83ff5..5f36f7e 100644 --- a/tests.py +++ b/tests.py @@ -31,6 +31,7 @@ class TestCassandraConnectionClass(AsyncTestCase): def find_cassandra(self): uri = os.environ.get('CASSANDRA_URI', 'cassandra://localhost') hostname = uri[12:] + return [hostname.split(':')[0]] _, _, ips = socket.gethostbyname_ex(hostname) return ips @@ -66,3 +67,12 @@ class TestCassandraConnectionClass(AsyncTestCase): @gen_test def test_set_keyspace(self): self.connection.set_keyspace(self.keyspace) + + @gen_test + def test_prepared_statement(self): + yield self.connection.execute('use %s' % self.keyspace) + stmt = self.connection.prepare('SELECT * FROM names;', 'get_names') + copy = self.connection.prepare('SELECT * FROM names;', 'get_names') + self.assertIs(stmt, copy, 'Should return the cached statement') + results = yield self.connection.execute('get_names') + self.assertEqual(results[0].name, 'Peabody') From a724bc53ce656df240c969bd2eb1cc49ce5e41bb Mon Sep 17 00:00:00 2001 From: Dan Tracy Date: Mon, 13 Jul 2015 13:59:23 -0400 Subject: [PATCH 2/2] Remove wonky cache lookup in execute --- sprockets/clients/cassandra/__init__.py | 3 +-- tests.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sprockets/clients/cassandra/__init__.py b/sprockets/clients/cassandra/__init__.py index 8120171..75c2760 100644 --- a/sprockets/clients/cassandra/__init__.py +++ b/sprockets/clients/cassandra/__init__.py @@ -112,9 +112,8 @@ class CassandraConnection(object): keyword arguments. See cassandra-python documentation for definition of those parameters. """ - stmt = CassandraConnection._prepared_statement_cache.get(query, query) tornado_future = Future() - cassandra_future = self._session.execute_async(stmt, *args, **kwargs) + cassandra_future = self._session.execute_async(query, *args, **kwargs) self._ioloop.add_callback( self._callback, cassandra_future, tornado_future) return tornado_future diff --git a/tests.py b/tests.py index 5f36f7e..5ad5460 100644 --- a/tests.py +++ b/tests.py @@ -74,5 +74,5 @@ class TestCassandraConnectionClass(AsyncTestCase): stmt = self.connection.prepare('SELECT * FROM names;', 'get_names') copy = self.connection.prepare('SELECT * FROM names;', 'get_names') self.assertIs(stmt, copy, 'Should return the cached statement') - results = yield self.connection.execute('get_names') + results = yield self.connection.execute(stmt) self.assertEqual(results[0].name, 'Peabody')