server/sources/rql2sql.py
branchstable
changeset 3315 59220b704562
parent 3245 7ef021ac8dec
child 3689 deb13e88e037
equal deleted inserted replaced
3298:caef98aa4a98 3315:59220b704562
   334         self._lock.acquire()
   334         self._lock.acquire()
   335         self._args = args
   335         self._args = args
   336         self._varmap = varmap
   336         self._varmap = varmap
   337         self._query_attrs = {}
   337         self._query_attrs = {}
   338         self._state = None
   338         self._state = None
       
   339         self._not_scope_offset = 0
   339         try:
   340         try:
   340             # union query for each rqlst / solution
   341             # union query for each rqlst / solution
   341             sql = self.union_sql(union)
   342             sql = self.union_sql(union)
   342             # we are done
   343             # we are done
   343             return sql, self._query_attrs
   344             return sql, self._query_attrs
   551             return res[0]
   552             return res[0]
   552         return ''
   553         return ''
   553 
   554 
   554     def visit_not(self, node):
   555     def visit_not(self, node):
   555         self._state.push_scope()
   556         self._state.push_scope()
       
   557         if isinstance(node.children[0], Relation):
       
   558             self._not_scope_offset += 1
   556         csql = node.children[0].accept(self)
   559         csql = node.children[0].accept(self)
       
   560         if isinstance(node.children[0], Relation):
       
   561             self._not_scope_offset -= 1
   557         sqls, tables = self._state.pop_scope()
   562         sqls, tables = self._state.pop_scope()
   558         if node in self._state.done or not csql:
   563         if node in self._state.done or not csql:
   559             # already processed or no sql generated by children
   564             # already processed or no sql generated by children
   560             self._state.actual_tables[-1] += tables
   565             self._state.actual_tables[-1] += tables
   561             self._state.restrictions += sqls
   566             self._state.restrictions += sqls
   649                     return
   654                     return
   650                 # OPTIONAL relation, generate a left|right outer join
   655                 # OPTIONAL relation, generate a left|right outer join
   651                 sql = self._visit_outer_join_relation(relation, rschema)
   656                 sql = self._visit_outer_join_relation(relation, rschema)
   652             elif rschema.inlined:
   657             elif rschema.inlined:
   653                 sql = self._visit_inlined_relation(relation)
   658                 sql = self._visit_inlined_relation(relation)
   654 #             elif isinstance(relation.parent, Not):
       
   655 #                 self._state.done.add(relation.parent)
       
   656 #                 # NOT relation
       
   657 #                 sql = self._visit_not_relation(relation, rschema)
       
   658             else:
   659             else:
   659                 # regular (non final) relation
   660                 # regular (non final) relation
   660                 sql = self._visit_relation(relation, rschema)
   661                 sql = self._visit_relation(relation, rschema)
   661         return sql
   662         return sql
   662 
   663 
  1078         # if current var or one of its attribute is selected , it *must*
  1079         # if current var or one of its attribute is selected , it *must*
  1079         # appear in the toplevel's FROM even if we're currently visiting
  1080         # appear in the toplevel's FROM even if we're currently visiting
  1080         # a EXISTS node
  1081         # a EXISTS node
  1081         if var.sqlscope is var.stmt:
  1082         if var.sqlscope is var.stmt:
  1082             scope = 0
  1083             scope = 0
       
  1084         # don't consider not_scope_offset if the variable is only used in one
       
  1085         # relation
       
  1086         elif len(var.stinfo['relations']) > 1:
       
  1087             scope = -1 - self._not_scope_offset
  1083         else:
  1088         else:
  1084             scope = -1
  1089             scope = -1
  1085         try:
  1090         try:
  1086             sql = self._varmap[var.name]
  1091             sql = self._varmap[var.name]
  1087             table = sql.split('.', 1)[0]
  1092             table = sql.split('.', 1)[0]
  1088             if scope == -1:
  1093             if scope < 0:
  1089                 scope = self._varmap_table_scope(var.stmt, table)
  1094                 scope = self._varmap_table_scope(var.stmt, table)
  1090             self.add_table(table, scope=scope)
  1095             self.add_table(table, scope=scope)
  1091         except KeyError:
  1096         except KeyError:
  1092             etype = self._state.solution[var.name]
  1097             etype = self._state.solution[var.name]
  1093             # XXX this check should be moved in rql.stcheck
  1098             # XXX this check should be moved in rql.stcheck
  1094             if self.schema.eschema(etype).is_final():
  1099             if self.schema.eschema(etype).is_final():
  1095                 raise BadRQLQuery(var.stmt.root)
  1100                 raise BadRQLQuery(var.stmt.root)
  1096             table = var.name
  1101             table = var.name
  1097             sql = '%s.%seid' % (table, SQL_PREFIX)
  1102             sql = '%s.%seid' % (table, SQL_PREFIX)
  1098             self.add_table('%s%s AS %s' % (SQL_PREFIX, etype, table), table, scope=scope)
  1103             self.add_table('%s%s AS %s' % (SQL_PREFIX, etype, table), table,
       
  1104                            scope=scope)
  1099         return sql, table
  1105         return sql, table
  1100 
  1106 
  1101     def _inlined_var_sql(self, var, rtype):
  1107     def _inlined_var_sql(self, var, rtype):
  1102         try:
  1108         try:
  1103             sql = self._varmap['%s.%s' % (var.name, rtype)]
  1109             sql = self._varmap['%s.%s' % (var.name, rtype)]
  1144     def add_table(self, table, key=None, scope=-1):
  1150     def add_table(self, table, key=None, scope=-1):
  1145         if key is None:
  1151         if key is None:
  1146             key = table
  1152             key = table
  1147         if key in self._state.tables:
  1153         if key in self._state.tables:
  1148             return
  1154             return
  1149         if scope == -1:
  1155         if scope < 0:
  1150             scope = len(self._state.actual_tables) - 1
  1156             scope = len(self._state.actual_tables) + scope
  1151         self._state.tables[key] = (scope, table)
  1157         self._state.tables[key] = (scope, table)
  1152         self._state.actual_tables[scope].append(table)
  1158         self._state.actual_tables[scope].append(table)
  1153 
  1159 
  1154     def replace_tables_by_outer_join(self, substitute, lefttable, *tables):
  1160     def replace_tables_by_outer_join(self, substitute, lefttable, *tables):
  1155         for table in tables:
  1161         for table in tables: