summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-10-08 20:06:58 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2013-10-08 20:06:58 -0400
commite74627f827542044c1d2087be95e41d4b1b46f24 (patch)
tree271f25fc6cc032008f2a61609b35a2f5e01dfa3e
parent9df4651fba6d1cd3d2b490f58263cc45a81788f4 (diff)
downloadsqlalchemy-e74627f827542044c1d2087be95e41d4b1b46f24.tar.gz
A :func:`.select` that is made to refer to itself in its FROM clause,
typically via in-place mutation, will raise an informative error message rather than causing a recursion overflow. [ticket:2815]
-rw-r--r--doc/build/changelog/changelog_08.rst9
-rw-r--r--lib/sqlalchemy/sql/selectable.py3
-rw-r--r--test/sql/test_selectable.py12
3 files changed, 24 insertions, 0 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 87dbc8f93..6731fe19a 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -11,6 +11,15 @@
:version: 0.8.3
.. change::
+ :tags: bug, sql
+ :tickets: 2815
+ :versions: 0.9.0
+
+ A :func:`.select` that is made to refer to itself in its FROM clause,
+ typically via in-place mutation, will raise an informative error
+ message rather than causing a recursion overflow.
+
+ .. change::
:tags: bug, orm
:tickets: 2813
:versions: 0.9.0
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index e06262c6d..43d5a084c 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -1936,6 +1936,9 @@ class Select(HasPrefixes, SelectBase):
def add(items):
for item in items:
+ if item is self:
+ raise exc.InvalidRequestError(
+ "select() construct refers to itself as a FROM")
if translate and item in translate:
item = translate[item]
if not seen.intersection(item._cloned_set):
diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py
index 87a226782..0fc7a0ed0 100644
--- a/test/sql/test_selectable.py
+++ b/test/sql/test_selectable.py
@@ -514,6 +514,18 @@ class SelectableTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiled
"SELECT c FROM (SELECT (SELECT (SELECT table1.col1 AS a FROM table1) AS b) AS c)"
)
+ def test_self_referential_select_raises(self):
+ t = table('t', column('x'))
+
+ s = select([t])
+
+ s.append_whereclause(s.c.x > 5)
+ assert_raises_message(
+ exc.InvalidRequestError,
+ r"select\(\) construct refers to itself as a FROM",
+ s.compile
+ )
+
def test_unusual_column_elements_text(self):
"""test that .c excludes text()."""