server/sources/rql2sql.py
changeset 1251 af40e615dc89
parent 1124 5548b608b7d9
child 1263 01152fffd593
child 1382 618f6aee8d52
equal deleted inserted replaced
1250:5c20a7f13c84 1251:af40e615dc89
    36 from rql.stmts import Union, Select
    36 from rql.stmts import Union, Select
    37 from rql.nodes import (SortTerm, VariableRef, Constant, Function, Not,
    37 from rql.nodes import (SortTerm, VariableRef, Constant, Function, Not,
    38                        Variable, ColumnAlias, Relation, SubQuery, Exists)
    38                        Variable, ColumnAlias, Relation, SubQuery, Exists)
    39 
    39 
    40 from cubicweb import server
    40 from cubicweb import server
       
    41 from cubicweb.server.sqlutils import SQL_PREFIX
    41 from cubicweb.server.utils import cleanup_solutions
    42 from cubicweb.server.utils import cleanup_solutions
    42 
    43 
    43 def _new_var(select, varname): 
    44 def _new_var(select, varname): 
    44     newvar = select.get_variable(varname)
    45     newvar = select.get_variable(varname)
    45     if not 'relations' in newvar.stinfo:
    46     if not 'relations' in newvar.stinfo:
   763             # reset lhs/rhs, we need the initial order now
   764             # reset lhs/rhs, we need the initial order now
   764             lhs, rhs = relation.get_variable_parts()
   765             lhs, rhs = relation.get_variable_parts()
   765             if '%s.%s' % (lhs.name, attr) in self._varmap:
   766             if '%s.%s' % (lhs.name, attr) in self._varmap:
   766                 lhssql = self._varmap['%s.%s' % (lhs.name, attr)]
   767                 lhssql = self._varmap['%s.%s' % (lhs.name, attr)]
   767             else:
   768             else:
   768                 lhssql = '%s.%s' % (self._var_table(lhs.variable), attr)
   769                 lhssql = '%s.%s%s' % (self._var_table(lhs.variable), SQL_PREFIX, attr)
   769             if not rhsvar is None:
   770             if not rhsvar is None:
   770                 t2 = self._var_table(rhsvar)
   771                 t2 = self._var_table(rhsvar)
   771                 if t2 is None:
   772                 if t2 is None:
   772                     if rhsconst is not None:
   773                     if rhsconst is not None:
   773                         # inlined relation with invariant as rhs
   774                         # inlined relation with invariant as rhs
   804         if not rhsconst:
   805         if not rhsconst:
   805             rhstable = rhsvar._q_sqltable
   806             rhstable = rhsvar._q_sqltable
   806             if rhstable:
   807             if rhstable:
   807                 assert rhstable is not None, rhsvar
   808                 assert rhstable is not None, rhsvar
   808                 join += ' %s OUTER JOIN %s ON (%s.%s=%s)' % (
   809                 join += ' %s OUTER JOIN %s ON (%s.%s=%s)' % (
   809                     outertype, self._state.tables[rhstable][1], rid, restrattr, rhssql)
   810                     outertype, self._state.tables[rhstable][1], rid, restrattr,
       
   811                     rhssql)
   810                 toreplace.append(rhstable)
   812                 toreplace.append(rhstable)
   811         self.replace_tables_by_outer_join(join, maintable, *toreplace)
   813         self.replace_tables_by_outer_join(join, maintable, *toreplace)
   812         return ''
   814         return ''
   813 
   815 
   814     def _visit_var_attr_relation(self, relation, rhs_vars):
   816     def _visit_var_attr_relation(self, relation, rhs_vars):
   844             lhssql = lhs.accept(self)
   846             lhssql = lhs.accept(self)
   845         else:
   847         else:
   846             try:
   848             try:
   847                 lhssql = self._varmap['%s.%s' % (lhs.name, relation.r_type)]
   849                 lhssql = self._varmap['%s.%s' % (lhs.name, relation.r_type)]
   848             except KeyError:
   850             except KeyError:
   849                 lhssql = '%s.%s' % (table, relation.r_type)
   851                 if relation.r_type == 'eid':
       
   852                     lhssql = lhs.variable._q_sql
       
   853                 else:
       
   854                     lhssql = '%s.%s%s' % (table, SQL_PREFIX, relation.r_type)
   850         try:
   855         try:
   851             if relation._q_needcast == 'TODAY':
   856             if relation._q_needcast == 'TODAY':
   852                 sql = 'DATE(%s)%s' % (lhssql, rhssql)
   857                 sql = 'DATE(%s)%s' % (lhssql, rhssql)
   853             # XXX which cast function should be used
   858             # XXX which cast function should be used
   854             #elif relation._q_needcast == 'NOW':
   859             #elif relation._q_needcast == 'NOW':
   991         elif variable._q_invariant:
   996         elif variable._q_invariant:
   992             # since variable is invariant, we know we won't found final relation
   997             # since variable is invariant, we know we won't found final relation
   993             principal = variable.stinfo['principal']
   998             principal = variable.stinfo['principal']
   994             if principal is None:
   999             if principal is None:
   995                 vtablename = variable.name
  1000                 vtablename = variable.name
   996                 self.add_table('entities AS %s' % variable.name, vtablename)
  1001                 self.add_table('entities AS %s' % vtablename, vtablename)
   997                 sql = '%s.eid' % vtablename
  1002                 sql = '%s.eid' % vtablename
   998                 if variable.stinfo['typerels']:
  1003                 if variable.stinfo['typerels']:
   999                     # add additional restriction on entities.type column
  1004                     # add additional restriction on entities.type column
  1000                     pts = variable.stinfo['possibletypes']
  1005                     pts = variable.stinfo['possibletypes']
  1001                     if len(pts) == 1:
  1006                     if len(pts) == 1:
  1056             etype = self._state.solution[var.name]
  1061             etype = self._state.solution[var.name]
  1057             # XXX this check should be moved in rql.stcheck
  1062             # XXX this check should be moved in rql.stcheck
  1058             if self.schema.eschema(etype).is_final():
  1063             if self.schema.eschema(etype).is_final():
  1059                 raise BadRQLQuery(var.stmt.root)
  1064                 raise BadRQLQuery(var.stmt.root)
  1060             table = var.name
  1065             table = var.name
  1061             sql = '%s.eid' % table
  1066             sql = '%s.%seid' % (table, SQL_PREFIX)
  1062             self.add_table('%s AS %s' % (etype, table), table, scope=scope)
  1067             self.add_table('%s%s AS %s' % (SQL_PREFIX, etype, table), table, scope=scope)
  1063         return sql, table
  1068         return sql, table
  1064     
  1069     
  1065     def _inlined_var_sql(self, var, rtype):
  1070     def _inlined_var_sql(self, var, rtype):
  1066         try:
  1071         try:
  1067             sql = self._varmap['%s.%s' % (var.name, rtype)]
  1072             sql = self._varmap['%s.%s' % (var.name, rtype)]
  1068             scope = var.sqlscope is var.stmt and 0 or -1
  1073             scope = var.sqlscope is var.stmt and 0 or -1
  1069             self.add_table(sql.split('.', 1)[0], scope=scope)
  1074             self.add_table(sql.split('.', 1)[0], scope=scope)
  1070         except KeyError:
  1075         except KeyError:
  1071             sql = '%s.%s' % (self._var_table(var), rtype)
  1076             sql = '%s.%s%s' % (self._var_table(var), SQL_PREFIX, rtype)
  1072             #self._state.done.add(var.name)
  1077             #self._state.done.add(var.name)
  1073         return sql
  1078         return sql
  1074         
  1079         
  1075     def _linked_var_sql(self, variable, contextrels=None):
  1080     def _linked_var_sql(self, variable, contextrels=None):
  1076         if contextrels is None:
  1081         if contextrels is None:
  1089                               % variable.name)
  1094                               % variable.name)
  1090         try:
  1095         try:
  1091             sql = self._varmap['%s.%s' % (linkedvar.name, rel.r_type)]
  1096             sql = self._varmap['%s.%s' % (linkedvar.name, rel.r_type)]
  1092         except KeyError:
  1097         except KeyError:
  1093             linkedvar.accept(self)            
  1098             linkedvar.accept(self)            
  1094             sql = '%s.%s' % (linkedvar._q_sqltable, rel.r_type)
  1099             sql = '%s.%s%s' % (linkedvar._q_sqltable, SQL_PREFIX, rel.r_type)
  1095         return sql
  1100         return sql
  1096 
  1101 
  1097     # tables handling #########################################################
  1102     # tables handling #########################################################
  1098 
  1103 
  1099     def alias_and_add_table(self, tablename):
  1104     def alias_and_add_table(self, tablename):