I have an instance method that is used to construct a Cassandra query, and I'm looking for a way to more safely parametrize the table name in a query without using string formatting.
For example,
def some_method(self, table_name):
statement = f"SELECT COUNT(*) FROM {self.table_name}"
results = self.cassandra.session.execute(query=statement)
...
I don't believe SimpleStatement or a PreparedStatement can be used to bind a table name.
If you are using DataStax's Python Driver for Cassandra (as of v3.28), there is no way to parametrize or bind the table name using Session.execute / Session.execute_async, because it only expects the column values to be in the
parametersargument, and the table name to be hardcoded in thestatementstring. You'll have to resort to string formatting, which then makes your linters complain about possible SQL injections (which you then have to silence with# noqaand such).I managed to work around this by using
cassandra.cqlengine.modelsinstead which is still part of the same Python driver package: https://docs.datastax.com/en/developer/python-driver/3.28/api/cassandra/cqlengine/models/.You can dynamically create the model for your table during runtime (during which you can pass the table names from somewhere), and then use that model to perform the queries.
First, define an abstract model:
Then on runtime, create a concrete model:
The
typecall is Python's built-intypefunction for creating a type, in this case a concretePersonclass based oncassandra.cqlengine.models.Model. The arguments totypein order are:table_name)(MyAbstractModel,))table_attrs), which in this case should be__table_name__(see https://docs.datastax.com/en/developer/python-driver/3.28/api/cassandra/cqlengine/models/)If your code runs successfully, you'll see that the table is created:
Once you've got your table, you can now use that to make your queries as a replacement to using
session.execute. Depending on how many tables you'll need to create, you'll probably need a mapping of the table names to their models:Copying the example from the question where the table name is a parameter of
some_method:Since the models are dynamically created, just make sure that
__table_name__and thetypename are consistentRead the documentation on Making Queries with models.