Skip to content

Commit 4532ef7

Browse files
committedNov 22, 2022
Fix generating appropriate syntax for OFFSET/LIMIT clauses
The standard SQLAlchemy statements compiler can generate `LIMIT -1` clauses, but PostgreSQL and CrateDB do not accept them, and need `LIMIT ALL` instead. The fix is to re-use the existing `PGCompiler.limit_clause` method within `CrateCompiler`.
1 parent 2742729 commit 4532ef7

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed
 

‎CHANGES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Unreleased
77
- Added a generic data type converter to the ``Cursor`` object, for converting
88
fetched data from CrateDB data types to Python data types.
99

10+
- Fixed generating appropriate syntax for OFFSET/LIMIT clauses. It was possible
11+
that SQL statement clauses like ``LIMIT -1`` could have been generated. Both
12+
PostgreSQL and CrateDB only accept ``LIMIT ALL`` instead.
13+
1014

1115
2022/10/10 0.27.2
1216
=================

‎src/crate/client/sqlalchemy/compiler.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from collections import defaultdict
2424

2525
import sqlalchemy as sa # lgtm[py/import-and-import-from]
26+
from sqlalchemy.dialects.postgresql.base import PGCompiler
2627
from sqlalchemy.sql import compiler, crud, selectable # lgtm[py/import-and-import-from]
2728
from .types import MutableDict
2829
from .sa_version import SA_VERSION, SA_1_4
@@ -289,6 +290,12 @@ def visit_update(self, update_stmt, **kw):
289290

290291
return text
291292

293+
def limit_clause(self, select, **kw):
294+
"""
295+
Generate OFFSET / LIMIT clause, PostgreSQL-compatible.
296+
"""
297+
return PGCompiler.limit_clause(self, select, **kw)
298+
292299
def _get_crud_params(compiler, stmt, **kw):
293300
""" extract values from crud parameters
294301
taken from SQLAlchemy's crud module (since 1.0.x) and

‎src/crate/client/sqlalchemy/tests/compiler_test.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class SqlAlchemyCompilerTest(TestCase):
3434
def setUp(self):
3535
self.crate_engine = sa.create_engine('crate://')
3636
self.sqlite_engine = sa.create_engine('sqlite://')
37-
metadata = sa.MetaData()
38-
self.mytable = sa.Table('mytable', metadata,
37+
self.metadata = sa.MetaData()
38+
self.mytable = sa.Table('mytable', self.metadata,
3939
sa.Column('name', sa.String),
4040
sa.Column('data', Craty))
4141

@@ -69,3 +69,30 @@ def test_bulk_update_on_builtin_type(self):
6969
)
7070

7171
self.assertFalse(hasattr(clauseelement, '_crate_specific'))
72+
73+
def test_select_with_offset(self):
74+
"""
75+
Verify the `CrateCompiler.limit_clause` method, with offset.
76+
"""
77+
self.metadata.bind = self.crate_engine
78+
selectable = self.mytable.select().offset(5)
79+
statement = str(selectable.compile())
80+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable\n LIMIT ALL OFFSET ?")
81+
82+
def test_select_with_limit(self):
83+
"""
84+
Verify the `CrateCompiler.limit_clause` method, with limit.
85+
"""
86+
self.metadata.bind = self.crate_engine
87+
selectable = self.mytable.select().limit(42)
88+
statement = str(selectable.compile())
89+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ?")
90+
91+
def test_select_with_offset_and_limit(self):
92+
"""
93+
Verify the `CrateCompiler.limit_clause` method, with offset and limit.
94+
"""
95+
self.metadata.bind = self.crate_engine
96+
selectable = self.mytable.select().offset(5).limit(42)
97+
statement = str(selectable.compile())
98+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ? OFFSET ?")

0 commit comments

Comments
 (0)
Please sign in to comment.