2013/5/6 Mikael <[email protected]> > 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 > > Ah, and here you conclude this statement's inserted row ID from:
If changed rows is zero or last insert row ID checked before query and after query are the same, then there was no row inserted, so there's no insert it (false/null/etc). Otherwise, use the last insert ID checked last. So this is the test procedure that the following applies to: > 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. > > And would be resolved by this: > > 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 > Brgds > > 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

