[storm] Best way to implement One-to-one relationships?
Mac Ryan
quasipedia at gmail.com
Sun Aug 30 15:17:01 BST 2009
On Sun, 2009-08-30 at 14:00 +0800, James Henstridge wrote:
> On Fri, Aug 28, 2009 at 6:19 PM, Mac Ryan<quasipedia at gmail.com> wrote:
> > On Fri, 2009-08-28 at 10:25 +0800, James Henstridge wrote:
> >> Hi Mac,
> >>
> >> I saw your question on IRC in my scrollback yesterday, but you quit
> >> before I was awake.
> >>
> >> ...
> >>
> >> Hope this helps.
> >>
> >> James.
> >
> > Wow... it's the first time it ever happened to me to be "chased" from IM
> > to ML from somebody wishing to help... I feel like a spoiled brat
> > now! :)
> >
> > Anyhow, thank you for your answer after a 1to1 comparison between the
> > tutorial and my code I came to the same conclusion.
> >
> > Somehow I expected Storm to behave differently (i.e.: introspect the
> > code to the point in which it would have created the object for me "on
> > the fly", (or retrieve it from the store if an existing primary key for
> > the "dependent table" was given). I do not why I believed so... it
> > seemed for me the most logical way to work, but I suppose that since
> > "explicit is better than implicit" it makes more Python-sense to work as
> > it is...
>
> Storm doesn't perform any introspection of your database schema -- it
> only works with the information you provide on the Python side.
>
> And the Reference() type is used for much more than a direct one to
> one relationship (often it is many to one), so automatically creating
> a row in the second table when one is created in the first does not
> make sense from a generic standpoint. In many cases, the Reference
> might be left NULL or linked to an existing object.
>
> For your case, if you always want a row created in the second table
> when you create one in the first table, I'd suggest doing so in the
> __init__() method of the first class. Something like:
>
> class TableA(object):
> _storm_table__ = 'tablea'
> ...
> def __init__(self):
> self.extra_fields = TableB()
>
> That way any TableA row created from Python and added to the store
> will have a matching TableB row.
>
> James.
Thank you James,
I finally decided to create a small one-way adapter (insert only),
modeled on the same syntax I use in other parts of the code, masking the
fact it inserts data in two different tables.
One problem that I came a cross, and that I worked around somehow, but
on which I would like to have some feedback is that if I have tables A
and B and the primary key of B is at the same time the foreign key
coming from A which is an autoincrement integer, Storm throw an
exception (get_identity_insert, NotImplementedError) when I flush the
store. In pseudocode:
class A
id = primary autoincrement
field1 = ...
extrafields = Reference(id, B.id)
class B
id = primary
field2 = ...
a = store.add(A())
a.extrafields = store.add(B())
... #populate here
store.flush()
I actually worked around it in my adapter by keeping the two table
independent at creation time:
a = store.add(A())
... #populate A
store.flush()
b = store.add(B())
b.id = a.id
... #populate B
store.flush()
Yet it seems to me as a clumsy workaround rather than good design, and I
would be happy to hear if there is a better way to avoid the exception.
Many thanks in advance,
Mac.
More information about the storm
mailing list