rqlrewrite.py
branchstable
changeset 9169 544b22a3485b
parent 9167 c05652b108ce
child 9170 e6fe77dbcfdf
--- a/rqlrewrite.py	Mon Jul 22 14:26:33 2013 +0200
+++ b/rqlrewrite.py	Thu Jul 18 10:19:06 2013 +0200
@@ -162,6 +162,17 @@
                 aliases.append(n.VariableRef(colalias))
                 selected.add(vref.name)
 
+def _has_multiple_cardinality(etypes, rdef, ttypes_func, cardindex):
+    """return True if relation definitions from entity types (`etypes`) to
+    target types returned by the `ttypes_func` function all have single (1 or ?)
+    cardinality.
+    """
+    for etype in etypes:
+        for ttype in ttypes_func(etype):
+            if rdef(etype, ttype).cardinality[cardindex] in '+*':
+                return True
+    return False
+
 
 def iter_relations(stinfo):
     # this is a function so that test may return relation in a predictable order
@@ -661,21 +672,22 @@
                     rdef = lambda x, y: rschema.rdef(y, x)
             except KeyError:
                 # may be raised by vi['xhs_rels'][sniprel.r_type]
-                return None
+                continue
             # don't share if relation's statement is not the current statement
             if orel.stmt is not stmt:
                 return None
             # can't share neged relation or relations with different outer join
             if (orel.neged(strict=True) or sniprel.neged(strict=True)
                 or (orel.optional and orel.optional != sniprel.optional)):
-                return None
+                continue
             # if cardinality is in '?1', we can ignore the snippet relation and use
             # variable from the original query
-            for etype in vi['stinfo']['possibletypes']:
-                for ttype in ttypes_func(etype):
-                    if rdef(etype, ttype).cardinality[cardindex] in '+*':
-                        return None
+            if _has_multiple_cardinality(vi['stinfo']['possibletypes'], rdef,
+                                         ttypes_func, cardindex):
+                continue
             break
+        else:
+            return None
         return orel
 
     def _use_orig_term(self, snippet_varname, term):