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
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
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
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)
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]
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
'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]
})
# 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
'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()