Please quote previous text above your response to it.  We read English  
top to bottom.

On 6 Jul 2009, at 8:22pm, James Gregurich wrote:

> On Jul 6, 2009, at 3:53 AM, Simon Slavin wrote:
>
>> It should not call DELETE triggers since it never deletes.  It should
>> call either INSERT triggers or UPDATE triggers depending on which one
>> it decides to do.
>>
>> In the meantime, you can do the same thing yourself: instead of
>> calling INSERT OR REPLACE, test to see which one would happen then
>> call either INSERT or UPDATE.  The triggers on both of those
>> combinations will work correctly.

> so you are suggesting that I put an INSERT in a C loop checking for a
> constraint violation failure.

You have pointed out an error I made.  I was thinking that REPLACE  
meant that only one existing row could be replaced.  This is wrong:  
the new row can replace any number of existing rows.  Thank you for  
spotting my error.  The documentation points it out, not quite as  
clearly, in the REPLACE section of

http://www.sqlite.org/lang_conflict.html

So any proper trigger structure would have to call a combination of  
all three types of triggers: INSERT, DELETE and UPDATE.  I can't think  
of a good way to manage this properly.  And that may be why INSERT OR  
REPLACE itself doesn't use triggers correctly: it's too complicated to  
work out which of the existing rows is being REPLACED.  And you can't  
call DELETE triggers instead, because they're intended to stop  
something being deleted, and it might be okay to DELETE this thing if  
you're immediately going to INSERT another row that satisfies the  
requirement.

I can only suggest that you handle the constraints testing yourself,  
in your code.  You will know, from the design of your database,  
whether your new row should be considered a replacement for an  
existing one.  You're going to have to replace your INSERT OR REPLACE  
with your own check for other constraints, and then deciding in your  
own code what commands to execute.  I don't think it will be possible  
to write code to do this properly for an arbitrary database.

>>   Or do the INSERT, allow it to fail if
>> it will, then do the UPDATE.

This previous suggestion of mine won't work at all, given that there's  
no way to tell which of the existing records you think you're updating.

I conclude that INSERT OR REPLACE isn't compatible with triggers, or  
that triggers have to support FOR EACH TRANSACTION as well as ROW and  
STATEMENT, or that INSERT OR REPLACE has to treat a primary key  
conflict differently to some other kind of conflict.  There are  
drawbacks to all three of these.  I can't think of a way to do it that  
suits SQLite's small/neat/obvious design criteria.

Simon.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to