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:20:33 -0400
commit89608ccd3f5e5796d578e9a39201f7c5c45a61fe (patch)
tree7ab7811b5d233fc7f4433d8bdc6ee84d237e1537
parentacf7fbd60b9b1291dfc91438416867c88e94c5ba (diff)
downloadsqlalchemy-89608ccd3f5e5796d578e9a39201f7c5c45a61fe.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
-rw-r--r--doc/build/changelog/unreleased_14/9634.rst11
-rw-r--r--lib/sqlalchemy/orm/session.py6
-rw-r--r--test/orm/test_events.py32
3 files changed, 48 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 e6d6251cf..792b59e81 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -603,7 +603,11 @@ class ORMExecuteState(util.MemoizedSlots):
]:
if not self.is_select:
return None
- opts = self.statement._compile_options
+ try:
+ opts = self.statement._compile_options
+ except AttributeError:
+ return None
+
if opts is not None and opts.isinstance(
context.ORMCompileState.default_compile_options
):
diff --git a/test/orm/test_events.py b/test/orm/test_events.py
index d2a43331f..07d27451d 100644
--- a/test/orm/test_events.py
+++ b/test/orm/test_events.py
@@ -16,6 +16,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
@@ -400,6 +401,37 @@ class ORMExecuteTest(RemoveORMEventsGlobally, _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")