]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
A better fix for the issue with RETURNING triggers on eponymous
authordrh <>
Fri, 28 Nov 2025 13:04:31 +0000 (13:04 +0000)
committerdrh <>
Fri, 28 Nov 2025 13:04:31 +0000 (13:04 +0000)
virtual tables and SQLITE_SCHEMA errors.

FossilOrigin-Name: 40ddaca3fb752425c26570365a9f31820786d21d043c1c0a4b49746ff9bc0782

manifest
manifest.uuid
src/callback.c
src/hash.c
src/hash.h
src/test_bestindex.c
src/vtab.c
test/bestindexE.test
test/returningfault.test

index a0e4f8759bccf980680cc8ed090a1197df0b4224..f766cd67dc2fba1468545c860da8c6b8b029bbf4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sbuffer\soverread\sin\sfts5\sthat\smight\soccur\swhile\sprocessing\sa\scorrupt\sdb.
-D 2025-11-28T12:36:04.399
+C A\sbetter\sfix\sfor\sthe\sissue\swith\sRETURNING\striggers\son\seponymous\nvirtual\stables\sand\sSQLITE_SCHEMA\serrors.
+D 2025-11-28T13:04:31.843
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -679,7 +679,7 @@ F src/btree.c cb5b8ceb9baa02a63a2f83dec09c4153e1cfbdf9c2adef5c62c26d2160eeb067
 F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
 F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
 F src/build.c 611e07299d72ff04bbcb9e7109183467e30925d203c3e121ef9bb3cf6876289b
-F src/callback.c afa59adfaa483f668260ce69f740c8273dee3e6fee9106846e0499ebdd1ac076
+F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
 F src/carray.c ff6081a31878fc34df8fa1052a9cbf17ddc22652544dcb3e2326886ed1053b55
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
@@ -691,8 +691,8 @@ F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
 F src/func.c 0b802107498048d3dcac0b757720bcb8506507ce02159e213ab8161458eb293b
 F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
-F src/hash.c dff10fa89d4a8280b764df9599b29342ea98cba2b868dccb5dfb3c419841a3f0
-F src/hash.h c5f4a02aaf1dca835a68b51c8b906af265c6ca3d8d53d255e0453f0abce561be
+F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
+F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
@@ -756,7 +756,7 @@ F src/test8.c 206d8f3cc73950d252906656e2646b5de0d580b07187b635fcb3edd8c2c5fbc0
 F src/test9.c df9ddc7db6ef1b8cf745866ee229090779728bcbe660c7f297d3127ab21d92af
 F src/test_autoext.c 14d4bbd3d0bd1eec0f6d16b29e28cf1e2d0b020d454835f0721a5f68121ac10f
 F src/test_backup.c a2bfd90d2ff2511b8635507bdb30fa9b605ade19c16b533066cae3077f5bdb72
-F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
+F src/test_bestindex.c a9428931bec06de830b2630f57a7b1f2711761269f04df62b7aa1affcbce15bb
 F src/test_blob.c 77b994e17f2c87055f44fd96c9a206c5a7155bae2cda2769af60c2f3582f962c
 F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
 F src/test_config.c 18aa596d37de1d5968c439fd58ebf38bc4d9c9d1db63621504e241fde375cecd
@@ -812,7 +812,7 @@ F src/vdbemem.c 48e562ff27e6386eb8613207ac27d3d98c1f67fdc4775a1ab13759d2c2a1c021
 F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
-F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
+F src/vtab.c 5437ce986db2f70e639ce8a3fe68dcdfe64b0f1abb14eaebecdabd5e0766cc68
 F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
 F src/wal.c 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6
 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
@@ -914,7 +914,7 @@ F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572e
 F test/bestindexB.test 328b97b69cd1a20928d5997f9ecb04d2e00f1d18e19ab27f9e9adb44d7bc51ce
 F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
 F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
-F test/bestindexE.test f0c7105d1e7facaa8f5e6c498849cc6dcadd533b35ea9e5e1176e54a9a2d70f1
+F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
 F test/between.test e7587149796101cbe8d5f8abae8d2a7b87f04d8226610aa1091615005dcf4d54
 F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
 F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -1527,7 +1527,7 @@ F test/reservebytes.test 6163640b5a5120c0dee6591481e673a0fa0bf0d12d4da7513bad692
 F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
 F test/returning1.test cd32517148948859db214dd814354597dd40e7489259590fac1a4f7bf44deb97
