server/rqlannotation.py
changeset 438 69b79faefa94
parent 340 bfe0e95571aa
child 599 9ef680acd92a
equal deleted inserted replaced
437:5d8dc9678707 438:69b79faefa94
    18     for subquery in rqlst.with_:
    18     for subquery in rqlst.with_:
    19         annotator._annotate_union(subquery.query)
    19         annotator._annotate_union(subquery.query)
    20     #if server.DEBUG:
    20     #if server.DEBUG:
    21     #    print '-------- sql annotate', repr(rqlst)
    21     #    print '-------- sql annotate', repr(rqlst)
    22     getrschema = annotator.schema.rschema
    22     getrschema = annotator.schema.rschema
    23     has_text_query = need_intersect = False
    23     has_text_query = False
    24     need_distinct = rqlst.distinct
    24     need_distinct = rqlst.distinct
    25     for rel in rqlst.iget_nodes(Relation):
    25     for rel in rqlst.iget_nodes(Relation):
    26         if rel.neged(strict=True):
    26         if rel.neged(strict=True):
    27             if rel.is_types_restriction():
    27             if rel.is_types_restriction():
    28                 need_distinct = True
    28                 need_distinct = True
    29             else:
    29             else:
    30                 rschema = getrschema(rel.r_type)
    30                 rschema = getrschema(rel.r_type)
    31                 if not rschema.is_final():
    31                 if not rschema.is_final():
    32                     # if one of the relation's variable is ambiguous, an intersection
       
    33                     # will be necessary
       
    34                     for vref in rel.get_nodes(VariableRef):
       
    35                         var = vref.variable
       
    36                         if not var.stinfo['selected'] and len(var.stinfo['possibletypes']) > 1:
       
    37                             need_intersect = True
       
    38                             break
       
    39                     if rschema.inlined:
    32                     if rschema.inlined:
    40                         try:
    33                         try:
    41                             var = rel.children[1].children[0].variable
    34                             var = rel.children[1].children[0].variable
    42                         except AttributeError:
    35                         except AttributeError:
    43                             pass # rewritten variable
    36                             pass # rewritten variable
   145             try:
   138             try:
   146                 stinfo['principal'] = _select_principal(var.sqlscope, joins)
   139                 stinfo['principal'] = _select_principal(var.sqlscope, joins)
   147             except CantSelectPrincipal:
   140             except CantSelectPrincipal:
   148                 stinfo['invariant'] = False
   141                 stinfo['invariant'] = False
   149     rqlst.need_distinct = need_distinct
   142     rqlst.need_distinct = need_distinct
   150     rqlst.need_intersect = need_intersect
       
   151     return has_text_query
   143     return has_text_query
   152 
   144 
   153 
   145 
   154 
   146 
   155 class CantSelectPrincipal(Exception): pass
   147 class CantSelectPrincipal(Exception): pass
   205             return rel
   197             return rel
   206         principal = rel
   198         principal = rel
   207     return principal
   199     return principal
   208 
   200 
   209 
   201 
   210 def set_qdata(union, noinvariant):
   202 def set_qdata(getrschema, union, noinvariant):
   211     """recursive function to set querier data on variables in the syntax tree
   203     """recursive function to set querier data on variables in the syntax tree
   212     """
   204     """
   213     for select in union.children:
   205     for select in union.children:
   214         for subquery in select.with_:
   206         for subquery in select.with_:
   215             set_qdata(subquery.query, noinvariant)
   207             set_qdata(getrschema, subquery.query, noinvariant)
   216         for var in select.defined_vars.itervalues():
   208         for var in select.defined_vars.itervalues():
   217             if var.stinfo['invariant']:
   209             if var.stinfo['invariant']:
   218                 if var in noinvariant and not var.stinfo['principal'].r_type == 'has_text':
   210                 if var in noinvariant and not var.stinfo['principal'].r_type == 'has_text':
   219                     var._q_invariant = False
   211                     var._q_invariant = False
   220                 else:
   212                 else:
   221                     var._q_invariant = True
   213                     var._q_invariant = True
   222             else:
   214             else:
   223                 var._q_invariant = False
   215                 var._q_invariant = False
       
   216         for rel in select.iget_nodes(Relation):
       
   217             if rel.neged(strict=True) and not rel.is_types_restriction():
       
   218                 rschema = getrschema(rel.r_type)
       
   219                 if not rschema.is_final():
       
   220                     # if one of the relation's variable is ambiguous but not
       
   221                     # invariant, an intersection will be necessary
       
   222                     for vref in rel.get_nodes(VariableRef):
       
   223                         var = vref.variable
       
   224                         if (not var._q_invariant and var.valuable_references() == 1
       
   225                             and len(var.stinfo['possibletypes']) > 1):
       
   226                             select.need_intersect = True
       
   227                             break
       
   228                     else:
       
   229                         continue
       
   230                     break
       
   231         else:
       
   232             select.need_intersect = False
   224 
   233 
   225 
   234 
   226 class SQLGenAnnotator(object):
   235 class SQLGenAnnotator(object):
   227     def __init__(self, schema):
   236     def __init__(self, schema):
   228         self.schema = schema
   237         self.schema = schema