diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-02-05 17:04:37 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-02-05 17:04:37 +0000 |
commit | 1e1eea05538e43a41750ba8548da517d77284e9c (patch) | |
tree | d2998bf781b5f7f8e9b4c08767436265a7a4118f | |
parent | a9fb2f3e6f9b3dd50385cfea5570a023a89ddd8c (diff) | |
download | sqlalchemy-1e1eea05538e43a41750ba8548da517d77284e9c.tar.gz |
got oracle LIMIT/OFFSET to use row_number() syntax
sql: ColumnClause will use the given name when proxying itself (used for the "ora_rn" label)
ansisql: When adding on ORDER_BY, GROUP_BY, etc. clauses, if there is no string for the column list,
then dont add the clause (this allows oracle to strip out the ORDER BY)
Oracle is modifying the select statement, which is not ideal - should fix that
-rw-r--r-- | lib/sqlalchemy/ansisql.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/databases/oracle.py | 20 | ||||
-rw-r--r-- | lib/sqlalchemy/sql.py | 2 |
3 files changed, 20 insertions, 6 deletions
diff --git a/lib/sqlalchemy/ansisql.py b/lib/sqlalchemy/ansisql.py index 30060a93c..fc4af5198 100644 --- a/lib/sqlalchemy/ansisql.py +++ b/lib/sqlalchemy/ansisql.py @@ -319,7 +319,9 @@ class ANSICompiler(sql.Compiled): text += " \nWHERE " + t for tup in select.clauses: - text += " " + tup[0] + " " + self.get_str(tup[1]) + ss = self.get_str(tup[1]) + if ss: + text += " " + tup[0] + " " + ss if select.having is not None: t = self.get_str(select.having) diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py index de4a76c3e..857b0c2fc 100644 --- a/lib/sqlalchemy/databases/oracle.py +++ b/lib/sqlalchemy/databases/oracle.py @@ -191,17 +191,29 @@ class OracleCompiler(ansisql.ANSICompiler): def visit_select(self, select): """looks for LIMIT and OFFSET in a select statement, and if so tries to wrap it in a - subquery with rownum criterion.""" + subquery with row_number() criterion.""" + # TODO: put a real copy-container on Select and copy, or somehow make this + # not modify the Select statement if getattr(select, '_oracle_visit', False): + # cancel out the compiled order_by on the select + if hasattr(select, "order_by_clause"): + self.strings[select.order_by_clause] = "" ansisql.ANSICompiler.visit_select(self, select) return if select.limit is not None or select.offset is not None: select._oracle_visit = True + if hasattr(select, "order_by_clause"): + orderby = self.strings[select.order_by_clause] + else: + orderby = "rowid ASC" + select.append_column(sql.ColumnClause("ROW_NUMBER() OVER (ORDER BY %s)" % orderby).label("ora_rn")) limitselect = select.select() - if select.limit is not None: - limitselect.append_whereclause("rownum<%d" % select.limit) if select.offset is not None: - limitselect.append_whereclause("rownum>%d" % select.offset) + limitselect.append_whereclause("ora_rn>%d" % select.offset) + if select.limit is not None: + limitselect.append_whereclause("ora_rn<=%d" % (select.limit + select.offset)) + else: + limitselect.append_whereclause("ora_rn<=%d" % select.limit) limitselect.accept_visitor(self) self.strings[select] = self.strings[limitselect] self.froms[select] = self.froms[limitselect] diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index 8be40ac1d..c8a05470c 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -987,7 +987,7 @@ class ColumnClause(ColumnElement): else: return BindParamClause(self.table.name + "_" + self.text, obj, shortname = self.text, type=self.type) def _make_proxy(self, selectable, name = None): - c = ColumnClause(self.text or name, selectable) + c = ColumnClause(name or self.text, selectable) selectable.columns[c.key] = c return c |