-F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
+F test/returningfault.test 5f9649d05680357ab077fa6bad574a3eb3f6e4858a6880b25171be516a4efcda
 F test/rollback.test 952c4d805bca96adc2be76f621ea22115fe40b330015af36fcc8028c8547fcee
 F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
 F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
@@ -2171,9 +2171,11 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 0c836387518dee719eaac8992c63da955630ac073a5e4ba4d887160dff42b898
-Q +8b0cbc18be3c6f2501b102757af6be98c48044a296104cca7bce822ac2304515
-R 1c559fa01e2045a73634bbe221e92967
+P 712e31c59254f82e62a19e41d3b6ac15391dd6e9df966cacadfa9ae79415b243
+Q +6a9fdde109865b23888f099d066721404e8b853f3dacd55ce08c8bbda2491ec3
+Q +bf399992cb98e5d5f002a90b521328d5c2f113ebab8601653452d78222077bde
+Q +dc569288dd63754269e14be7a9937c882531685a3e9caec25f86ec8c01eb9583
+R e6faec25512909b375a6de433bcc999d
 U drh
-Z a5ce86195e7ae4027ea13f269316d3e3
+Z 6bdf6810679e96e0bba6c4bccb37d033
 # Remove this line to create a well-formed Fossil manifest.
index 3b055bb81fb997710493f2493e09877c19c55e66..cfd00cb0f36639341c2015af0dd460d99e69a3f2 100644 (file)
@@ -1 +1 @@
-712e31c59254f82e62a19e41d3b6ac15391dd6e9df966cacadfa9ae79415b243
+40ddaca3fb752425c26570365a9f31820786d21d043c1c0a4b49746ff9bc0782
index 9ea3616b383307a88720140f1d8a3c00f36f19c2..e6418097f67744e261751a04ec4badcd178023d8 100644 (file)
@@ -504,17 +504,10 @@ void sqlite3SchemaClear(void *p){
   temp2 = pSchema->trigHash;
   sqlite3HashInit(&pSchema->trigHash);
   sqlite3HashClear(&pSchema->idxHash);
-  for(pElem=sqliteHashFirst(&temp2); pElem; ){
-    HashElem *pNext = sqliteHashNext(pElem);
-    Trigger *pTrig = (Trigger*)sqliteHashData(pElem);
-    if( pTrig->bReturning ){
-      /* Do not remove RETURNING triggers from the temp-triggers hash */
-      sqlite3HashTransfer(&pSchema->trigHash, &temp2, pElem);
-    }else{
-      sqlite3DeleteTrigger(&xdb, pTrig);
-    }
-    pElem = pNext;
+  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
+    sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
   }
+
   sqlite3HashClear(&temp2);
   sqlite3HashInit(&pSchema->tblHash);
   for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
index 670df16d8193f2ab3e24fba58038378eaba7c518..35df65808e8b59a243c318216a69c83d53641fc2 100644 (file)
@@ -271,25 +271,3 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
   return 0;
 }
 
-/*
-** Parameter pElem is currently part of hash table pFrom. Add it to hash 
-** table pTo. 
-**
-** This procedure corrupts hash table pFrom. Specifically, it removes element
-** pElem from the list of all elements in the hash table, but may leave
-** a pointer to it in one of the hash buckets of pFrom. This is not a problem
-** because this function is only called if hash table pFrom will be cleared
-** before any further lookups or inserts are attempted.
-*/
-void sqlite3HashTransfer(Hash *pTo, Hash *pFrom, HashElem *pElem){
-  if( pElem->prev ){
-    pElem->prev->next = pElem->next; 
-  }else{
-    assert( pFrom->first==pElem );
-    pFrom->first = pElem->next;
-  }
-  pTo->count++;
-  insertElement(pTo, pTo->ht ? &pTo->ht[pElem->h % pTo->htsize] : 0, pElem);
-}
-
-
index 4cb1fbe47b08d76adafaae12c66057f4c6425ad3..cff65d6e508717c7b6ac63bf92429e1139bbc265 100644 (file)
@@ -70,7 +70,6 @@ void sqlite3HashInit(Hash*);
 void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
 void *sqlite3HashFind(const Hash*, const char *pKey);
 void sqlite3HashClear(Hash*);
