]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- MapperProperty gets its .key attribute assigned early, in _compile_property.
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 16 Jul 2008 21:56:23 +0000 (21:56 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 16 Jul 2008 21:56:23 +0000 (21:56 +0000)
MapperProperty compilation is detected using a "_compiled" flag.
- A mapper which inherits from another, when inheriting
the columns of its inherited mapper, will use any
reassigned property names specified in that inheriting
mapper.  Previously, if "Base" had reassigned "base_id"
to the name "id", "SubBase(Base)" would still get
an attribute called "base_id".   This could be worked
around by explicitly stating the column in each
submapper as well but this is fairly unworkable
and also impossible when using declarative [ticket:1111].

CHANGES
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance/basic.py

diff --git a/CHANGES b/CHANGES
index 60a1862a43dbc27a5579991f1bf2e8126fc53424..68171c925fe6aa6f635022b6133fb8921c3c7f71 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,16 @@ CHANGES
       This is called at the point of attachment for objects
       via add(), add_all(), delete(), and merge().
 
+    - A mapper which inherits from another, when inheriting
+      the columns of its inherited mapper, will use any
+      reassigned property names specified in that inheriting
+      mapper.  Previously, if "Base" had reassigned "base_id"
+      to the name "id", "SubBase(Base)" would still get 
+      an attribute called "base_id".   This could be worked
+      around by explicitly stating the column in each
+      submapper as well but this is fairly unworkable
+      and also impossible when using declarative [ticket:1111].
+    
 - mysql
     - Quoting of MSEnum values for use in CREATE TABLE is now
       optional & will be quoted on demand as required.  (Quoting was
index 7d0bae1da7dec2e78858fd3ea8cd0284a5254eee..dc934b9770f427972a988b738810564ad47294f2 100644 (file)
@@ -380,6 +380,7 @@ class MapperProperty(object):
         """
 
         self.key = key
+        self._compiled = True
         self.do_init()
 
     def do_init(self):
index 3b45b28ee65f49431c510ad4d9b298a3c6df59b0..588bc359d308dfe900f24e1947b716f034d84304 100644 (file)
@@ -386,7 +386,7 @@ class Mapper(object):
         l = [(key, prop) for key, prop in self.__props.iteritems()]
         for key, prop in l:
             self.__log("initialize prop " + key)
-            if getattr(prop, 'key', None) is None:
+            if not getattr(prop, '_compiled', False):
                 prop.init(key, self)
         self.__log("__initialize_properties() complete")
         self.compiled = True
@@ -674,6 +674,12 @@ class Mapper(object):
 
             column_key = (self.column_prefix or '') + column.key
 
+            # adjust the "key" used for this column to that
+            # of the inheriting mapper
+            for mapper in self.iterate_to_root():
+                if column in mapper._columntoproperty:
+                    column_key = mapper._columntoproperty[column].key
+                
             self._compile_property(column_key, column, init=False, setparent=True)
 
         # do a special check for the "discriminiator" column, as it may only be present
@@ -755,13 +761,15 @@ class Mapper(object):
                 self._compile_property(prop.name, ColumnProperty(self.mapped_table.c[key]), init=init, setparent=setparent)
 
         self.__props[key] = prop
-
+        prop.key = key
+        
         if setparent:
             prop.set_parent(self)
 
             if not self.non_primary:
                 self.class_manager.install_descriptor(
                     key, Mapper._CompileOnAttr(self.class_, key))
+                    
         if init:
             prop.init(key, self)
 
index 6dd49208b98e05b198a35faa894bbb8adb3ca24f..831d346e637c242d928a0ca9c7875cf61ca71bd7 100644 (file)
@@ -720,6 +720,8 @@ class OverrideColKeyTest(ORMTest):
         mapper(Base, base)
         mapper(Sub, subtable, inherits=Base)
         
+        # Sub gets a "base_id" property using the "base_id"
+        # column of both tables.
         self.assertEquals(
             class_mapper(Sub).get_property('base_id').columns,
             [base.c.base_id, subtable.c.base_id]
@@ -727,7 +729,8 @@ class OverrideColKeyTest(ORMTest):
 
     def test_override_explicit(self):
         # this pattern is what you see when using declarative
-        # in particular
+        # in particular, here we do a "manual" version of
+        # what we'd like the mapper to do.
         
         class Base(object):
             pass
@@ -738,7 +741,8 @@ class OverrideColKeyTest(ORMTest):
             'id':base.c.base_id
         })
         mapper(Sub, subtable, inherits=Base, properties={
-            # this is required...good luck getting any end users to figure this out
+            # this is the manual way to do it, is not really
+            # possible in declarative
             'id':[base.c.base_id, subtable.c.base_id]
         })
 
@@ -792,11 +796,10 @@ class OverrideColKeyTest(ORMTest):
         # PK col
         assert s2.id == s2.base_id != 15
         
-    @testing.fails_on_everything_except()
     def test_override_implicit(self):
-        # this is how the pattern looks intuitively,
-        # including the intuition of the SQLAlchemy creator,
-        # but unfortunately....zzzt
+        # this is how the pattern looks intuitively when 
+        # using declarative.
+        # fixed as part of [ticket:1111]
         
         class Base(object):
             pass
@@ -810,17 +813,16 @@ class OverrideColKeyTest(ORMTest):
             'id':subtable.c.base_id
         })
         
-        # what in fact happens is that "Sub" gets the column "base_id" mapped
-        # as well.   what *should* happen is, Sub mapper should reconcile
-        # the inherited "id" from Base.  right now Base's "id" is ignored
-        # totally because the same key is present in Sub.
+        # Sub mapper compilation needs to detect that "base.c.base_id"
+        # is renamed in the inherited mapper as "id", even though
+        # it has its own "id" property.  Sub's "id" property 
+        # gets joined normally with the extra column.
         
         self.assertEquals(
             class_mapper(Sub).get_property('id').columns,
             [base.c.base_id, subtable.c.base_id]
         )
         
-        # this fails too
         s1 = Sub()
         s1.id = 10
         sess = create_session()