customizable polymorphic_on/polymorphic_identity schemes

Issue #1131 resolved
Mike Bayer repo owner created an issue

The orm/inheritance/abc_inheritance test relies upon fold_equivalents to spell out a UNION which builds a polymorphic discriminator column on the fly. This whole use case (i.e., joined table inheritance with no discriminator column) is more easily managed by using regular joined table inheritance, joining to all tables (i.e. with_polymorphic), and using a callable polymorphic_on function which checks for the presence of each joined table in order to determine the type. This is an easy enhancement and makes us compatible with Hibernate's joined table inheritance behavior. the whole fold_equivalents feature which nobody is using anyway can then be removed won't be needed in this case (a nicer fold_equivalents proposed in #1729).

Comments (8)

  1. Mike Bayer reporter

    My current thinking is that this should be in a MapperExtension:

    class MyPolymorphicExtension(MapperExtension):
        def polymorphic_mapper(self, row):
            return {
                     None:class_mapper(DefaultClass),
                     'typeone':class_mapper(SomeClass),    
                     'typetwo':class_mapper(SomeOtherClass)
                    }[row['discriminator'](row['discriminator')]
    

    to support non-discriminator use cases:

    class MyPolymorphicExtension(MapperExtension):
        def polymorphic_mapper(self, mapper, row):
            if 'foobar' in row:
                return class_mapper(FooBarClass)
            elif 'hoho' in row:
                return class_mapper(HohoClass)
            else:
                return class_mapper(DefaultClass)
    

    When this is used, polymorphic_on is not set. The mapper will not auto-populate any discriminator column. that again is up to the user:

    discriminator_to_cls = {
                     None:DefaultClass,
                     'typeone':SomeClass,    
                     'typetwo':SomeOtherClass
                    }
    cls_to_discriminator = dict((v, k) for k, v in discriminator_to_cls.iteritems())
    
    class MyPolymorphicExtension(MapperExtension):
        def before_insert(self, mapper, connection, instance):
            instance.discrminator = cls_to_discriminator[instance.__class__](instance.__class__)
    
        def polymorphic_mapper(self, mapper, row):
            return class_mapper(discriminator_to_cls(row['discriminator']('discriminator')))
    
  2. Mike Bayer reporter

    as mentioned in the email we'd like to move "fold_equivalents" into select() itself. I have added #1729 for that.

  3. Mike Bayer reporter

    current proposal: pass a callable to polymorphic_on():

    polymorphic_on=fn

    row, as well as the adapted row, is passed.

  4. Log in to comment