summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-05-23 11:20:27 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-05-23 11:20:27 -0400
commit48c6eb3f9f2bafd6db34b404df27242835b4f8dd (patch)
treea99767bc16cc9a5bf9481be42859de083fd84742 /lib/sqlalchemy/dialects
parent0932e16cb7375a1d9f70b3c35cfe33a2835fa85a (diff)
parent81959af6d37be503a13ce9c53317d443e14ae570 (diff)
downloadsqlalchemy-48c6eb3f9f2bafd6db34b404df27242835b4f8dd.tar.gz
Merge branch 'ticket_3034'
Diffstat (limited to 'lib/sqlalchemy/dialects')
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py9
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py52
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py16
-rw-r--r--lib/sqlalchemy/dialects/oracle/base.py18
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py10
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py10
-rw-r--r--lib/sqlalchemy/dialects/sybase/base.py12
7 files changed, 74 insertions, 53 deletions
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py
index 21db57b68..a3867457e 100644
--- a/lib/sqlalchemy/dialects/firebird/base.py
+++ b/lib/sqlalchemy/dialects/firebird/base.py
@@ -77,7 +77,6 @@ from sqlalchemy.sql import expression
from sqlalchemy.engine import base, default, reflection
from sqlalchemy.sql import compiler
-
from sqlalchemy.types import (BIGINT, BLOB, DATE, FLOAT, INTEGER, NUMERIC,
SMALLINT, TEXT, TIME, TIMESTAMP, Integer)
@@ -300,10 +299,10 @@ class FBCompiler(sql.compiler.SQLCompiler):
"""
result = ""
- if select._limit:
- result += "FIRST %s " % self.process(sql.literal(select._limit))
- if select._offset:
- result += "SKIP %s " % self.process(sql.literal(select._offset))
+ if select._limit_clause:
+ result += "FIRST %s " % self.process(select._limit_clause)
+ if select._offset_clause:
+ result += "SKIP %s " % self.process(select._offset_clause)
if select._distinct:
result += "DISTINCT "
return result
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index 3fcc95f46..59cbb80bb 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -740,18 +740,22 @@ class MSSQLCompiler(compiler.SQLCompiler):
self.process(binary.right, **kw))
def get_select_precolumns(self, select):
- """ MS-SQL puts TOP, its version of LIMIT, here """
- if select._distinct or select._limit is not None:
- s = select._distinct and "DISTINCT " or ""
+ """ MS-SQL puts TOP, it's version of LIMIT here """
+ s = ""
+ if select._distinct:
+ s += "DISTINCT "
+
+ if select._simple_int_limit and not select._offset:
# ODBC drivers and possibly others
# don't support bind params in the SELECT clause on SQL Server.
# so have to use literal here.
- if select._limit is not None:
- if not select._offset:
- s += "TOP %d " % select._limit
+ s += "TOP %d " % select._limit
+
+ if s:
return s
- return compiler.SQLCompiler.get_select_precolumns(self, select)
+ else:
+ return compiler.SQLCompiler.get_select_precolumns(self, select)
def get_from_hint_text(self, table, text):
return text
@@ -768,28 +772,42 @@ class MSSQLCompiler(compiler.SQLCompiler):
so tries to wrap it in a subquery with ``row_number()`` criterion.
"""
- if select._offset and not getattr(select, '_mssql_visit', None):
+ if (
+ (
+ not select._simple_int_limit and
+ select._limit_clause is not None
+ ) or (
+ select._offset_clause is not None and
+ not select._simple_int_offset or select._offset
+ )
+ ) and not getattr(select, '_mssql_visit', None):
+
# to use ROW_NUMBER(), an ORDER BY is required.
if not select._order_by_clause.clauses:
raise exc.CompileError('MSSQL requires an order_by when '
- 'using an offset.')
+ 'using an OFFSET or a non-simple '
+ 'LIMIT clause')
- _offset = select._offset
- _limit = select._limit
_order_by_clauses = select._order_by_clause.clauses
+ limit_clause = select._limit_clause
+ offset_clause = select._offset_clause
select = select._generate()
select._mssql_visit = True
select = select.column(
- sql.func.ROW_NUMBER().over(order_by=_order_by_clauses)
- .label("mssql_rn")
- ).order_by(None).alias()
+ sql.func.ROW_NUMBER().over(order_by=_order_by_clauses)
+ .label("mssql_rn")).order_by(None).alias()
mssql_rn = sql.column('mssql_rn')
limitselect = sql.select([c for c in select.c if
c.key != 'mssql_rn'])
- limitselect.append_whereclause(mssql_rn > _offset)
- if _limit is not None:
- limitselect.append_whereclause(mssql_rn <= (_limit + _offset))
+ if offset_clause is not None:
+ limitselect.append_whereclause(mssql_rn > offset_clause)
+ if limit_clause is not None:
+ limitselect.append_whereclause(
+ mssql_rn <= (limit_clause + offset_clause))
+ else:
+ limitselect.append_whereclause(
+ mssql_rn <= (limit_clause))
return self.process(limitselect, iswrapper=True, **kwargs)
else:
return compiler.SQLCompiler.visit_select(self, select, **kwargs)
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 85cbd6e22..e8a15fdbc 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1568,15 +1568,15 @@ class MySQLCompiler(compiler.SQLCompiler):
# The latter is more readable for offsets but we're stuck with the
# former until we can refine dialects by server revision.
- limit, offset = select._limit, select._offset
+ limit_clause, offset_clause = select._limit_clause, select._offset_clause
- if (limit, offset) == (None, None):
+ if (limit_clause, offset_clause) == (None, None):
return ''
- elif offset is not None:
+ elif offset_clause is not None:
# As suggested by the MySQL docs, need to apply an
# artificial limit if one wasn't provided
# http://dev.mysql.com/doc/refman/5.0/en/select.html
- if limit is None:
+ if limit_clause is None:
# hardwire the upper limit. Currently
# needed by OurSQL with Python 3
# (https://bugs.launchpad.net/oursql/+bug/686232),
@@ -1584,15 +1584,15 @@ class MySQLCompiler(compiler.SQLCompiler):
# bound as part of MySQL's "syntax" for OFFSET with
# no LIMIT
return ' \n LIMIT %s, %s' % (
- self.process(sql.literal(offset)),
+ self.process(offset_clause),
"18446744073709551615")
else:
return ' \n LIMIT %s, %s' % (
- self.process(sql.literal(offset)),
- self.process(sql.literal(limit)))
+ self.process(offset_clause),
+ self.process(limit_clause))
else:
# No offset provided, so just use the limit
- return ' \n LIMIT %s' % (self.process(sql.literal(limit)),)
+ return ' \n LIMIT %s' % (self.process(limit_clause),)
def update_limit_clause(self, update_stmt):
limit = update_stmt.kwargs.get('%s_limit' % self.dialect.name, None)
diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py
index 5dcc93f79..b0f32f491 100644
--- a/lib/sqlalchemy/dialects/oracle/base.py
+++ b/lib/sqlalchemy/dialects/oracle/base.py
@@ -652,24 +652,26 @@ class OracleCompiler(compiler.SQLCompiler):
# Wrap the middle select and add the hint
limitselect = sql.select([c for c in select.c])
- if select._limit and self.dialect.optimize_limits:
- limitselect = limitselect.prefix_with("/*+ FIRST_ROWS(%d) */" % select._limit)
+ limit = select._limit
+ if limit and self.dialect.optimize_limits:
+ limitselect = limitselect.prefix_with("/*+ FIRST_ROWS(%d) */" % limit)
limitselect._oracle_visit = True
limitselect._is_wrapper = True
# If needed, add the limiting clause
- if select._limit is not None:
- max_row = select._limit
- if select._offset is not None:
- max_row += select._offset
+ offset = select._offset
+ if limit is not None:
+ max_row = limit
+ if offset is not None:
+ max_row += offset
if not self.dialect.use_binds_for_limits:
max_row = sql.literal_column("%d" % max_row)
limitselect.append_whereclause(
sql.literal_column("ROWNUM") <= max_row)
# If needed, add the ora_rn, and wrap again with offset.
- if select._offset is None:
+ if offset is None:
limitselect._for_update_arg = select._for_update_arg
select = limitselect
else:
@@ -683,7 +685,7 @@ class OracleCompiler(compiler.SQLCompiler):
offsetselect._oracle_visit = True
offsetselect._is_wrapper = True
- offset_value = select._offset
+ offset_value = offset
if not self.dialect.use_binds_for_limits:
offset_value = sql.literal_column("%d" % offset_value)
offsetselect.append_whereclause(
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index bcbf0b12c..e2accfedb 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1161,12 +1161,12 @@ class PGCompiler(compiler.SQLCompiler):
def limit_clause(self, select):
text = ""
- if select._limit is not None:
- text += " \n LIMIT " + self.process(sql.literal(select._limit))
- if select._offset is not None:
- if select._limit is None:
+ if select._limit_clause is not None:
+ text += " \n LIMIT " + self.process(select._limit_clause)
+ if select._offset_clause is not None:
+ if select._limit_clause is None:
text += " \n LIMIT ALL"
- text += " OFFSET " + self.process(sql.literal(select._offset))
+ text += " OFFSET " + self.process(select._offset_clause)
return text
def format_from_hint_text(self, sqltext, table, hint, iscrud):
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index 7687493b2..de8b01e6f 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -519,12 +519,12 @@ class SQLiteCompiler(compiler.SQLCompiler):
def limit_clause(self, select):
text = ""
- if select._limit is not None:
- text += "\n LIMIT " + self.process(sql.literal(select._limit))
- if select._offset is not None:
- if select._limit is None:
+ if select._limit_clause is not None:
+ text += "\n LIMIT " + self.process(select._limit_clause)
+ if select._offset_clause is not None:
+ if select._limit_clause is None:
text += "\n LIMIT " + self.process(sql.literal(-1))
- text += " OFFSET " + self.process(sql.literal(select._offset))
+ text += " OFFSET " + self.process(select._offset_clause)
else:
text += " OFFSET " + self.process(sql.literal(0))
return text
diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py
index 501270778..3e61b5ba6 100644
--- a/lib/sqlalchemy/dialects/sybase/base.py
+++ b/lib/sqlalchemy/dialects/sybase/base.py
@@ -325,18 +325,20 @@ class SybaseSQLCompiler(compiler.SQLCompiler):
s = select._distinct and "DISTINCT " or ""
# TODO: don't think Sybase supports
# bind params for FIRST / TOP
- if select._limit:
+ limit = select._limit
+ if limit:
#if select._limit == 1:
#s += "FIRST "
#else:
#s += "TOP %s " % (select._limit,)
- s += "TOP %s " % (select._limit,)
- if select._offset:
- if not select._limit:
+ s += "TOP %s " % (limit,)
+ offset = select._offset
+ if offset:
+ if not limit:
# FIXME: sybase doesn't allow an offset without a limit
# so use a huge value for TOP here
s += "TOP 1000000 "
- s += "START AT %s " % (select._offset + 1,)
+ s += "START AT %s " % (offset + 1,)
return s
def get_from_hint_text(self, table, text):