server/rqlannotation.py
branchtls-sprint
changeset 1802 d628defebc17
parent 1132 96752791c2b6
child 1977 606923dff11b
equal deleted inserted replaced
1801:672acc730ce5 1802:d628defebc17
    67             continue
    67             continue
    68         if stinfo['selected'] and var.valuable_references() == 1+bool(stinfo['constnode']):
    68         if stinfo['selected'] and var.valuable_references() == 1+bool(stinfo['constnode']):
    69             # "Any X", "Any X, Y WHERE X attr Y"
    69             # "Any X", "Any X, Y WHERE X attr Y"
    70             stinfo['invariant'] = False
    70             stinfo['invariant'] = False
    71             continue
    71             continue
    72         joins = set()            
    72         joins = set()
    73         invariant = False
    73         invariant = False
    74         for ref in var.references():
    74         for ref in var.references():
    75             rel = ref.relation()
    75             rel = ref.relation()
    76             if rel is None or rel.is_types_restriction():
    76             if rel is None or rel.is_types_restriction():
    77                 continue
    77                 continue
    78             lhs, rhs = rel.get_parts()
    78             lhs, rhs = rel.get_parts()
    79             onlhs = ref is lhs
    79             onlhs = ref is lhs
    80             if rel.r_type == 'eid':
    80             if rel.r_type == 'eid':
    81                 if not (onlhs and len(stinfo['relations']) > 1): 
    81                 if not (onlhs and len(stinfo['relations']) > 1):
    82                     break
    82                     break
    83                 if not stinfo['constnode']:
    83                 if not stinfo['constnode']:
    84                     joins.add(rel)
    84                     joins.add(rel)
    85                 continue
    85                 continue
    86             elif rel.r_type == 'identity':
    86             elif rel.r_type == 'identity':
   108                     break
   108                     break
   109                 joins.add(rel)
   109                 joins.add(rel)
   110                 continue
   110                 continue
   111             if not stinfo['constnode']:
   111             if not stinfo['constnode']:
   112                 if rschema.inlined and rel.neged(strict=True):
   112                 if rschema.inlined and rel.neged(strict=True):
   113                     # if relation is inlined, can't be invariant if that 
   113                     # if relation is inlined, can't be invariant if that
   114                     # variable is used anywhere else.
   114                     # variable is used anywhere else.
   115                     # see 'Any P WHERE NOT N ecrit_par P, N eid 512':                    
   115                     # see 'Any P WHERE NOT N ecrit_par P, N eid 512':
   116                     # sql for 'NOT N ecrit_par P' is 'N.ecrit_par is NULL' so P
   116                     # sql for 'NOT N ecrit_par P' is 'N.ecrit_par is NULL' so P
   117                     # can use N.ecrit_par as principal
   117                     # can use N.ecrit_par as principal
   118                     if (stinfo['selected'] or len(stinfo['relations']) > 1):
   118                     if (stinfo['selected'] or len(stinfo['relations']) > 1):
   119                         break
   119                         break
   120                 elif rschema.symetric and stinfo['selected']:
   120                 elif rschema.symetric and stinfo['selected']:
   182     # since introduced duplicates will be removed
   182     # since introduced duplicates will be removed
   183     if sqlscope.stmt.distinct and diffscope_rels:
   183     if sqlscope.stmt.distinct and diffscope_rels:
   184         return iter(_sort(diffscope_rels)).next()
   184         return iter(_sort(diffscope_rels)).next()
   185     # XXX  could use a relation for a different scope if it can't generate
   185     # XXX  could use a relation for a different scope if it can't generate
   186     # duplicates, so we would have to check cardinality
   186     # duplicates, so we would have to check cardinality
   187     raise CantSelectPrincipal()    
   187     raise CantSelectPrincipal()
   188 
   188 
   189 def _select_main_var(relations):
   189 def _select_main_var(relations):
   190     """given a list of rqlst relations, select one which will be used as main
   190     """given a list of rqlst relations, select one which will be used as main
   191     relation for the rhs variable
   191     relation for the rhs variable
   192     """
   192     """
   263         if len([rel for rel in var.stinfo['relations']
   263         if len([rel for rel in var.stinfo['relations']
   264                 if rel.sqlscope is var.sqlscope and rel.r_type == 'has_text']) == 1:
   264                 if rel.sqlscope is var.sqlscope and rel.r_type == 'has_text']) == 1:
   265             return False
   265             return False
   266         try:
   266         try:
   267             data = var.stmt._deamb_data
   267             data = var.stmt._deamb_data
   268         except AttributeError: 
   268         except AttributeError:
   269             data = var.stmt._deamb_data = IsAmbData(self.schema, self.nfdomain)
   269             data = var.stmt._deamb_data = IsAmbData(self.schema, self.nfdomain)
   270             data.compute(var.stmt)
   270             data.compute(var.stmt)
   271         return data.is_ambiguous(var)
   271         return data.is_ambiguous(var)
   272 
   272 
   273         
   273 
   274 class IsAmbData(object):
   274 class IsAmbData(object):
   275     def __init__(self, schema, nfdomain):
   275     def __init__(self, schema, nfdomain):
   276         self.schema = schema
   276         self.schema = schema
   277         # shortcuts
   277         # shortcuts
   278         self.rschema = schema.rschema
   278         self.rschema = schema.rschema
   286         # remember if a variable has been deambiguified by another to avoid
   286         # remember if a variable has been deambiguified by another to avoid
   287         # doing the opposite
   287         # doing the opposite
   288         self.deambification_map = {}
   288         self.deambification_map = {}
   289         # not invariant variables (access to final.inlined relation)
   289         # not invariant variables (access to final.inlined relation)
   290         self.not_invariants = set()
   290         self.not_invariants = set()
   291         
   291 
   292     def is_ambiguous(self, var):
   292     def is_ambiguous(self, var):
   293         return var in self.ambiguousvars
   293         return var in self.ambiguousvars
   294 
   294 
   295     def restrict(self, var, restricted_domain):
   295     def restrict(self, var, restricted_domain):
   296         self.varsols[var] &= restricted_domain
   296         self.varsols[var] &= restricted_domain
   297         if var in self.ambiguousvars and self.varsols[var] == var.stinfo['possibletypes']:
   297         if var in self.ambiguousvars and self.varsols[var] == var.stinfo['possibletypes']:
   298             self.ambiguousvars.remove(var)
   298             self.ambiguousvars.remove(var)
   299     
   299 
   300     def compute(self, rqlst):
   300     def compute(self, rqlst):
   301         # set domains for each variable
   301         # set domains for each variable
   302         for varname, var in rqlst.defined_vars.iteritems():
   302         for varname, var in rqlst.defined_vars.iteritems():
   303             if var.stinfo['uidrels'] or \
   303             if var.stinfo['uidrels'] or \
   304                    self.eschema(rqlst.solutions[0][varname]).is_final():
   304                    self.eschema(rqlst.solutions[0][varname]).is_final():
   332                             modified = True
   332                             modified = True
   333                             break
   333                             break
   334                 except KeyError:
   334                 except KeyError:
   335                     # no relation to deambiguify
   335                     # no relation to deambiguify
   336                     continue
   336                     continue
   337         
   337 
   338     def _debug_print(self):
   338     def _debug_print(self):
   339         print 'varsols', dict((x, sorted(str(v) for v in values))
   339         print 'varsols', dict((x, sorted(str(v) for v in values))
   340                                for x, values in self.varsols.iteritems())
   340                                for x, values in self.varsols.iteritems())
   341         print 'ambiguous vars', sorted(self.ambiguousvars)
   341         print 'ambiguous vars', sorted(self.ambiguousvars)
   342 
   342 
   348                 self.restrict(var, frozenset(etypes_func()))
   348                 self.restrict(var, frozenset(etypes_func()))
   349                 try:
   349                 try:
   350                     self.maydeambrels[var].add(rel)
   350                     self.maydeambrels[var].add(rel)
   351                 except KeyError:
   351                 except KeyError:
   352                     self.maydeambrels[var] = set((rel,))
   352                     self.maydeambrels[var] = set((rel,))
   353         
   353 
   354     def deambiguifying_relation(self, var, rel):
   354     def deambiguifying_relation(self, var, rel):
   355         lhs, rhs = rel.get_variable_parts()
   355         lhs, rhs = rel.get_variable_parts()
   356         onlhs = var is getattr(lhs, 'variable', None)
   356         onlhs = var is getattr(lhs, 'variable', None)
   357         other = onlhs and rhs or lhs
   357         other = onlhs and rhs or lhs
   358         otheretypes = None
   358         otheretypes = None