Here what I got for now :

from pyparsing import nestedExpr
# Not the worse case but has enough complexity to start with
grouped_query_string = \
        '((((a_table.integer_field > 1) & ' \
        '   (a_table.integer_field not equal 2) &' \
        '   (~a_table.integer_field in "200, 300, 400")) & ' \
        '(a_table.integer_field =< 3000)) | ' \
        '(a_table.boolean_field = "True"))'

list_of_nested_query_string = nestedExpr('(',
')').parseString(grouped_query_string).asList()

ops_translation = {
        '==': '=',
        '!=': '!=',
        '<': '<',
        '>': '>',
        '<=': '<=',
        '>=': '>=',
        '<>': '!=',
        '=<': '<=',
        '=>': '>=',
        '=': '=',
        'less or equal than': '<=',
        'greater or equal than': '>=',
        'equal or less than': '<=',
        'equal or greater than': '>=',
        'less or equal': '<=',
        'greater or equal': '>=',
        'equal or less': '<=',
        'equal or greater': '>=',
        'not equal to': '!=',
        'not equal': '!=',
        'equal to': '=',
        'equal': '=',
        'equals': '=',
        'less than': '<',
        'greater than': '>',
        'starts with': 'startswith',  # ??
        'ends with': 'endswith',  # ??
        'not in': 'notbelongs',  # ??
        'in': 'belongs',  # ??
        'is': '='
    }

# Base traverse() function which I derive the rest
# def traverse(o, tree_types=(list, tuple)):
#     if isinstance(o, tree_types):
#         for value in o:
#             for subvalue in traverse(value):
#                 yield subvalue
#     else:
#         yield o

# Here the beast
queries = {}

nested = []

def traverse(o, tree_types=(list, tuple)):
    ops = ('&', '|')
    q = None
    negative = None
    if isinstance(o, tree_types):
        # nested.append('()')
        # if len(o) > 2 and o[1] in ops:
        #     nested.append(o[1])
        if len(o) > 2 and o[1] not in ops:
            print o
            table, field_name = o[0].split('.')
            if table[0] == '~':
                negative = True
                table = table[1:]
            field = db[table][field_name]
            op = ops_translation[' '.join(o[1:-1])]
            value = o[-1]
            if op == '=':
                q = field == value
            elif op == '<':
                q = field < value
            elif op == '>':
                q = field > value
            elif op == '<=':
                q = field <= value
            elif op == '>=':
                q = field >= value
            elif op == '!=':
                q = field != value
            elif op == 'belongs':
                q = field.belongs(value[1:-1].split(','))
            elif op == 'notbelongs':
                q = ~field.belongs(value[1:-1].split(','))
            elif field.type in ('text', 'string', 'json'):
                if op == 'contains':
                    q = field.contains(value)
                elif op == 'like':
                    q = field.ilike(value)
                elif op == 'startswith':
                    q = field.startswith(value)
                elif op == 'endswith':
                    q = field.endswith(value)
                else:
                    raise RuntimeError("Invalid operation")
            queries[tuple(o)] = q
            print q
        for value in o:
            for subvalue in traverse(value):
                yield subvalue
    else:
        yield o

# For invoquing the generator
for e in traverse(list_of_nested_query_string): e  # Notting come out
except print

# Then have a look to queries

I build a dict of tuple query has key to try to replace the sublist in the
"list_of_nested_query_string", but then I need to traverse it again and
build nested query in another traverse derived function... Not clean code...

# Here model definition for testing purpose
db.define_table('a_table',
                Field('string_field', 'string'),
                Field('text_field', 'text'),
                Field('boolean_field', 'boolean'),
                Field('integer_field', 'integer'),
                Field('double_field', 'double'),
                # Field('decimal_field', 'decimal'),
                # Field('date_field', 'date'),
                # Field('time_field', 'time'),
                # Field('datetime_field', 'datetime'),
                # Field('reference_field', 'reference referred_table'),
                # Field('list_string_field', 'list:string'),
                # Field('list_integer_field', 'list:integer'),
                # Field('list_reference_field', 'list:reference
referred_table')
                )

fields = [db.a_table.string_field,
          db.a_table.text_field,
          db.a_table.boolean_field,
          db.a_table.integer_field,
          db.a_table.double_field,
          # db.a_table.decimal_field,
          # db.a_table.date_field,
          # db.a_table.time_field,
          # db.a_table.reference_field,
          # db.a_table.list_string_field,
          # db.a_table.list_integer_field,
          # db.a_table.list_reference_field
          ]

On Thu, May 7, 2015 at 10:37 PM, Richard Vézina <ml.richard.vez...@gmail.com
> wrote:

> Recursive problem... I get closer, but have a lot of difficulty figuring
> out how to assembling the nested queries in the right order and the right
> depth of each query...
>
> I have been so far able to extract a flatten dict of each individually
> nested query and translated them into web2py query...
>
> But as explained above now I bang my head on my desk...
>
> :)
>
> Richard
>
> On Thu, Apr 30, 2015 at 9:46 AM, Richard Vézina <
> ml.richard.vez...@gmail.com> wrote:
>
>> It could work of course, but it hurts to have to do that to just filter
>> out correctly a dropdown menu... What I was doing until now was to have a
>> single returning json_feed which for each dropdown required... But it not
>> try, I need to create almost identical function for each particular
>> dropdown to feed typeahead widget with remote data... I am padding
>> smart_query() with unittest right now before give a try to make it accept
>> "grouped" query...
>>
>> Richard
>>
>> On Thu, Apr 30, 2015 at 7:47 AM, Johann Spies <johann.sp...@gmail.com>
>> wrote:
>>
>>> Will it not be easier to encapsulate your complex query in a database
>>> view and run the grid on the view?
>>>
>>> e.g.  in the controller:
>>> db.execute(create view xx as complexquery)
>>>
>>> db.define_table('xx',
>>>                         Field1(),
>>>                         Field2...
>>>
>>>
>>>
>>> Johann
>>> --
>>> Because experiencing your loyal love is better than life itself,
>>> my lips will praise you.  (Psalm 63:3)
>>>
>>> --
>>> Resources:
>>> - http://web2py.com
>>> - http://web2py.com/book (Documentation)
>>> - http://github.com/web2py/web2py (Source code)
>>> - https://code.google.com/p/web2py/issues/list (Report Issues)
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "web2py-users" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to web2py+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to