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 <[email protected]
> 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 <
> [email protected]> 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 <[email protected]>
>> 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 [email protected].
>>> 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 [email protected].
For more options, visit https://groups.google.com/d/optout.