representing multiple aspects, bitemporal

28 views
Skip to first unread message

sdo...@sistechnology.com

unread,
Mar 15, 2008, 3:45:58 AM3/15/08
to sqlal...@googlegroups.com
hi.
This is somewhat longish and dense post, "what we needed - what we've
invented to represent it - are there other ways??", so be warned.
Also, the examples below are somewhat artificial (in real-life)...

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

Michael Bayer

unread,
Mar 15, 2008, 6:22:23 PM3/15/08
to sqlal...@googlegroups.com

On Mar 15, 2008, at 3:45 AM, sdo...@sistechnology.com wrote:

> 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.

sdo...@sistechnology.com

unread,
Mar 15, 2008, 6:53:06 PM3/15/08
to sqlal...@googlegroups.com
i dont have anything at hand for multiple inheritance, i avoided it
for now, but u can get something like 2 separate hierachies (like 2
differently named copies of that standard Person/Employee/Manager
example, or some of above fictious CarOwner/TruckOwner/whatever) and
try to glue them... looks to me like some composite primary key
consisting of all the ids of the base classes... but this is a wild
guess.

Michael Bayer

unread,
Mar 15, 2008, 7:09:22 PM3/15/08
to sqlal...@googlegroups.com

On Mar 15, 2008, at 3:45 AM, sdo...@sistechnology.com wrote:

>
> 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.

sdo...@sistechnology.com

unread,
Mar 15, 2008, 7:56:29 PM3/15/08
to sqlal...@googlegroups.com
On Sunday 16 March 2008 01:09:22 Michael Bayer wrote:
> On Mar 15, 2008, at 3:45 AM, sdo...@sistechnology.com wrote:
> > 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 ?
>
mmh.
lets have object classes A and B, A.has_many( B).
lets have 2 real-world-objects A1 and A2, and B1 and B2, and
each of these having 2 versions, A1c,A1d; A2c,A2d; B1c,B1d, B2c,B2d.
So, software objects would be these A1c...B2d, the numeric index
representing real-obj-id, and letter-index representing versions.
So initialy A1c has B1c, and A2c has B1c too.

- 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

Reply all
Reply to author
Forward
0 new messages