First, we have bi-temporal objects (i.e. with history/versions).
Second, we have 1-to-many relationship like 'Aobj has Bobj'. In
bitemporal, this becomes many-to-many, because Aobj has versions and
Bobj has versions, and in order to be able to 'upgrade' either side
without changing the other, one gets an itermediate table to record
which particular verfsion of Aobj has which particular version of
Bobj (and the operation upgrade-Aold-toAnew copies all previous
records for Aold).
Third, we have many such relationships, each of which representing
some aspect of the objects.
e.g. "has_car", "has_bank_account", "has_color":
- (instances of Person, Company, Factory) has_car (instances of
Car,Truck)
- (instances of Person, Bank, Company) has_bank_account (instances of
BankAccount)
- (instances of Person, Dog, Car) has_color (instances of Color)
Each aspect carries some behavior (i.e. methods) with +it.
------
One way to represent this, in pure OO, might be one common base for
each aspect - CarOwner, BankAccOwner, ColoredOne - as mixin, and then
combining these mixins via multiple inheritance:
class Person( CarOwner, BankAccOwner, ColoredOne): pass
class Bank( BankAccOwner): pass
class Company( CarOwner, BankAccOwner): pass
i'm not sure if this is right way to do it, but it is possible.
on the association side, this would be something like:
BaseAssoc = something.based.on.dbcook.Association
class HasCar_Assoc( BaseAssoc):
car = BaseAssoc.Link( CarType)
owner = BaseAssoc.Link( CarOwner, relname= "hascars")
Now representing all this via ORM into DB... multiple inheritance
doesnt sound to me as right thing, as each inheritance will mean a
common base-table for that aspect, with its own unique sequence, and
then joining multiple of these in one table...
Here Question one: how to represent multiple inheritance in DB?
we've decided to avoid multiple inheritance, at least in DB. Instead,
the intermediate association table for each aspect will do the
polymorphism discriminate/dispatch by itself, having many columns,
each referencing only one subtype of the linked one:
class HasCarAssoc( BaseAssoc):
car = BaseAssoc.Link( CarType)
owner4Person = BaseAssoc.Link( Person , "hascars", nullable=True)
owner4Company = BaseAssoc.Link( Company, "hascars", nullable=True)
owner4Factory = BaseAssoc.Link( Factory, "hascars", nullable=True)
# where only one of the owner4* references is set-up in any record
owner = property( get_owner, set_owner) # something-smart-here
Thus, at least in DB, the things stay separate.
Declaration-wise, theres no change needed to the respective
owner-classes Person Company etc, they would automaticaly "grow" a
hascars relation, although they still may need to have common
(non-DB) aspect-base-class, for the aspect's behaviour - if that
cannot be delegated to the "hascars" thing. This would need some
logic for the polymorhism switching at python level, but overall,
this is not complicating the code too much, maybe because of
separation-of-concerns + dbcook-light-syntax.
so the main question: is this looking insane?
Are there other ways to do it?
if u got to here, Thanks for your time anyway.
ciao
svilen
www.svilendobrev.com
> Thus, at least in DB, the things stay separate.
> Declaration-wise, theres no change needed to the respective
> owner-classes Person Company etc, they would automaticaly "grow" a
> hascars relation, although they still may need to have common
> (non-DB) aspect-base-class, for the aspect's behaviour - if that
> cannot be delegated to the "hascars" thing. This would need some
> logic for the polymorhism switching at python level, but overall,
> this is not complicating the code too much, maybe because of
> separation-of-concerns + dbcook-light-syntax.
>
> so the main question: is this looking insane?
> Are there other ways to do it?
> if u got to here, Thanks for your time anyway.
> ciao
> svilen
> www.svilendobrev.com
show me a schema and I''ll take a crack at how I'd map to it.
multiple inheritance has been mentioned here at Pycon and i believe
there are some relational approaches to it but it does seem complicated.
>
> Second, we have 1-to-many relationship like 'Aobj has Bobj'. In
> bitemporal, this becomes many-to-many, because Aobj has versions and
> Bobj has versions, and in order to be able to 'upgrade' either side
> without changing the other, one gets an itermediate table to record
> which particular verfsion of Aobj has which particular version of
> Bobj (and the operation upgrade-Aold-toAnew copies all previous
> records for Aold).
I actually do not understand whats happening here fully, could you
show an example ?
it seems to me that if you wanted to maintain versions of things, and
relations between things that are independent of the version, every
versioned object would be represented by a "primary" table and a
separate "versions" table with its temporal data. I wouldnt get into
any kind of elaborate manipulation when new versions are created.
Also take a look at what these guys are doing: http://www.pagodacms.org/
theyre using SA to handle a pretty complex versioning idea.
- scenario 1: B1 is changed (into B1d - different version of same
real-obj)
if it is 1-to-many, A1c has to point to new B1d... but that changes
A1c as such. Hence a new A1d is needed... which may have its own
refereees etc... change propagates and generates a lot of mess. in
many2many, the change does not propagate more than the intermediate
table.
- scenario 2: A1 is changed to have B2 instead of B1 (different
real-world obj)
in 1-to-many, this will be a new A1d haveing a copy of the relation
from A1c, with B1c replaced by B2c... but since this is a new A1, all
the Bxx that pointed to A1c, now has to point to A1d... another mess.
> it seems to me that if you wanted to maintain versions of things,
> and relations between things that are independent of the version,
> every versioned object would be represented by a "primary" table
> and a separate "versions" table with its temporal data.
u mean, the primary table would hold just the real-world-ids, and
there would be many records in the other table (versions) per one
real-world-id... hmm, we dont do it in such separate way, our
real-obj-id is only existing bundled in the versions table (but is
generated separately); i'll have a look if it might simplify some
things or not really.
> I wouldnt
> get into any kind of elaborate manipulation when new versions are
> created.
as i said, the relation becomes many2many, and scenario 2 does a copy
of all the records (A1c:Bxx) into (A1d:Bxx), thus not propagating
change any further. this is tested (well, sort of).
> Also take a look at what these guys are doing:
> http://www.pagodacms.org/ theyre using SA to handle a pretty
> complex versioning idea.
hmm. From what i understand, they have versions but they have only one
view - current one - and dont have a need to see how-it-was at any
time back (t1) - and from which time perspective (t2).
But another thing they talk about is multilingual-data; we've also
invented a sort-of mixin to handle that "nicely" (as i see it now,
even 2 diff.ways, both via many2many), but it isn't ready to show
yet... no time to really test it.
Another thing that may be useful to someone - if u remember, once i
was asking about representing hierarchical user-transactions (that
may last days-weeks)... there's also a dbcook.misc entry about that,
near-ready.
Maybe if someone is interested i should publish these in dbcook.misc
in whatever shape they are, and then colaborate...
i was so much hoping that someone would go and use the bitemporal
mixin and find all our mistakes (;-) and/or tidy the awful sql a
bit...
anyway
ciao
svilen
www.svilendobrev.com