server/sources/rql2sql.py
branchstable
changeset 5994 97c55baefa0c
parent 5901 782b27eaf97a
child 6003 5fbc1c4c13ff
equal deleted inserted replaced
5976:00b1b6b906cf 5994:97c55baefa0c
   609                 sql += '\nGROUP BY %s' % groups
   609                 sql += '\nGROUP BY %s' % groups
   610             if having:
   610             if having:
   611                 sql += '\nHAVING %s' % having
   611                 sql += '\nHAVING %s' % having
   612             # sort
   612             # sort
   613             if sorts:
   613             if sorts:
   614                 sql += '\nORDER BY %s' % ','.join(self._sortterm_sql(sortterm,
   614                 sqlsortterms = [self._sortterm_sql(sortterm, fselectidx)
   615                                                                      fselectidx)
   615                                 for sortterm in sorts]
   616                                                   for sortterm in sorts)
   616                 sqlsortterms = [x for x in sqlsortterms if x is not None]
   617                 if fneedwrap:
   617                 if sqlsortterms:
   618                     selection = ['T1.C%s' % i for i in xrange(len(origselection))]
   618                     sql += '\nORDER BY %s' % ','.join(sqlsortterms)
   619                     sql = 'SELECT %s FROM (%s) AS T1' % (','.join(selection), sql)
   619                     if sorts and fneedwrap:
       
   620                         selection = ['T1.C%s' % i for i in xrange(len(origselection))]
       
   621                         sql = 'SELECT %s FROM (%s) AS T1' % (','.join(selection), sql)
   620             state.finalize_source_cbs()
   622             state.finalize_source_cbs()
   621         finally:
   623         finally:
   622             select.selection = origselection
   624             select.selection = origselection
   623         # limit / offset
   625         # limit / offset
   624         limit = select.limit
   626         limit = select.limit
   694         return 'SELECT %s' % ', '.join(clause)
   696         return 'SELECT %s' % ', '.join(clause)
   695 
   697 
   696     def _sortterm_sql(self, sortterm, selectidx):
   698     def _sortterm_sql(self, sortterm, selectidx):
   697         term = sortterm.term
   699         term = sortterm.term
   698         try:
   700         try:
   699             sqlterm = str(selectidx.index(str(term)) + 1)
   701             sqlterm = selectidx.index(str(term)) + 1
   700         except ValueError:
   702         except ValueError:
   701             # Constant node or non selected term
   703             # Constant node or non selected term
   702             sqlterm = str(term.accept(self))
   704             sqlterm = term.accept(self)
       
   705             if sqlterm is None:
       
   706                 return None
   703         if sortterm.asc:
   707         if sortterm.asc:
   704             return sqlterm
   708             return str(sqlterm)
   705         else:
   709         else:
   706             return '%s DESC' % sqlterm
   710             return '%s DESC' % sqlterm
   707 
   711 
   708     def visit_and(self, et):
   712     def visit_and(self, et):
   709         """generate SQL for a AND subtree"""
   713         """generate SQL for a AND subtree"""
  1058         if isinstance(rel.parent, Not):
  1062         if isinstance(rel.parent, Not):
  1059             self._state.done.add(rel.parent)
  1063             self._state.done.add(rel.parent)
  1060             not_ = True
  1064             not_ = True
  1061         else:
  1065         else:
  1062             not_ = False
  1066             not_ = False
  1063         return self.dbhelper.fti_restriction_sql(alias, const.eval(self._args),
  1067         query = const.eval(self._args)
       
  1068         return self.dbhelper.fti_restriction_sql(alias, query,
  1064                                                  jointo, not_) + restriction
  1069                                                  jointo, not_) + restriction
  1065 
  1070 
  1066     def visit_comparison(self, cmp):
  1071     def visit_comparison(self, cmp):
  1067         """generate SQL for a comparison"""
  1072         """generate SQL for a comparison"""
  1068         if len(cmp.children) == 2:
  1073         if len(cmp.children) == 2:
  1102             pass
  1107             pass
  1103         return '(%s %s %s)'% (lhs.accept(self), operator, rhs.accept(self))
  1108         return '(%s %s %s)'% (lhs.accept(self), operator, rhs.accept(self))
  1104 
  1109 
  1105     def visit_function(self, func):
  1110     def visit_function(self, func):
  1106         """generate SQL name for a function"""
  1111         """generate SQL name for a function"""
       
  1112         if func.name == 'FTIRANK':
       
  1113             try:
       
  1114                 rel = iter(func.children[0].variable.stinfo['ftirels']).next()
       
  1115             except KeyError:
       
  1116                 raise BadRQLQuery("can't use FTIRANK on variable not used in an"
       
  1117                                   " 'has_text' relation (eg full-text search)")
       
  1118             const = rel.get_parts()[1].children[0]
       
  1119             return self.dbhelper.fti_rank_order(self._fti_table(rel),
       
  1120                                                 const.eval(self._args))
  1107         args = [c.accept(self) for c in func.children]
  1121         args = [c.accept(self) for c in func.children]
  1108         if func in self._state.source_cb_funcs:
  1122         if func in self._state.source_cb_funcs:
  1109             # function executed as a callback on the source
  1123             # function executed as a callback on the source
  1110             assert len(args) == 1
  1124             assert len(args) == 1
  1111             return args[0]
  1125             return args[0]
  1130             _id = constant.value
  1144             _id = constant.value
  1131             if isinstance(_id, unicode):
  1145             if isinstance(_id, unicode):
  1132                 _id = _id.encode()
  1146                 _id = _id.encode()
  1133         else:
  1147         else:
  1134             _id = str(id(constant)).replace('-', '', 1)
  1148             _id = str(id(constant)).replace('-', '', 1)
  1135             if isinstance(value, unicode):
       
  1136                 value = value.encode(self.dbencoding)
       
  1137             self._query_attrs[_id] = value
  1149             self._query_attrs[_id] = value
  1138         return '%%(%s)s' % _id
  1150         return '%%(%s)s' % _id
  1139 
  1151 
  1140     def visit_variableref(self, variableref):
  1152     def visit_variableref(self, variableref):
  1141         """get the sql name for a variable reference"""
  1153         """get the sql name for a variable reference"""