server/rqlannotation.py
changeset 599 9ef680acd92a
parent 438 69b79faefa94
child 967 aeeec5447eb0
equal deleted inserted replaced
598:4705ceb624cc 599:9ef680acd92a
   144 
   144 
   145 
   145 
   146 
   146 
   147 class CantSelectPrincipal(Exception): pass
   147 class CantSelectPrincipal(Exception): pass
   148 
   148 
   149 def _select_principal(sqlscope, relations):
   149 def _select_principal(sqlscope, relations, _sort=lambda x:x):
   150     """given a list of rqlst relations, select one which will be used to
   150     """given a list of rqlst relations, select one which will be used to
   151     represent an invariant variable (e.g. using on extremity of the relation
   151     represent an invariant variable (e.g. using on extremity of the relation
   152     instead of the variable's type table
   152     instead of the variable's type table
   153     """
   153     """
       
   154     # _sort argument is there for test
   154     diffscope_rels = {}
   155     diffscope_rels = {}
   155     has_same_scope_rel = False
   156     has_same_scope_rel = False
   156     ored_rels = set()
   157     ored_rels = set()
   157     diffscope_rels = set()
   158     diffscope_rels = set()
   158     for rel in relations:
   159     for rel in _sort(relations):
   159         # note: only eid and has_text among all final relations may be there
   160         # note: only eid and has_text among all final relations may be there
   160         if rel.r_type in ('eid', 'identity'):
   161         if rel.r_type in ('eid', 'identity'):
   161             has_same_scope_rel = rel.sqlscope is sqlscope
   162             has_same_scope_rel = rel.sqlscope is sqlscope
   162             continue
   163             continue
   163         if rel.ored(traverse_scope=True):
   164         if rel.ored(traverse_scope=True):
   173                 if rel1 is rel2:
   174                 if rel1 is rel2:
   174                     continue
   175                     continue
   175                 if isinstance(common_parent(rel1, rel2), Or):
   176                 if isinstance(common_parent(rel1, rel2), Or):
   176                     ored_rels.discard(rel1)
   177                     ored_rels.discard(rel1)
   177                     ored_rels.discard(rel2)
   178                     ored_rels.discard(rel2)
   178     for rel in ored_rels:
   179     for rel in _sort(ored_rels):
   179         if rel.sqlscope is sqlscope:
   180         if rel.sqlscope is sqlscope:
   180             return rel
   181             return rel
   181         diffscope_rels.add(rel)
   182         diffscope_rels.add(rel)
   182     # if DISTINCT query, can use variable from a different scope as principal
   183     # if DISTINCT query, can use variable from a different scope as principal
   183     # since introduced duplicates will be removed
   184     # since introduced duplicates will be removed
   184     if sqlscope.stmt.distinct and diffscope_rels:
   185     if sqlscope.stmt.distinct and diffscope_rels:
   185         return iter(diffscope_rels).next()
   186         return iter(_sort(diffscope_rels)).next()
   186     # XXX  could use a relation for a different scope if it can't generate
   187     # XXX  could use a relation for a different scope if it can't generate
   187     # duplicates, so we would have to check cardinality
   188     # duplicates, so we would have to check cardinality
   188     raise CantSelectPrincipal()
   189     raise CantSelectPrincipal()    
   189     
       
   190 
   190 
   191 def _select_main_var(relations):
   191 def _select_main_var(relations):
   192     """given a list of rqlst relations, select one which will be used as main
   192     """given a list of rqlst relations, select one which will be used as main
   193     relation for the rhs variable
   193     relation for the rhs variable
   194     """
   194     """