pythonsqlpypika

Pypika: Is it possible to dynamically change the operator in where clause


I am using Pypika to query a HDB. Usually I create the query and then add where clauses like this:

query = query.where(table.ID == value)

Now I have a situation where I don't know which operator will be used. It can be any of the possible operators:

['==', '<>', '<', '>', '<=', '>=']

Is there a way to specify the operator for Pypika dynamically?

At the moment I am doing this:

if operator == '<=':
        query = query.where(table.ID == value)
elif operator == '>=':
    ...

But I would like to do something like this:

operator = '=='
query = query.where(table.ID {operator} value)

Solution

  • I see that you posted this about 30 days ago, so I hope you have found a solution in the meantime. But, if you haven't - I ran into the same issue, and the following worked for me: writing a function that takes an operator from the operator module, and produces the query:

    from pypika import Table, Field, Query
    from typing import List, Callable
    import operator
    
    
    def gen_my_query(varname: str, 
                 my_operator: Callable, 
                 permitted_value: int, 
                 my_table: str, 
                 selected_vars: List[str]):
    
        my_query = Query.from_(Table(my_table)
                              ).select(','.join(selected_vars)
                              ).where(
                                      my_operator(Field(varname), permitted_value)
                              ).get_sql(quote_char=None)
    
        return my_query
    

    The function can be used as follows:

    gen_my_query(varname='id', 
                 my_operator=operator.eq, 
                 permitted_value=1, 
                 my_table='table', 
                 selected_vars=["var1", "var2", "var3"])
    

    Which produces the following result:

    'SELECT var1,var2,var3 FROM table WHERE id=1'
    

    If you want to continue using the operators defined as strings, you could e.g. define a mapping in a dictionary and refactor the function above to grab the correct operator from the dict, e.g.:

    my_operators = {'==': operator.eq,
                    '<': operator.le} # ... etc.
    

    Hope this helps!