Dear Simon, Günter and list,

The issue goes like this:

Currently in the absence of a sqlite3_reset_last_insert_rowid(), the
closest you can do to figure out what ID was actually inserted by the most
recent SQLite query is:

 * Lock mutex

 * Get sqlite*'s last insert row ID

 * Perform the query

 * Get number of changed rows

 * Get sqlite*'s last insert row ID

 * Unlock mutex


But this test leaks crazily much!

If either of the following holds true, you're in Wild Bugs land!

 * This query was made as an INSERT to one table, and the last query was
made as an INSERT to another table, and both yielded the same ID

 * This query was an UPDATE, so it gave a change count but did not actually
generate a new ID



Probably there's much more cases, though this is enough to show that the
above method is absolutely undesirable and a perpetual source of bugs for
use  general method for retrieving a query's insert id.


What do you say about a sqlite3_reset_last_insert_rowid() as to enable
SQLite with this?

It has a zero performance overhead on present code, and the binary addition
should be in the range 50 bytes.

Best regards

2013/5/6 Hick Gunter <[email protected]>

> I use a separate SQLite connection for each thread to avoid such issues.
>
> When does the "last inserted rowid" become obsolete?
> In your example, do you mean to imply that the last inserted rowid may be
> retrieved once and once only?
>
> Why not just:
>
> (lock mutex)
> (execute query)
> if sqlite3_changes() ** may still be 0, see below
> then
>         rowid = sqlite3_last_insert_rowid()
> else
>         rowid = undefined
> (unlock mutex)
>
> What about if the query creates more than 1 row (as in INSERT INTO ...
> SELECT or even multiple VALUES tuples)? Why would you want to know only the
> last rowid and not all of them?
>
> If you need to count changes made by triggers and foreign keys you may
> need to:
>
> (lock mutex)
> Before = sqlite_total_changes
> (execute query)
> After = sqlite_total_changes
> If (Before < After)
> ...
> (unlock mutex)
>
> Also note that INSERT OR IGNORE does not change the last inserted rowid.
>
> I also suspect that INSERT OR REPLACE may very well change the last
> inserted rowid (without tallying sqlite3_changes!!! See documentation).
>
> -----Ursprüngliche Nachricht-----
> Von: Mikael [mailto:[email protected]]
> Gesendet: Montag, 06. Mai 2013 14:40
> An: Richard Hipp; [email protected]
> Betreff: [sqlite] How do sqlite3_reset_last_insert_rowid() or functional
> equivalent?
>
> Dear list,
>
> After having made an SQLite statement the ID of a newly inserted row can
> be retrieved with sqlite3_last_insert_rowid .
>
> It'd be a great thing to be able to produce a general mechanism for
> retrieving this value with regard to the most recently performed query only
> right after a query has been made, as programming aimed at getting this
> value lazily won't work as other local code may have made another query to
> the SQLite handle meanwhile.
>
> The most robust way to do this would be through having a
> sqlite3_reset_last_insert_rowid() procedure to invoke right before a query,
> because, sqlite3_last_insert_rowid is only updated on a successful insert.
>
> The code to check if a query is non-readonly can be done using
> sqlite3_stmt_readonly , but then the step from there to check if it's an
> *insert* and not only that but a successful insert, is a huge step and
> possibly the only reliable way to tell this, would be by SQLite telling it,
> and the most straightforward way for it to do this would be through
> sqlite3_last_insert_rowid , so then what about un-problematizing that value
> as to guarantee it won't return any obsolete value, by introducing a
> sqlite3_reset_last_insert_rowid() ?
>
> Please let me know the best practice for solving this particular problem -
> the ability to make a "Query" abstraction atop SQLite, that has its very
> own "ID of row inserted" method, I believe is a reasonable aim.
>
> (I.e., not having such a property but that is not guaranteed to actually
> contain the right thing, depending on very specific circumstances.)
>
> Example:
>
> (mutex for sqlite3 lock)
> sqlite3_reset_last_insert_rowid(sqlite3*);
> (perform SQLite query on sqlite3*)
> sqlite3_last_insert_rowid(sqlite3*) => Guaranteedly returns the rowid of
> any row inserted by the query, or 0 if no insert was done.
> (mutex for sqlite3 unlock)
> [starting here sqlite3_last_insert_rowid(sqlite3)'s return value is
> undefined]
>
>
>
> Thanks,
> Mikael
> _______________________________________________
> sqlite-users mailing list
> [email protected]
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
>
>
> --------------------------------------------------------------------------
>  Gunter Hick
> Software Engineer
> Scientific Games International GmbH
> Klitschgasse 2 – 4, A - 1130 Vienna, Austria
> FN 157284 a, HG Wien
> Tel: +43 1 80100 0
> E-Mail: [email protected]
>
> This e-mail is confidential and may well also be legally privileged. If
> you have received it in error, you are on notice as to its status and
> accordingly please notify us immediately by reply e-mail and then delete
> this message from your system. Please do not copy it or use it for any
> purposes, or disclose its contents to any person as to do so could be a
> breach of confidence. Thank you for your cooperation.
> _______________________________________________
> sqlite-users mailing list
> [email protected]
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to