I have a dictionary that defines some configuration, where I will not know in advance the exact filters that my user wants to build
it's specified like this:
{"col1": ["val1", "~val2"],
"col2": ["val3", "val4"],
"col3": ["val5", "val6", "~val7", "~val8"]}
where this should translate into:
WHERE (
col1 LIKE val1
AND
col1 NOT LIKE val2
)
OR (
col2 LIKE val3
OR
col2 LIKE val4
)
OR
(
(
col3 LIKE val5
OR
col3 LIKE val6
)
AND
col3 NOT LIKE val7
AND
col3 NOT LIKE val8
)
the criteria at the top level is always an 'or' (you either match one column as specified or match another column as specified) never 'and'
however, within the list, you can match any of the positive criteria but none of the negative criteria (criteria here being strings)
my attempt so far at building this dynamically looks something like this:
def make_filter(definition):
f = {}
for variable in definition:
v = getattr(Target, variable)
f[v] = []
for col in definition[variable]:
f[v].append(col)
return f
def make_query(def_dict):
q = destination.query(Target)
filter = make_filter(def_dict)
for col in filter:
for val in filter[col]:
if '~' in val:
q = q.filter(sa.not_(col.like(val)))
else:
q = q.filter(col.like(val))
for record in q.all():
# do stuff
but obviously, that combines all the criteria by 'and' - I can't see a way to dynamically combine with 'or' for an unknown number of conditions...
I can modify the specifications if that's a better way to solve this problem as long as the same set of criteria can be specified unambiguously. I haven't specifically required users to put all positive criteria before all negative criteria, but that's reasonable for instance.