-void sqlite3HashTransfer(Hash*, Hash*, HashElem *pElem);
 
 /*
 ** Macros for looping over all elements of a hash table.  The idiom is
index 2f9203d85ed69c7c63df7aea5306583a8e8194c9..f6b5db0fbe7f85289aa350e7b7110171825a7158 100644 (file)
 typedef struct tcl_vtab tcl_vtab;
 typedef struct tcl_cursor tcl_cursor;
 typedef struct TestFindFunction TestFindFunction;
+typedef struct TestVtabContext TestVtabContext;
 
 /* 
 ** A fs virtual-table object 
@@ -125,6 +126,10 @@ struct TestFindFunction {
   TestFindFunction *pNext;
 };
 
+struct TestVtabContext {
+  Tcl_Interp *interp;
+  Tcl_Obj *pDefault;
+};
 
 /*
 ** Dequote string z in place.
@@ -178,25 +183,33 @@ static int tclConnect(
   sqlite3_vtab **ppVtab,
   char **pzErr
 ){
-  Tcl_Interp *interp = (Tcl_Interp*)pAux;
+  TestVtabContext *pCtx = (TestVtabContext*)pAux;
+  Tcl_Interp *interp = pCtx->interp;
   tcl_vtab *pTab = 0;
   char *zCmd = 0;
   Tcl_Obj *pScript = 0;
   int rc = SQLITE_OK;
 
-  if( argc!=4 ){
+  if( argc!=4 && (argc!=3 || pCtx->pDefault==0) ){
     *pzErr = sqlite3_mprintf("wrong number of arguments");
     return SQLITE_ERROR;
   }
 
-  zCmd = sqlite3_malloc64(strlen(argv[3])+1);
+  if( argc==4 ){
+    zCmd = sqlite3_malloc64(strlen(argv[3])+1);
+  }
   pTab = (tcl_vtab*)sqlite3_malloc64(sizeof(tcl_vtab));
-  if( zCmd && pTab ){
-    memcpy(zCmd, argv[3], strlen(argv[3])+1);
-    tclDequote(zCmd);
+  if( (zCmd || argc==3) && pTab ){
     memset(pTab, 0, sizeof(tcl_vtab));
 
-    pTab->pCmd = Tcl_NewStringObj(zCmd, -1);
+    if( zCmd ){
+      memcpy(zCmd, argv[3], strlen(argv[3])+1);
+      tclDequote(zCmd);
+      pTab->pCmd = Tcl_NewStringObj(zCmd, -1);
+    }else{
+      pTab->pCmd = Tcl_DuplicateObj(pCtx->pDefault);
+    }
+
     pTab->interp = interp;
     pTab->db = db;
     Tcl_IncrRefCount(pTab->pCmd);
@@ -208,7 +221,11 @@ static int tclConnect(
     rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
     if( rc!=TCL_OK ){
       *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp));
-      rc = SQLITE_ERROR;
+      if( sqlite3_stricmp(*pzErr, "database schema has changed")==0 ){
+        rc = SQLITE_SCHEMA;
+      }else{
+        rc = SQLITE_ERROR;
+      }
     }else{
       rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp));
       if( rc!=SQLITE_OK ){
@@ -802,6 +819,39 @@ static int tclFindFunction(
   return iRet;
 }
 
+static int tclUpdate(
+  sqlite3_vtab *tab, 
+  int nArg, 
+  sqlite3_value **apVal, 
+  sqlite3_int64 *piRowid
+){
+  tcl_vtab *pTab = (tcl_vtab*)tab;
+  Tcl_Interp *interp = pTab->interp; 
+  Tcl_Obj *pEval = Tcl_DuplicateObj(pTab->pCmd);
+  Tcl_Obj *pRes = 0;
+  int rc = TCL_OK;
+
+  Tcl_IncrRefCount(pEval);
+  Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj("xUpdate",-1));
+
+  rc = Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL);
+  Tcl_DecrRefCount(pEval);
+
+  if( rc==TCL_OK ){
+    Tcl_Obj *pRes = Tcl_GetObjResult(interp);
+    Tcl_WideInt v;
+    rc = Tcl_GetWideIntFromObj(interp, pRes, &v);
+    *piRowid = (sqlite3_int64)v;
+  }
+
+  if( rc!=TCL_OK ){
+    tab->zErrMsg = sqlite3_mprintf("%s", Tcl_GetStringResult(pTab->interp));
+    return rc;
+  }
+
+  return SQLITE_OK;
+}
+
 /*
 ** A virtual table module that provides read-only access to a
 ** Tcl global variable namespace.
@@ -833,12 +883,47 @@ static sqlite3_module tclModule = {
   0,                           /* xShadowName */
   0                            /* xIntegrity */
 };
