[storm] Best way to implement One-to-one relationships?
Jason Baker
jbaker at zeomega.com
Mon Aug 31 14:30:33 BST 2009
On Sun, Aug 30, 2009 at 9:17 AM, Mac Ryan<quasipedia at gmail.com> wrote:
> 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.
>
>
> --
> storm mailing list
> storm at lists.canonical.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/storm
>
Are you using the MySQL backend? Unless I'm missing something, either
the MySQL backend doesn't support this kind of behavior or this is a
bug (ie the identity insert data should have already been filled in
during Connection.execute).
More information about the storm
mailing list