twice. Thanks *much* to Dave Vitek
for the excellent fix here. [ticket:2247]
+ - Query will convert an OFFSET of zero when
+ slicing into None, so that needless OFFSET
+ clauses are not invoked.
+
- sqlite
- Ensured that the same ValueError is raised for
illegal date/time/datetime string parsed from
source for server side cursor names;
conflicts have been reported in rare cases.
+- mssql
+ - "0" is accepted as an argument for limit() which
+ will produce "TOP 0". [ticket:2222]
+
- ext
- Added local_attr, remote_attr, attr accessors
to AssociationProxy, providing quick access
def get_select_precolumns(self, select):
""" MS-SQL puts TOP, it's version of LIMIT here """
- if select._distinct or select._limit:
+ if select._distinct or select._limit is not None:
s = select._distinct and "DISTINCT " or ""
# 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:
+ if select._limit is not None:
if not select._offset:
s += "TOP %d " % select._limit
return s
elif start is not None and stop is None:
self._offset = (self._offset or 0) + start
+ if self._offset == 0:
+ self._offset = None
+
@_generative(_no_statement_condition)
def limit(self, limit):
"""Apply a ``LIMIT`` to the query and return the newly resulting
self.assert_compile(
s,
"SELECT TOP 10 t.x, t.y FROM t WHERE t.x = :x_1 ORDER BY t.y",
- {u'x_1': 5}
+ checkparams={u'x_1': 5}
+ )
+
+ def test_limit_zero_using_top(self):
+ t = table('t', column('x', Integer), column('y', Integer))
+
+ s = select([t]).where(t.c.x==5).order_by(t.c.y).limit(0)
+
+ self.assert_compile(
+ s,
+ "SELECT TOP 0 t.x, t.y FROM t WHERE t.x = :x_1 ORDER BY t.y",
+ checkparams={u'x_1': 5}
)
def test_offset_using_window(self):
"AS y, ROW_NUMBER() OVER (ORDER BY t.y) AS "
"mssql_rn FROM t WHERE t.x = :x_1) AS "
"anon_1 WHERE mssql_rn > :mssql_rn_1",
- {u'mssql_rn_1': 20, u'x_1': 5}
+ checkparams={u'mssql_rn_1': 20, u'x_1': 5}
)
def test_limit_offset_using_window(self):
"FROM t "
"WHERE t.x = :x_1) AS anon_1 "
"WHERE mssql_rn > :mssql_rn_1 AND mssql_rn <= :mssql_rn_2",
- {u'mssql_rn_1': 20, u'mssql_rn_2': 30, u'x_1': 5}
+ checkparams={u'mssql_rn_1': 20, u'mssql_rn_2': 30, u'x_1': 5}
+ )
+
+ def test_limit_zero_offset_using_window(self):
+ t = table('t', column('x', Integer), column('y', Integer))
+
+ s = select([t]).where(t.c.x==5).order_by(t.c.y).limit(0).offset(0)
+
+ # render the LIMIT of zero, but not the OFFSET
+ # of zero, so produces TOP 0
+ self.assert_compile(
+ s,
+ "SELECT TOP 0 t.x, t.y FROM t "
+ "WHERE t.x = :x_1 ORDER BY t.y",
+ checkparams={u'x_1': 5}
)
assert_raises(ValueError, select, offset="foo")
assert_raises(ValueError, select, limit="foo")
+ def test_limit_offset(self):
+ for lim, offset, exp, params in [
+ (5, 10, "LIMIT :param_1 OFFSET :param_2",
+ {'param_1':5, 'param_2':10}),
+ (None, 10, "LIMIT -1 OFFSET :param_1", {'param_1':10}),
+ (5, None, "LIMIT :param_1", {'param_1':5}),
+ (0, 0, "LIMIT :param_1 OFFSET :param_2",
+ {'param_1':0, 'param_2':0}),
+ ]:
+ self.assert_compile(
+ select([1]).limit(lim).offset(offset),
+ "SELECT 1 " + exp,
+ checkparams =params
+ )
+
def test_from_subquery(self):
"""tests placing select statements in the column clause of another select, for the
purposes of selecting from the exported columns of that select."""