From: Mike Bayer Date: Mon, 29 Nov 2010 22:28:36 +0000 (-0500) Subject: - repair MS-SQL handling of LIMIT/OFFSET as binds, add bindparam() to the compile... X-Git-Tag: rel_0_7b1~217 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=35bfda533ed1546f40a5907dfe87c14c0b71cd0d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - repair MS-SQL handling of LIMIT/OFFSET as binds, add bindparam() to the compile stream so they function correctly --- diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index fc374c5953..7dd7400ea6 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -740,13 +740,13 @@ class MSSQLCompiler(compiler.SQLCompiler): sql.literal_column("ROW_NUMBER() OVER (ORDER BY %s)" \ % orderby).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>%s" % self.process(sql.literal(_offset))) + limitselect.append_whereclause(mssql_rn> _offset) if _limit is not None: - limitselect.append_whereclause("mssql_rn<=%s" % - (self.process(sql.literal(_limit + _offset)))) + limitselect.append_whereclause(mssql_rn<=(_limit + _offset)) return self.process(limitselect, iswrapper=True, **kwargs) else: return compiler.SQLCompiler.visit_select(self, select, **kwargs) diff --git a/test/dialect/test_mssql.py b/test/dialect/test_mssql.py index 26c53298c6..63aa874fd0 100644 --- a/test/dialect/test_mssql.py +++ b/test/dialect/test_mssql.py @@ -334,7 +334,49 @@ class CompileTest(TestBase, AssertsCompiledSQL): 'LEN(inserted.name) AS length_1 VALUES ' '(:name)') + def test_limit_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(10) + + 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} + ) + + def test_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).offset(20) + + self.assert_compile( + s, + "SELECT anon_1.x, anon_1.y FROM (SELECT t.x AS x, t.y " + "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} + ) + def test_limit_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(10).offset(20) + + self.assert_compile( + s, + "SELECT anon_1.x, anon_1.y " + "FROM (SELECT t.x AS x, t.y 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 AND mssql_rn <= :mssql_rn_2", + {u'mssql_rn_1': 20, u'mssql_rn_2': 30, u'x_1': 5} + ) + + + class IdentityInsertTest(TestBase, AssertsCompiledSQL): __only_on__ = 'mssql' __dialect__ = mssql.MSDialect()