Skip to content

Commit c1ac679

Browse files
committed
SQLAlchemy: Ignore SQL "FOR UPDATE" clause, CrateDB does not support it
1 parent 471f026 commit c1ac679

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

CHANGES.txt

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Unreleased
1717
constraints
1818
- DBAPI: Properly raise ``IntegrityError`` exceptions instead of
1919
``ProgrammingError``, when CrateDB raises a ``DuplicateKeyException``.
20+
- SQLAlchemy: Ignore SQL's ``FOR UPDATE`` clause. Thanks, @surister.
2021

2122
.. _urllib3 v2.0 migration guide: https://urllib3.readthedocs.io/en/latest/v2-migration-guide.html
2223
.. _urllib3 v2.0 roadmap: https://urllib3.readthedocs.io/en/stable/v2-roadmap.html

src/crate/client/sqlalchemy/compiler.py

+7
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,10 @@ def limit_clause(self, select, **kw):
309309
Generate OFFSET / LIMIT clause, PostgreSQL-compatible.
310310
"""
311311
return PGCompiler.limit_clause(self, select, **kw)
312+
313+
def for_update_clause(self, select, **kw):
314+
# CrateDB does not support the `INSERT ... FOR UPDATE` clause.
315+
# See https://github.com/crate/crate-python/issues/577.
316+
warnings.warn("CrateDB does not support the 'INSERT ... FOR UPDATE' clause, "
317+
"it will be omitted when generating SQL statements.")
318+
return ''

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

+29-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
from crate.testing.settings import crate_host
4444

4545

46-
class SqlAlchemyCompilerTest(ParametrizedTestCase):
46+
class SqlAlchemyCompilerTest(ParametrizedTestCase, ExtraAssertions):
4747

4848
def setUp(self):
4949
self.crate_engine = sa.create_engine('crate://')
@@ -257,6 +257,34 @@ def test_insert_manyvalues(self):
257257
mock.call(mock.ANY, 'INSERT INTO mytable (name) VALUES (?)', ('foo_4', ), None),
258258
])
259259

260+
def test_for_update(self):
261+
"""
262+
Verify the `CrateCompiler.for_update_clause` method to
263+
omit the clause, since CrateDB does not support it.
264+
"""
265+
266+
with warnings.catch_warnings(record=True) as w:
267+
268+
# By default, warnings from a loop will only be emitted once.
269+
# This scenario tests exactly this behaviour, to verify logs
270+
# don't get flooded.
271+
warnings.simplefilter("once")
272+
273+
selectable = self.mytable.select().with_for_update()
274+
_ = str(selectable.compile(bind=self.crate_engine))
275+
276+
selectable = self.mytable.select().with_for_update()
277+
statement = str(selectable.compile(bind=self.crate_engine))
278+
279+
# Verify SQL statement.
280+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable")
281+
282+
# Verify if corresponding warning is emitted, once.
283+
self.assertEqual(len(w), 1)
284+
self.assertIsSubclass(w[-1].category, UserWarning)
285+
self.assertIn("CrateDB does not support the 'INSERT ... FOR UPDATE' clause, "
286+
"it will be omitted when generating SQL statements.", str(w[-1].message))
287+
260288

261289
FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
262290

0 commit comments

Comments
 (0)