summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-04-17 10:16:35 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2023-04-17 10:21:51 -0400
commitd519bca7f953a0520cda79504dbc019e74e87b28 (patch)
tree4d63a27c206cb3b181a6f3d0d9d068211979c3b6
parente45cbb296cd1f158b7627999dc46b1fca798b829 (diff)
downloadsqlalchemy-d519bca7f953a0520cda79504dbc019e74e87b28.tar.gz
dont assume _compile_options are present
Fixed bug where various ORM-specific getters such as :attr:`.ORMExecuteState.is_column_load`, :attr:`.ORMExecuteState.is_relationship_load`, :attr:`.ORMExecuteState.loader_strategy_path` etc. would throw an ``AttributeError`` if the SQL statement itself were a "compound select" such as a UNION. Fixes: #9634 Change-Id: Ia37df5d6f89d6534d69237dcab294bd849ece28b (cherry picked from commit 89608ccd3f5e5796d578e9a39201f7c5c45a61fe)
-rw-r--r--doc/build/changelog/unreleased_14/9634.rst11
-rw-r--r--lib/sqlalchemy/orm/session.py5
-rw-r--r--test/orm/test_events.py32
3 files changed, 47 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_14/9634.rst b/doc/build/changelog/unreleased_14/9634.rst
new file mode 100644
index 000000000..664e85716
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/9634.rst
@@ -0,0 +1,11 @@
+.. change::
+ :tags: bug, orm
+ :tickets: 9634
+ :versions: 2.0.10
+
+ Fixed bug where various ORM-specific getters such as
+ :attr:`.ORMExecuteState.is_column_load`,
+ :attr:`.ORMExecuteState.is_relationship_load`,
+ :attr:`.ORMExecuteState.loader_strategy_path` etc. would throw an
+ ``AttributeError`` if the SQL statement itself were a "compound select"
+ such as a UNION.
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 753d1ec5f..5a7a8bb21 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -347,7 +347,10 @@ class ORMExecuteState(util.MemoizedSlots):
def _orm_compile_options(self):
if not self.is_select:
return None
- opts = self.statement._compile_options
+ try:
+ opts = self.statement._compile_options
+ except AttributeError:
+ return None
if opts.isinstance(context.ORMCompileState.default_compile_options):
return opts
else:
diff --git a/test/orm/test_events.py b/test/orm/test_events.py
index efb39bd2f..052b9e016 100644
--- a/test/orm/test_events.py
+++ b/test/orm/test_events.py
@@ -8,6 +8,7 @@ from sqlalchemy import literal_column
from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy import testing
+from sqlalchemy import text
from sqlalchemy import update
from sqlalchemy.orm import attributes
from sqlalchemy.orm import class_mapper
@@ -292,6 +293,37 @@ class ORMExecuteTest(_RemoveListeners, _fixtures.FixtureTest):
return canary
+ @testing.combinations(
+ (lambda: select(1), True),
+ (lambda User: select(User).union(select(User)), True),
+ (lambda: text("select * from users"), False),
+ )
+ def test_non_orm_statements(self, stmt, is_select):
+ sess = Session(testing.db, future=True)
+
+ canary = self._flag_fixture(sess)
+
+ User, Address = self.classes("User", "Address")
+ stmt = testing.resolve_lambda(stmt, User=User)
+ sess.execute(stmt).all()
+
+ eq_(
+ canary.mock_calls,
+ [
+ call.options(
+ bind_mapper=None,
+ all_mappers=[],
+ is_select=is_select,
+ is_update=False,
+ is_delete=False,
+ is_orm_statement=False,
+ is_relationship_load=False,
+ is_column_load=False,
+ lazy_loaded_from=None,
+ )
+ ],
+ )
+
def test_all_mappers_accessor_one(self):
User, Address = self.classes("User", "Address")