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): |