[Zope] Can I capture results from insert in Z SQL methods?

Jim Gallacher jg.lists@sympatico.ca
Sun, 03 Nov 2002 12:30:52 -0500


Hi Skip,


Skip Montanaro wrote:
>     Andrew> This is really a general SQL problem rather than anything to do
>     Andrew> with Zope/ZSQL.
> 
> So ZSQL methods don't provide any special syntactic sugar other than
> <dtml-sqlvar>?
> 
>     Andrew> Then do a select nextval('whatever'); to get the next id which
>     Andrew> can then be used for the inserts.
> 
> Thanks, I'll check it out.  This seems (naively) like it would be a race to
> me though.  Let's say I do this:
> 
>     insert into phone ( ... ) values ( ... );
> 
> The new row in phone got a unique id (I do use the serial type for my
> primary keys).  Now, I need the id that row got to use in another insert.
> If I do something like:
> 
>     insert into contact (
>         ...
>         phone,
>         ...
>     )
>     values (
>         ...
>         (select currval(phone_id_seq)),
>         ...
>     );
> 
> That will get the id of the record I just inserted assuming someone else
> didn't sneak in and insert another row in the phone table before I queried
> phone_id_seq.
> 
> Or were you suggesting I do something like:
> 
>     <some dtml assignment ... select nextval(phone_id_seq); ...>
>     insert into phone (
>         id,
>         ...
>     )
>     values (
>         <value retrieved above>
>         ...
>     );
> 
> If so, how do I capture the value of nextval(...) within the ZSQL method?


I've struggled with the same thing, but never got it work 
satisfactorily. The approach I take is to have a separate ZSQL method 
for each insert and glue them together with a python script.

ZSQL method  nextPhoneId:
select nextval('phone_id_seq') as phone_id;

ZSQL method  nextContactId:
select nextval('contact_id_seq') as contact_id;

ZSQL method insertPhone:
insert into phones (phone_id, phone_number ) values
(<dtml-sqlvar phone_id type=int>,<dtml-sqlvar phone_number type=string>)



Python script:
request = container.REQUEST
response =  request.RESPONSE
contact_id = context.nextContactId()
request.set(contact_id)

phone_id = context.nextPhoneId()
request.set(phone_id)


# call ZSQL method to insert the contact
context.insertContact()
# call ZSQL method to insert the phone
context.insertPhone()
# return the user a page template to view the newly added contact
response.redirect('viewContact?contact_id=%s' % (contact_id))

I've found this works well for me, although you do tend to end up with a 
lot of separate ZSQL methods.

Jim