]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Arrange for sqlite3_last_insert_rowid() to work with virtual tables. (CVS 3259)
authordanielk1977 <danielk1977@noemail.net>
Fri, 16 Jun 2006 06:17:47 +0000 (06:17 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 16 Jun 2006 06:17:47 +0000 (06:17 +0000)
FossilOrigin-Name: afa39a46320e9996a5478ea6e19eb4c2014327ac

manifest
manifest.uuid
src/insert.c
src/sqlite.h.in
src/test8.c
src/test_schema.c
src/vdbe.c
test/vtab1.test

index afabe007b229529c10d5ae6e6dc60293bf328986..bbd3c645e3c52d9332f93d5ae54b2ddbf564e347 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\stype\sin\stest_schema.c.\s(CVS\s3258)
-D 2006-06-15T16:26:45
+C Arrange\sfor\ssqlite3_last_insert_rowid()\sto\swork\swith\svirtual\stables.\s(CVS\s3259)
+D 2006-06-16T06:17:47
 F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -46,7 +46,7 @@ F src/expr.c 78b521337d628b1fd9d87b12dbbe771247aab585
 F src/func.c 01e559893b5e43bea85135ad3e481d86c447942a
 F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
-F src/insert.c eba160c6d7f2c44232ff0f168f7b047e20d6f473
+F src/insert.c 09440829e4fa2b0e11dbde5508b8a291025a745d
 F src/legacy.c fa15d505dd4e45044177ee4d1c6aeaf8c836d390
 F src/loadext.c 676257ae268457e7f03261d8ca0d1e72968a26c8
 F src/main.c 7875e8835539d4f16e8b62fad1dee9bda2091272
@@ -72,7 +72,7 @@ F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
 F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36
-F src/sqlite.h.in 1dc44da025da28a011d11ad1608c11a951047fab
+F src/sqlite.h.in 2fc589cf9b550c5bb8b0bac6414389e2057940d1
 F src/sqlite3ext.h fc8647211af0caa9d8e49ab31624b357c1332380
 F src/sqliteInt.h 5eb64f1dd9a8b237d147962bc57637d87e044ff4
 F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
@@ -84,11 +84,11 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
 F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
 F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
 F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
-F src/test8.c 9579de4645c9b8be3f8de217224bcf9280da9b6a
+F src/test8.c 75d9ef60e12ea8a281ab6cd9643992a5a99b2c6a
 F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
 F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
-F src/test_schema.c 889fde757c78b11538c7e448c392198a1ccc8be3
+F src/test_schema.c 3b9fb30f0fed8297097c9b7bd3df484d0cd5e639
 F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
 F src/test_tclvar.c c52f67fbe06d32804af2ba9a2d7aadfc15f5910c
 F src/tokenize.c 6ebcafa6622839968dda4418a7b6945f277a128f
@@ -97,7 +97,7 @@ F src/update.c 5e638a61102776c0f0333994e18361b40598b44f
 F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
 F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d
 F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
-F src/vdbe.c 4a66e5815c50e7f39454fe75d2e3f342785ea20a
+F src/vdbe.c f17a90ab6c630438394807c4e21c0c1c7731ee4f
 F src/vdbe.h 258b5d1c0aaa72192f09ff0568ce42b383f156fa
 F src/vdbeInt.h 6ccb7eaae76ebd761470f6a035501ff33aa92c20
 F src/vdbeapi.c 6af0e7160af260052a7a4500464221a03dada75f
@@ -291,7 +291,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
 F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
 F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
-F test/vtab1.test 519f360d15b8009845e7957789801807346286ff
+F test/vtab1.test a31c323cf158bf7326b3a4af4156b1bdd98cf8a8
 F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
 F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
 F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
@@ -367,7 +367,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P de8d32ac71a6e113e83b952813424cb3fb5a2e59
-R a9b9717f996b4f699ae87b1b5716d890
+P d65d83d38321258a7bb8c38f4b2657650b0f1033
+R cbf7f69fafe0127b012e719eed74f4d3
 U danielk1977
-Z c802729e8f39cde93a7672cc85fc0701
+Z 33e3dbe7c063b046d5656223c8b15932
index e30ebee8de46ca21a24719bba3e991f3782e0c86..a45225230e89d4a74c38dab64449d87e4de53641 100644 (file)
@@ -1 +1 @@
-d65d83d38321258a7bb8c38f4b2657650b0f1033
\ No newline at end of file
+afa39a46320e9996a5478ea6e19eb4c2014327ac
\ No newline at end of file
index e36417767cf7f83f0e55cc923889e83c8b78075e..efefb2aaee84ee56d0959eee95dd2925234d1267 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.167 2006/06/15 07:29:01 danielk1977 Exp $
+** $Id: insert.c,v 1.168 2006/06/16 06:17:47 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -632,7 +632,7 @@ void sqlite3Insert(
     */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( IsVirtual(pTab) ){
-      sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
+      sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2,
                      (const char*)pTab->pVtab, P3_VTAB);
     }else
 #endif
index 68f3a568bb84ffec074e80653d727149cc80dff6..f210bfa425571fc26377ea576aa610a53799d16c 100644 (file)
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.177 2006/06/15 04:28:13 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.178 2006/06/16 06:17:47 danielk1977 Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -1552,7 +1552,7 @@ struct sqlite3_module {
   int (*xNext)(sqlite3_vtab_cursor*);
   int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
   int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
-  int (*xUpdate)(sqlite3_vtab *pVTab, int, sqlite3_value **apData);
+  int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *);
   int (*xBegin)(sqlite3_vtab *pVTab);
   int (*xSync)(sqlite3_vtab *pVTab);
   int (*xCommit)(sqlite3_vtab *pVTab);
index 847ae20f55b972c1172769790fce7780a1b47fa6..563d2799d03f80bac4d051454cb2092d8b982487 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test8.c,v 1.23 2006/06/15 15:38:42 danielk1977 Exp $
+** $Id: test8.c,v 1.24 2006/06/16 06:17:47 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -512,7 +512,12 @@ static void string_concat(char **pzStr, char *zAppend, int doFree){
 **    NULL       INTEGER    (nCol args)    INSERT (incl. rowid value)
 **
 */
-int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){
+int echoUpdate(
+  sqlite3_vtab *tab, 
+  int nData, 
+  sqlite3_value **apData, 
+  sqlite_int64 *pRowid
+){
   echo_vtab *pVtab = (echo_vtab *)tab;
   sqlite3 *db = pVtab->db;
   int rc = SQLITE_OK;
@@ -557,7 +562,7 @@ int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){
     int ii;
     char *zInsert = 0;
     char *zValues = 0;
-
+  
     zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (", pVtab->zTableName);
     if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){
       bindArgOne = 1;
@@ -602,6 +607,10 @@ int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){
     rc = sqlite3_finalize(pStmt);
   }
 
+  if( pRowid && rc==SQLITE_OK ){
+    *pRowid = sqlite3_last_insert_rowid(db);
+  }
+
   return rc;
 }
 
index e5da4f4d4aaceb62288b0d543fb371cb6b64edf1..9d8a6b1d5f6cd832eaf048c0dd1aaaeccbc3f02f 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test_schema.c,v 1.2 2006/06/15 16:26:45 danielk1977 Exp $
+** $Id: test_schema.c,v 1.3 2006/06/16 06:17:47 danielk1977 Exp $
 */
 
 /* The code in this file defines a sqlite3 module that provides
@@ -301,6 +301,7 @@ static int register_schema_module(
     Tcl_WrongNumArgs(interp, 1, objv, "DB");
     return TCL_ERROR;
   }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   sqlite3_create_module(db, "schema", &schemaModule, 0);
 #endif
index 035dc948789efccc6f095df97d45f077504db263..04413347437a8180d4cfcfc3e628ddf698a28a32 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.561 2006/06/15 07:29:01 danielk1977 Exp $
+** $Id: vdbe.c,v 1.562 2006/06/16 06:17:47 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -3269,6 +3269,10 @@ case OP_NewRowid: {
 ** then rowid is stored for subsequent return by the
 ** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
 **
+** Parameter P3 may point to a string containing the table-name, or
+** may be NULL. If it is not NULL, then the update-hook 
+** (sqlite3.xUpdateCallback) is invoked following a successful insert.
+**
 ** This instruction only works on tables.  The equivalent instruction
 ** for indices is OP_IdxInsert.
 */
@@ -4773,7 +4777,7 @@ case OP_VNoChange: {
 
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VUpdate * P2 P3
+/* Opcode: VUpdate P1 P2 P3
 **
 ** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
 ** This opcode invokes the corresponding xUpdate method. P2 values
@@ -4795,6 +4799,10 @@ case OP_VNoChange: {
 **
 ** If P2==1 then no insert is performed.  argv[0] is the rowid of
 ** a row to delete.
+**
+** P1 is a boolean flag. If it is set to true and the xUpdate call
+** is successful, then the value returned by sqlite3_last_insert_rowid() 
+** is set to the value of the rowid for the row just inserted.
 */
 case OP_VUpdate: {   /* no-push */
   sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
@@ -4806,14 +4814,19 @@ case OP_VUpdate: {   /* no-push */
     rc = SQLITE_ERROR;
   }else{
     int i;
+    sqlite_int64 rowid;
     Mem **apArg = p->apArg;
     Mem *pX = &pTos[1-nArg];
     for(i = 0; i<nArg; i++, pX++){
       apArg[i] = pX->flags ? storeTypeInfo(pX,0), pX : 0;
     }
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
-    rc = pModule->xUpdate(pVtab, nArg, apArg);
+    rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+    if( pOp->p1 && rc==SQLITE_OK ){
+      assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
+      db->lastRowid = rowid;
+    }
   }
   popStack(&pTos, nArg);
   break;
index 647088d5fbc6c40ec31e270e5c487c1c07698039..bc98aba305449c2411256485015352f18a359456 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is creating and dropping virtual tables.
 #
-# $Id: vtab1.test,v 1.17 2006/06/15 10:41:16 danielk1977 Exp $
+# $Id: vtab1.test,v 1.18 2006/06/16 06:17:47 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -31,6 +31,7 @@ ifcapable !vtab {
 # vtab1-4.*: Table scans and ORDER BY clauses.
 # vtab1-5.*: Test queries that include joins. This brings the
 #            sqlite3_index_info.estimatedCost variable into play.
+# vtab1-6.*: Test UPDATE/INSERT/DELETE on vtables.
 #
 # This file uses the "echo" module (see src/test8.c). Refer to comments
 # in that file for the special behaviour of the Tcl $echo_module variable.
@@ -38,7 +39,6 @@ ifcapable !vtab {
 # TODO: 
 #   * How to test the sqlite3_index_constraint_usage.omit field?
 #   * vtab1-5.*
-#   * 
 #
 
 
@@ -487,10 +487,99 @@ foreach stmt [list \
 ] {
   execsql $stmt
   execsql $stmt db2
-  check_echo_table vtab1-6.6.[incr tn]
+  check_echo_table vtab1-6.8.[incr tn]
 }
 
-
 db2 close
+
+#----------------------------------------------------------------------
+# Test cases vtab1-7 tests that the value returned by 
+# sqlite3_last_insert_rowid() is set correctly when rows are inserted
+# into virtual tables.
+do_test vtab1.7-1 {
+  execsql {
+    CREATE TABLE real_abc(a PRIMARY KEY, b, c);
+    CREATE VIRTUAL TABLE echo_abc USING echo(real_abc);
+  }
+} {}
+do_test vtab1.7-2 {
+  execsql {
+    INSERT INTO echo_abc VALUES(1, 2, 3);
+    SELECT last_insert_rowid();
+  }
+} {1}
+do_test vtab1.7-3 {
+  execsql {
+    INSERT INTO echo_abc(rowid) VALUES(31427);
+    SELECT last_insert_rowid();
+  }
+} {31427}
+do_test vtab1.7-4 {
+  execsql {
+    INSERT INTO echo_abc SELECT a||'.v2', b, c FROM echo_abc;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-5 {
+  execsql {
+    SELECT rowid, a, b, c FROM echo_abc
+  }
+} [list 1     1    2  3  \
+        31427 {}   {} {} \
+        31428 1.v2 2  3  \
+        31429 {}  {} {}  \
+]
+
+# Now test that DELETE and UPDATE operations do not modify the value.
+do_test vtab1.7-6 {
+  execsql {
+    UPDATE echo_abc SET c = 5 WHERE b = 2;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-7 {
+  execsql {
+    UPDATE echo_abc SET rowid = 5 WHERE rowid = 1;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-8 {
+  execsql {
+    DELETE FROM echo_abc WHERE b = 2;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-9 {
+  execsql {
+    SELECT rowid, a, b, c FROM echo_abc
+  }
+} [list 31427 {} {} {} \
+        31429 {} {} {} \
+]
+do_test vtab1.7-10 {
+  execsql {
+    DELETE FROM echo_abc WHERE b = 2;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-11 {
+  execsql {
+    SELECT rowid, a, b, c FROM real_abc
+  }
+} [list 31427 {} {} {} \
+        31429 {} {} {} \
+]
+do_test vtab1.7-12 {
+  execsql {
+    DELETE FROM echo_abc;
+    SELECT last_insert_rowid();
+  }
+} {31429}
+do_test vtab1.7-13 {
+  execsql {
+    SELECT rowid, a, b, c FROM real_abc
+  }
+} {}
+
 finish_test