mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-15 05:07:16 -04:00
Merge "ensure correlate_except is checked for empty tuple" into main
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
.. change::
|
||||
:tags: bug, orm
|
||||
:tickets: 7514
|
||||
|
||||
Fixed issue where :meth:`_sql.Select.correlate_except` method, when passed
|
||||
either the ``None`` value or no arguments, would not correlate any elements
|
||||
when used in an ORM context (that is, passing ORM entities as FROM
|
||||
clauses), rather than causing all FROM elements to be considered as
|
||||
"correlated" in the same way which occurs when using Core-only constructs.
|
||||
@@ -774,7 +774,7 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
|
||||
for s in query._correlate
|
||||
)
|
||||
)
|
||||
elif query._correlate_except:
|
||||
elif query._correlate_except is not None:
|
||||
self.correlate_except = tuple(
|
||||
util.flatten_iterator(
|
||||
sql_util.surface_selectables(s) if s is not None else None
|
||||
@@ -1192,7 +1192,7 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
|
||||
if correlate:
|
||||
statement.correlate.non_generative(statement, *correlate)
|
||||
|
||||
if correlate_except:
|
||||
if correlate_except is not None:
|
||||
statement.correlate_except.non_generative(
|
||||
statement, *correlate_except
|
||||
)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from sqlalchemy import bindparam
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import exc
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy import insert
|
||||
from sqlalchemy import inspect
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import literal_column
|
||||
from sqlalchemy import null
|
||||
from sqlalchemy import or_
|
||||
@@ -31,12 +33,15 @@ from sqlalchemy.sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
|
||||
from sqlalchemy.testing import assert_raises_message
|
||||
from sqlalchemy.testing import AssertsCompiledSQL
|
||||
from sqlalchemy.testing import eq_
|
||||
from sqlalchemy.testing import fixtures
|
||||
from sqlalchemy.testing import is_
|
||||
from sqlalchemy.testing.assertions import expect_raises_message
|
||||
from sqlalchemy.testing.fixtures import fixture_session
|
||||
from sqlalchemy.testing.util import resolve_lambda
|
||||
from sqlalchemy.util.langhelpers import hybridproperty
|
||||
from .inheritance import _poly_fixtures
|
||||
from .test_query import QueryTest
|
||||
from ..sql.test_compiler import CorrelateTest as _CoreCorrelateTest
|
||||
|
||||
# TODO:
|
||||
# composites / unions, etc.
|
||||
@@ -2320,3 +2325,29 @@ class RawSelectTest(QueryTest, AssertsCompiledSQL):
|
||||
)
|
||||
self.assert_compile(stmt1, expected)
|
||||
self.assert_compile(stmt2, expected)
|
||||
|
||||
|
||||
class CorrelateTest(fixtures.DeclarativeMappedTest, _CoreCorrelateTest):
|
||||
@classmethod
|
||||
def setup_classes(cls):
|
||||
Base = cls.DeclarativeBasic
|
||||
|
||||
class T1(Base):
|
||||
__tablename__ = "t1"
|
||||
a = Column(Integer, primary_key=True)
|
||||
|
||||
@hybridproperty
|
||||
def c(self):
|
||||
return self
|
||||
|
||||
class T2(Base):
|
||||
__tablename__ = "t2"
|
||||
a = Column(Integer, primary_key=True)
|
||||
|
||||
@hybridproperty
|
||||
def c(self):
|
||||
return self
|
||||
|
||||
def _fixture(self):
|
||||
t1, t2 = self.classes("T1", "T2")
|
||||
return t1, t2, select(t1).where(t1.c.a == t2.c.a)
|
||||
|
||||
@@ -5920,6 +5920,14 @@ class CorrelateTest(fixtures.TestBase, AssertsCompiledSQL):
|
||||
)
|
||||
)
|
||||
|
||||
def test_correlate_except_empty(self):
|
||||
t1, t2, s1 = self._fixture()
|
||||
self._assert_where_all_correlated(
|
||||
select(t1, t2).where(
|
||||
t2.c.a == s1.correlate_except().scalar_subquery()
|
||||
)
|
||||
)
|
||||
|
||||
def test_correlate_except_having(self):
|
||||
t1, t2, s1 = self._fixture()
|
||||
self._assert_having_correlated(
|
||||
|
||||
Reference in New Issue
Block a user