Hi Günter,

Great, yes that makes sense!

So that solves it.


I was thinking about this and thought there must be some way to do this
already; thank you so much for pointing this out.

This would also open up for picking up several inserted id:s from one query
which is nice.

Thanks,
Mikael

2013/5/7 Hick Gunter <h...@scigames.at>

>  How about calling sqlite3_update_hook()?****
>
> ** **
>
> You will be notified about all UPDATE, INSERT and DELETE operations as
> they occur, with the database, table and rowid affected and in the thread
> executing the statement.****
>
> ** **
>
> If you register a well-behaved function (i.e. that calls the previously
> registered function) these hooks may even be layered…****
>
> ** **
>
> *Von:* Mikael [mailto:mikael.tr...@gmail.com]
> *Gesendet:* Dienstag, 07. Mai 2013 14:15
> *An:* Richard Hipp; Simon Slavin; Hick Gunter; James K. Lowden; General
> Discussion of SQLite Database
> *Betreff:* Re: [sqlite] How do sqlite3_reset_last_insert_rowid() or
> functionalequivalent?****
>
> ** **
>
> Hi,****
>
> ** **
>
> Thanks for your feedback, James.****
>
> ** **
>
> A generalized way of getting if an ID was inserted on the last performed
> query and if so which, is of value for instance when inserting a row into a
> table with an AUTOINCREMENT key e.g.****
>
> ** **
>
> CREATE TABLE t (****
>
>      id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,****
>
>      d  TEXT****
>
> );****
>
> ** **
>
> and then inserting into it, e.g.****
>
> ** **
>
> "INSERT INTO t (d) VALUES (\"a\");" => inserted id: 1****
>
> "INSERT INTO t (d) VALUES (\"a\");" => inserted id: 2****
>
> "INSERT INTO t (d) VALUES (\"b\");" => inserted id: 3****
>
> "INSERT INTO t (d) VALUES (\"b\");" => inserted id: 4****
>
> "INSERT INTO t (d) VALUES (\"c\");" => inserted id: 5****
>
> ** **
>
> This functionality makes a lot of sense in at least certain SQLite
> bindings. In the places where it's not strictly required, it will still
> provide clarity which is valuable in debug, and convenience from being
> dynamic, please see the example use ~15 rows below for this -****
>
> ** **
>
> ** **
>
> So what I'm looking for is a general mechanism for deriving the ID
> inserted for a query. E.g.:****
>
> ** **
>
> "SELECT a FROM b" => none****
>
> ** **
>
> "UPDATE b SET a = c" => none****
>
> ** **
>
> "INSERT IGNORE INTO b (a) VALUES (c)" and the ID was already in there =>
> none****
>
> ** **
>
> "INSERT IGNORE INTO b (a) VALUES (c)" and the ID was not already in there
> => the ID of the inserted row****
>
> ** **
>
> "INSERT INTO b (a) VALUES (c)" => the ID of the inserted row****
>
> ** **
>
> ** **
>
> Thanks to this, a SQLite binding can be achieved which
> dynamically/*automatically* detects not only if it was a readonly or
> non-readonly query, but also within the non-readonly query if it was an
> update or insert, and thus a generalized query mechanism can be devised
> that behaves like:****
>
> ** **
>
> SELECT query  => The query results****
>
> UPDATE query => The number of rows updated****
>
> INSERT query => The ID of the row inserted, or none (by null/false/0/etc.)
> ****
>
> ** **
>
> ** **
>
> This is to create a general abstraction for this purpose. Indeed SQLite
> performs queries, well, at the level of query and, the meaningful work you
> do with SQLite is at the granularity of a query, so it appears reasonable
> to me that there would be a mechanism using which you could retrieve the ID
> of the row inserted by a particular query.****
>
> ** **
>
> A generalized "rows changed by this query" abstraction can be implemented
> as of today, using sqlite3_changes which returns the number of changed rows
> in the *last performed query*, the error reporting (as to check
> sqlite3_changes was set on the last query) and possibly secondarily
> by stmt_readonly .****
>
> ** **
>
> ** **
>
> The problem with checking the ID of the last inserted row is that the
> abstraction for checking it cannot reasonably know that a query is an
> insert;****
>
> ** **
>
> Essentially doing a string match for "INSERT " in the query executed would
> be a leaky abstraction.****
>
> ** **
>
> Getting a copy of SQLite's SQL parser's data could be something, but then
> - this is a bit beyond my current SQLite skills - aren't there mechanisms
> to make INSERT:s indirectly in SQLite, like through a database-stored
> procedure or alike?****
>
> ** **
>
> That would make any abstraction like this leak, because it wouldn't know
> if an INSERT was made during a query, and that knowledge is required as to
> know if sqlite3_last_insert_rowid regards the last inserted ID or not.****
>
> ** **
>
> ** **
>
> ** **
>
> And to illustrate how sqlite3_changes and sqlite3_last_insert_rowid does
> not deliver for automatic query ID retrieval:****
>
> ** **
>
> Using these two, let's define an attempt at a general mechanism for this,
> in pseudocode:****
>
> ** **
>
> var last_rowId_on_last_query = 0;****
>
> function query(query) {****
>
>      lock_mutex();****
>
>      sqlite_perform_query(query);****
>
>      var last_rowId = sqlite_last_rowid();****
>
>      var id_of_this_row = (last_rowId != last_rowId_on_last_query) ?
> last_rowId : null;
>      last_rowId_on_last_query = last_rowId;****
>
>      unlock_mutex();****
>
>      return id_of_this_row;****
>
> }****
>
> ** **
>
> Now, let's set up these two tables****
>
> ** **
>
> CREATE TABLE t1 ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, d TEXT );
> CREATE TABLE t2 ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, d TEXT );
> ****
>
> ** **
>
> and now make some inserts with it! The use of query() above is implied
> here.****
>
> ** **
>
> "INSERT INTO t1 (d) VALUES (\"a\");" => 1    - Correct!****
>
> "INSERT INTO t1 (d) VALUES (\"a\");" => 2    - Correct!****
>
> "INSERT INTO t2 (d) VALUES (\"a\");" => 1    - Correct!****
>
> "INSERT INTO t2 (d) VALUES (\"a\");" => 2    - Correct!****
>
> "INSERT INTO t2 (d) VALUES (\"a\");" => 3    - Correct!****
>
> "INSERT INTO t1 (d) VALUES (\"a\");" => null - Error, abstraction leak,
> ouch!****
>
> ** **
>
> ** **
>
> All of this leakiness would be undone if before a query, the SQLite user
> could reset the sqlite3_last_insert_rowid . By that, the user can just
> check the sqlite3_last_insert_rowid right after the query, and by that
> know that that was .****
>
> ** **
>
> It may be a bit too simplistic if a query inserted several ID:s as you
> pointed out, though at least it's general unlike the present solution, and
> can be made to fit any usecase at least I have in reach, as in SQLite any
> INSERT operation can be performed one row per query with OK-to-great
> performance.****
>
> ** **
>
> ** **
>
> Introduction of a sqlite3_reset_last_insert_rowid would be complimenting
> the current sqlite_int64 sqlite3_last_insert_rowid at sqlite3.c row
> 114023-114028:****
>
> ** **
>
> /*****
>
> ** Return the ROWID of the most recent insert****
>
> */****
>
> SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){****
>
>   return db->lastRowid;****
>
> }****
>
> ** **
>
> with the similar****
>
> ** **
>
> SQLITE_API void sqlite3_reset_last_insert_rowid(sqlite3 *db){****
>
>   db->lastRowid = 0;****
>
> }****
>
> ** **
>
> and then making it export properly.****
>
> ** **
>
> ** **
>
> The reason I address you on this list directly with this is because it
> appears to be of use for SQLite bindings as far as I can see.****
>
> ** **
>
> I agree that keeping the API minimal is a top priority. Though, for
> instance exporting this as a SQL procedure that could be invoked by
> preparing "CALL reset_last_insert_rowid();" and then invoking it, wouldn't
> that be a bit too costly to do on *every* query however small in a
> particular binding?****
>
> ** **
>
> ** **
>
> ** **
>
> If you see any other way to solve this with good performance, please feel
> free to share, I'm just looking for a general way of getting if the last
> query inserted an ID and if so which, it can be implemented any way as long
> as it performs so good it can be included in a general query mechanism in a
> binding.****
>
> ** **
>
> Thanks,****
>
> Mikael****
>
> ** **
>
> 2013/5/7 James K. Lowden <jklow...@schemamania.org>****
>
> On Mon, 6 May 2013 20:55:01 +0300
> Mikael <mikael.tr...@gmail.com> wrote:
>
> > 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****
>
> I don't understand.  The process doing the insert presumably knows
> which data it inserted.  Why not turn around and SELECT the ids for the
> inserted values?  No mutex and no guesswork.
>
> Your process seems to imply that the the inserted values don't
> constitute a key, or that you want to compute the row IDs for
> performance.  Those don't strike me as  sufficient reason to perturb
> the API.
>
> --jkl****
>
>
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@sqlite.org
> 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: h...@scigames.at
>
> 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
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to