compiler.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from django.db.models.sql import compiler
  2. from django.utils.six.moves import zip_longest
  3. class SQLCompiler(compiler.SQLCompiler):
  4. def resolve_columns(self, row, fields=()):
  5. # If this query has limit/offset information, then we expect the
  6. # first column to be an extra "_RN" column that we need to throw
  7. # away.
  8. if self.query.high_mark is not None or self.query.low_mark:
  9. rn_offset = 1
  10. else:
  11. rn_offset = 0
  12. index_start = rn_offset + len(self.query.extra_select)
  13. values = [self.query.convert_values(v, None, connection=self.connection)
  14. for v in row[rn_offset:index_start]]
  15. for value, field in zip_longest(row[index_start:], fields):
  16. values.append(self.query.convert_values(value, field, connection=self.connection))
  17. return tuple(values)
  18. def as_sql(self, with_limits=True, with_col_aliases=False):
  19. """
  20. Creates the SQL for this query. Returns the SQL string and list
  21. of parameters. This is overridden from the original Query class
  22. to handle the additional SQL Oracle requires to emulate LIMIT
  23. and OFFSET.
  24. If 'with_limits' is False, any limit/offset information is not
  25. included in the query.
  26. """
  27. if with_limits and self.query.low_mark == self.query.high_mark:
  28. return '', ()
  29. # The `do_offset` flag indicates whether we need to construct
  30. # the SQL needed to use limit/offset with Oracle.
  31. do_offset = with_limits and (self.query.high_mark is not None
  32. or self.query.low_mark)
  33. if not do_offset:
  34. sql, params = super(SQLCompiler, self).as_sql(with_limits=False,
  35. with_col_aliases=with_col_aliases)
  36. else:
  37. sql, params = super(SQLCompiler, self).as_sql(with_limits=False,
  38. with_col_aliases=True)
  39. # Wrap the base query in an outer SELECT * with boundaries on
  40. # the "_RN" column. This is the canonical way to emulate LIMIT
  41. # and OFFSET on Oracle.
  42. high_where = ''
  43. if self.query.high_mark is not None:
  44. high_where = 'WHERE ROWNUM <= %d' % (self.query.high_mark,)
  45. sql = 'SELECT * FROM (SELECT ROWNUM AS "_RN", "_SUB".* FROM (%s) "_SUB" %s) WHERE "_RN" > %d' % (sql, high_where, self.query.low_mark)
  46. return sql, params
  47. class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):
  48. pass
  49. class SQLDeleteCompiler(compiler.SQLDeleteCompiler, SQLCompiler):
  50. pass
  51. class SQLUpdateCompiler(compiler.SQLUpdateCompiler, SQLCompiler):
  52. pass
  53. class SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler):
  54. pass
  55. class SQLDateCompiler(compiler.SQLDateCompiler, SQLCompiler):
  56. pass
  57. class SQLDateTimeCompiler(compiler.SQLDateTimeCompiler, SQLCompiler):
  58. pass