+static sqlite3_module tclModuleUpdate = {
+  0,                         /* iVersion */
+  tclConnect,
+  tclConnect,
+  tclBestIndex,
+  tclDisconnect, 
+  tclDisconnect,
+  tclOpen,                      /* xOpen - open a cursor */
+  tclClose,                     /* xClose - close a cursor */
+  tclFilter,                    /* xFilter - configure scan constraints */
+  tclNext,                      /* xNext - advance a cursor */
+  tclEof,                       /* xEof - check for end of scan */
+  tclColumn,                    /* xColumn - read data */
+  tclRowid,                     /* xRowid - read data */
+  tclUpdate,                   /* xUpdate */
+  0,                           /* xBegin */
+  0,                           /* xSync */
+  0,                           /* xCommit */
+  0,                           /* xRollback */
+  tclFindFunction,             /* xFindFunction */
+  0,                           /* xRename */
+  0,                           /* xSavepoint */
+  0,                           /* xRelease */
+  0,                           /* xRollbackTo */
+  0,                           /* xShadowName */
+  0                            /* xIntegrity */
+};
 
 /*
 ** Decode a pointer to an sqlite3 object.
 */
 extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
 
+static void delTestVtabCtx(void *p){
+  TestVtabContext *pCtx = (TestVtabContext*)p;
+  if( pCtx->pDefault ){
+    Tcl_DecrRefCount(pCtx->pDefault);
+  }
+  ckfree(pCtx);
+}
+
 /*
 ** Register the echo virtual table module.
 */
