Reputation: 63
EDIT: I thought that order in WHERE conditions in SQL matter and so was the reason for me asking for the solution to the problem. Therefore, I got my answer.
I am trying to set default query filter in sqlalchemy model, that executes every time the query is called.
But the problem is that it adds the filter at the end of the query, which breaks my SQL.
Is it possible to make it first filter in query?
I was following this recipe: https://github.com/sqlalchemy/sqlalchemy/wiki/FilteredQuery
Skeleton from the recipe:
# see the linked web page, for full code
@event.listens_for(Query, "before_compile", retval=True)
def before_compile(query):
for ent in query.column_descriptions:
entity = ent['entity']
if entity is None:
continue
insp = inspect(ent['entity'])
mapper = getattr(insp, 'mapper', None)
if mapper and issubclass(mapper.class_, HasPrivate):
query = query.enable_assertions(False).filter(
ent['entity'].public == True)
return query
# this is my filter
query = query.enable_assertions(False).filter(
ent['entity'].id != ent['entity'].other_id)
ent['entity'].id != ent['entity'].other_id
is put at the end of my SQL query.
Upvotes: 0
Views: 472
Reputation: 13129
I think you should add a break
statement when you add the filter to the query, otherwise you risk filtering on the same condition multiple times.
Looking at the internals of the filter method, I see the following code to execute for a list of conditions or criterions:
for criterion in list(criterion):
criterion = expression._expression_literal_as_text(criterion)
criterion = self._adapt_clause(criterion, True, True)
if self._criterion is not None:
self._criterion = self._criterion & criterion
else:
self._criterion = criterion
This implies that you can prepend the condition using the following code:
@event.listens_for(Query, "before_compile", retval=True)
def before_compile(query):
criterion = query._adapt_clause(criterion, True, True)
for ent in query.column_descriptions:
entity = ent['entity']
if entity is None:
continue
insp = inspect(ent['entity'])
mapper = getattr(insp, 'mapper', None)
if mapper and issubclass(mapper.class_, HasPrivate):
if query._criterion is not None:
query._criterion = criterion & query._criterion
else:
query._criterion = criterion
break
return query
Upvotes: 1