# HG changeset patch # User Sylvain Thénault # Date 1479737852 -3600 # Node ID e6cdc4d3add5ff1d0e8d18e3512256222cffda6d # Parent 056de1196ef80727736803cb11cb635da58309c6 [rqlrewrite] Test and fix potential NameError We were referencing a loop variable, which may lead to a name error and show a potential error if there are several matching variables. To avoid this, introduce a list to hold every encountered variable and process all of them later. diff -r 056de1196ef8 -r e6cdc4d3add5 cubicweb/rqlrewrite.py --- a/cubicweb/rqlrewrite.py Wed Nov 16 15:55:35 2016 +0100 +++ b/cubicweb/rqlrewrite.py Mon Nov 21 15:17:32 2016 +0100 @@ -580,6 +580,7 @@ done.add(rel) rschema = get_rschema(rel.r_type) if rschema.final or rschema.inlined: + subselect_vrefs = [] rel.children[0].name = varname # XXX explain why subselect.add_restriction(rel.copy(subselect)) for vref in rel.children[1].iget_nodes(n.VariableRef): @@ -592,6 +593,7 @@ "least uninline %s" % rel.r_type) subselect.append_selected(vref.copy(subselect)) aliases.append(vref.name) + subselect_vrefs.append(vref) self.select.remove_node(rel) # when some inlined relation has to be copied in the # subquery and that relation is optional, we need to @@ -602,14 +604,15 @@ # also, if some attributes or inlined relation of the # object variable are accessed, we need to get all those # from the subquery as well - if vref.name not in done and rschema.inlined: - # we can use vref here define in above for loop - ostinfo = vref.variable.stinfo - for orel in iter_relations(ostinfo): - orschema = get_rschema(orel.r_type) - if orschema.final or orschema.inlined: - todo.append( (vref.name, ostinfo) ) - break + for vref in subselect_vrefs: + if vref.name not in done and rschema.inlined: + # we can use vref here define in above for loop + ostinfo = vref.variable.stinfo + for orel in iter_relations(ostinfo): + orschema = get_rschema(orel.r_type) + if orschema.final or orschema.inlined: + todo.append( (vref.name, ostinfo) ) + break if need_null_test: snippetrqlst = n.Or( n.make_relation(subselect.get_variable(selectvar), 'is', diff -r 056de1196ef8 -r e6cdc4d3add5 cubicweb/test/unittest_rqlrewrite.py --- a/cubicweb/test/unittest_rqlrewrite.py Wed Nov 16 15:55:35 2016 +0100 +++ b/cubicweb/test/unittest_rqlrewrite.py Mon Nov 21 15:17:32 2016 +0100 @@ -215,6 +215,12 @@ self.assertEqual(rqlst.as_string(), u'Any A,AR,X,CD WHERE A concerne X?, A ref AR, A eid %(a)s WITH X,CD BEING (Any X,CD WHERE X creation_date CD, EXISTS(X created_by B), B eid %(A)s, X is IN(Division, Note, Societe))') + def test_ambiguous_optional_same_exprs_constant(self): + rqlst = parse(u'Any A,AR,X WHERE A concerne X?, A ref AR, A eid %(a)s, X creation_date TODAY') + rewrite(rqlst, {('X', 'X'): ('X created_by U',),}, {'a': 3}) + self.assertEqual(rqlst.as_string(), + u'Any A,AR,X WHERE A concerne X?, A ref AR, A eid %(a)s WITH X BEING (Any X WHERE X creation_date TODAY, EXISTS(X created_by B), B eid %(A)s, X is IN(Division, Note, Societe))') + def test_optional_var_inlined(self): c1 = ('X require_permission P') c2 = ('X inlined_card O, O require_permission P')