@@ -849,13 +934,25 @@ static int SQLITE_TCLAPI register_tcl_module(
   Tcl_Obj *CONST objv[]  /* Command arguments */
 ){
   sqlite3 *db;
-  if( objc!=2 ){
-    Tcl_WrongNumArgs(interp, 1, objv, "DB");
+  if( objc!=2 && objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB ?DEFAULT-CMD?");
     return TCL_ERROR;
   }
   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  sqlite3_create_module(db, "tcl", &tclModule, (void *)interp);
+  {
+    sqlite3_module *pMod = &tclModule;
+    TestVtabContext *pCtx = (TestVtabContext*)ckalloc(sizeof(TestVtabContext));
+    pCtx->interp = interp;
+    pCtx->pDefault = 0;
+    if( objc==3 ){
+      pCtx->pDefault = objv[2];
+      Tcl_IncrRefCount(pCtx->pDefault);
+    }
+
+    if( objc==3 ){ pMod = &tclModuleUpdate; }
+    sqlite3_create_module_v2(db, "tcl", pMod, (void*)pCtx, delTestVtabCtx);
+  }
 #endif
   return TCL_OK;
 }
index e40f60873a17dc28aecf8dd12d136797ff3651bc..ed4b0afaf40dcca43eb513f71bc9bd3d5445b2d4 100644 (file)
@@ -1279,9 +1279,12 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
   addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
   addModuleArgument(pParse, pTab, 0);
   addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
+  db->nSchemaLock++;
   rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
+  db->nSchemaLock--;
   if( rc ){
     sqlite3ErrorMsg(pParse, "%s", zErr);
+    pParse->rc = rc;
     sqlite3DbFree(db, zErr);
     sqlite3VtabEponymousTableClear(db, pMod);
   }
index 48397fc7b3b6fc7ab2028b470eaa974a69a6c153..d225d74aef6f0633d7000ac4750e20e5866629a6 100644 (file)
@@ -13,7 +13,7 @@
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
-set testprefix bestindex1
+set testprefix bestindexE
 
 ifcapable !vtab {
   finish_test
@@ -124,7 +124,68 @@ do_bestindex_test 2.2 {
   {Customer: oid=?}
 }
 
+#--------------------------------------------------------------------------
+reset_db
+register_tcl_module db eponymous_cmd
 
+proc eponymous_cmd {method args} {
+  switch -- $method {
+    xConnect {
+      db eval { SELECT * FROM sqlite_schema }
+      return "CREATE TABLE t1 (a, b)"
+    }
 
+    xBestIndex {
+      return "idxnum 555"
+    }
+
+    xFilter {
+      return [list sql {SELECT 123, 'A', 'B'}]
+    }
+
+    xUpdate {
+      return 123
+    }
+
+  }
+
+  return {}
+}
+
+do_execsql_test 3.1.0 {
+  PRAGMA table_info = tcl
+} {
+  0 a {} 0 {} 0 1 b {} 0 {} 0
+}
+do_execsql_test 3.1.1 {
+  SELECT rowid, * FROM tcl
+} {123 A B}
+do_execsql_test 3.1.2 {
+  INSERT INTO tcl VALUES('i', 'ii') RETURNING *;
+} {i ii}
+do_test 3.1.3 {
+  db last_insert_rowid
+} {123}
+
+do_execsql_test 3.1.4 {
+  CREATE TABLE x1(x);
+}
+
+db close
+sqlite3 db  test.db
+register_tcl_module db eponymous_cmd
+sqlite3 db2 test.db
+
+# Load the schema into connection [db]
+do_execsql_test 3.2.1 { SELECT * FROM x1 }
+
+# Modify the schema on disk
+do_execsql_test -db db2 3.2.2 { CREATE TABLE x2(x) }
+
+# Insert with RETURNING trigger on eponymous table.
+do_execsql_test 3.2.3 {
+  INSERT INTO tcl VALUES('i', 'ii') RETURNING *;
+} {i ii}
 
 finish_test
+
index 8bf6fbfe06427daff90b4c226725c79684489f8f..b0177e6dc81af99de152879c0d577a2a13f1fb9b 100644 (file)
@@ -14,13 +14,15 @@ set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 source $testdir/malloc_common.tcl
 
+set ::testprefix returningfault
+
 
 do_execsql_test 1.0 {
   CREATE TABLE t1 (b);
 } {}
 faultsim_save_and_close
 
-do_faultsim_test pagerfault-1 -faults oom-t* -prep {
+do_faultsim_test 1 -faults oom-t* -prep {
   faultsim_restore_and_reopen
 } -body {
   execsql { 
@@ -32,5 +34,52 @@ do_faultsim_test pagerfault-1 -faults oom-t* -prep {
   faultsim_test_result {1 {sub-select returns 5 columns - expected 1}}
 }
 
+ifcapable vtab {
+  reset_db
+  do_execsql_test 2.0 {
+    CREATE TABLE t1(x);
+  }
+  proc eponymous_cmd {method args} {
+    switch -- $method {
+      xConnect {
+        db eval { SELECT * FROM sqlite_schema }
+        return "CREATE TABLE t1 (a, b)"
+      }
+  
+      xBestIndex {
+        return "idxnum 555"
+      }
+  
+      xFilter {
+        return [list sql {SELECT 123, 'A', 'B'}]
+      }
+  
+      xUpdate {
+        return 123
+      }
+  
+    }
+  
+    return {}
+  }
+
+  faultsim_save_and_close
+
+  do_faultsim_test 2 -faults oom* -prep {
+    faultsim_restore_and_reopen
+    register_tcl_module db eponymous_cmd
+    db eval { SELECT * FROM t1 }
+    sqlite3 db2 test.db
+    db2 eval { CREATE TABLE t2(y) }
+    db2 close
+  } -body {
+    db eval {
+      INSERT INTO tcl VALUES('hello', 'world') RETURNING *
+    }
+  } -test {
+    faultsim_test_result {0 {hello world}} {1 {vtable constructor failed: tcl}}
+  }
+}
 
 finish_test