]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Ensure _BundleEntity provides .mapper
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 29 Jan 2018 23:07:19 +0000 (18:07 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 30 Jan 2018 02:24:04 +0000 (21:24 -0500)
Fixed bug where the :class:`.Bundle` object did not
correctly report upon the primary :class:`.Mapper` object
represened by the bundle, if any.   An immediate
side effect of this issue was that the new selectinload
loader strategy wouldn't work with the horizontal sharding
extension.

Change-Id: I54a626100b2f4da497597e8944fa8dd853de47a3
Fixes: #4175
doc/build/changelog/unreleased_12/4175.rst [new file with mode: 0644]
lib/sqlalchemy/orm/query.py
test/ext/test_horizontal_shard.py
test/orm/test_query.py

diff --git a/doc/build/changelog/unreleased_12/4175.rst b/doc/build/changelog/unreleased_12/4175.rst
new file mode 100644 (file)
index 0000000..7d215a7
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 4175
+
+    Fixed bug where the :class:`.Bundle` object did not
+    correctly report upon the primary :class:`.Mapper` object
+    represened by the bundle, if any.   An immediate
+    side effect of this issue was that the new selectinload
+    loader strategy wouldn't work with the horizontal sharding
+    extension.
index 87f58b996d21b22be71113dc419e7ec47ea4be5d..4f7b22cc928c1f627361bda7cd93f64d56acfb73 100644 (file)
@@ -3892,6 +3892,10 @@ class _BundleEntity(_QueryEntity):
 
         self.supports_single_entity = self.bundle.single_entity
 
+    @property
+    def mapper(self):
+        return self.entity_zero.mapper
+
     @property
     def entities(self):
         entities = []
index c09753e5dfc2c0bf554092859136c9a6aba65ba3..a5ea44e04d7a234ffbb4e0e3c8439c6e06ba2e6d 100644 (file)
@@ -9,6 +9,7 @@ from sqlalchemy.sql import operators
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing.engines import testing_engine
 from sqlalchemy.testing import eq_
+from sqlalchemy import testing
 
 # TODO: ShardTest can be turned into a base for further subclasses
 
@@ -296,7 +297,6 @@ class ShardTest(object):
 
 
 class DistinctEngineShardTest(ShardTest, fixtures.TestBase):
-
     def _init_dbs(self):
         db1 = testing_engine('sqlite:///shard1.db',
                              options=dict(pool_threadlocal=True))
@@ -338,3 +338,37 @@ class AttachedFileShardTest(ShardTest, fixtures.TestBase):
             return stmt, params
 
         return db1, db2, db3, db4
+
+
+class SelectinloadRegressionTest(fixtures.DeclarativeMappedTest):
+    @classmethod
+    def setup_classes(cls):
+        Base = cls.DeclarativeBasic
+
+        class Book(Base):
+            __tablename__ = 'book'
+            id = Column(Integer, primary_key=True)
+            pages = relationship('Page')
+
+        class Page(Base):
+            __tablename__ = 'page'
+            id = Column(Integer, primary_key=True)
+            book_id = Column(ForeignKey('book.id'))
+
+    def test_selectinload_query(self):
+        session = ShardedSession(
+            shards={"test": testing.db},
+            shard_chooser=lambda *args: 'test',
+            id_chooser=lambda *args: None,
+            query_chooser=lambda *args: ['test']
+        )
+
+        Book, Page = self.classes("Book", "Page")
+        book = Book()
+        book.pages.append(Page())
+
+        session.add(book)
+        session.commit()
+
+        result = session.query(Book).options(selectinload('pages')).all()
+        eq_(result, [book])
index 3b91f5ffaf749621c38384d66157d9ab2a68c955..502f1427a87013e82cc800ae012e0d6e9318dc59 100644 (file)
@@ -843,6 +843,10 @@ class InvalidGenerationsTest(QueryTest, AssertsCompiledSQL):
         is_(q._mapper_zero(), None)
         is_(q._entity_zero(), None)
 
+        q1 = s.query(Bundle('b1', User.id, User.name))
+        is_(q1._mapper_zero(), inspect(User))
+        is_(q1._entity_zero(), inspect(User))
+
     def test_from_statement(self):
         User = self.classes.User