summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-02-05 17:04:37 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-02-05 17:04:37 +0000
commit1e1eea05538e43a41750ba8548da517d77284e9c (patch)
treed2998bf781b5f7f8e9b4c08767436265a7a4118f /lib/sqlalchemy
parenta9fb2f3e6f9b3dd50385cfea5570a023a89ddd8c (diff)
downloadsqlalchemy-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
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/ansisql.py4
-rw-r--r--lib/sqlalchemy/databases/oracle.py20
-rw-r--r--lib/sqlalchemy/sql.py2
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