]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Modify swarmvtab to use a separate database connection for each database file.
authordan <dan@noemail.net>
Thu, 3 Aug 2017 20:13:00 +0000 (20:13 +0000)
committerdan <dan@noemail.net>
Thu, 3 Aug 2017 20:13:00 +0000 (20:13 +0000)
FossilOrigin-Name: 1f05ad29c3a540408470da7f8111f1319f961539c1a96b1a81abf1423af90f15

ext/misc/unionvtab.c
manifest
manifest.uuid
test/swarmvtab.test

index 208c576eabfde44c1b26e81ceef4f2027d54eb50..243152b2617045b07b17156945e34d2bdd3e21e8 100644 (file)
@@ -84,8 +84,9 @@ struct UnionSrc {
 
   /* Fields used by swarmvtab only */
   char *zFile;                    /* File to ATTACH */
-  int bAttached;                  /* True if currently attached */
-  UnionSrc *pNextAttached;        /* Next in list of all attached sources */
+  int nUser;                      /* Current number of users */
+  sqlite3 *db;                    /* Database handle */
+  UnionSrc *pNextClosable;        /* Next in list of closable sources */
 };
 
 /*
@@ -97,14 +98,13 @@ struct UnionTab {
   int bSwarm;                     /* 1 for "swarmvtab", 0 for "unionvtab" */
   int iPK;                        /* INTEGER PRIMARY KEY column, or -1 */
   int nSrc;                       /* Number of elements in the aSrc[] array */
-  sqlite3_stmt *pSourceStr;       /* Used by unionSourceToStr() */
   UnionSrc *aSrc;                 /* Array of source tables, sorted by rowid */
 
   /* Used by swarmvtab only */
   char *zSourceStr;               /* Expected unionSourceToStr() value */
-  UnionSrc *pAttached;            /* First in list of attached sources */
-  int nAttach;                    /* Current number of attached sources */
-  int nMaxAttach;                 /* Maximum number of attached sources */
+  UnionSrc *pClosable;            /* First in list of closable sources */
+  int nOpen;                      /* Current number of open sources */
+  int nMaxOpen;                   /* Maximum number of open sources */
 };
 
 /*
@@ -119,6 +119,8 @@ struct UnionCsr {
   int iTab;                       /* Index of table read by pStmt */
 };
 
+#define unionGetDb(pTab, pSrc) ((pTab)->bSwarm ? (pSrc)->db : (pTab)->db)
+
 /*
 ** If *pRc is other than SQLITE_OK when this function is called, it
 ** always returns NULL. Otherwise, it attempts to allocate and return
@@ -284,33 +286,37 @@ static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
 ** SQLITE_OK when this function is called, then it is set to the
 ** value returned by sqlite3_finalize() before this function exits.
 */
-static void unionFinalize(int *pRc, sqlite3_stmt *pStmt){
+static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
+  sqlite3 *db = sqlite3_db_handle(pStmt);
   int rc = sqlite3_finalize(pStmt);
-  if( *pRc==SQLITE_OK ) *pRc = rc;
+  if( *pRc==SQLITE_OK ){
+    *pRc = rc;
+    if( rc ){
+      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+    }
+  }
 }
 
-static int unionDetachDatabase(UnionTab *pTab, char **pzErr){
-  sqlite3_stmt *pStmt = 0;
+/*
+** Close one database from the closable list.
+*/
+static int unionCloseDatabase(UnionTab *pTab, char **pzErr){
   int rc = SQLITE_OK;
   UnionSrc **pp;
-  assert( pTab->pAttached );
 
-  pp = &pTab->pAttached;
-  while( (*pp)->pNextAttached ){
-    pp = &(*pp)->pNextAttached;
-  }
+  assert( pTab->pClosable && pTab->bSwarm );
 
-  pStmt = unionPreparePrintf(&rc, pzErr, pTab->db, "DETACH %s", (*pp)->zDb);
-  if( rc==SQLITE_OK ) sqlite3_step(pStmt);
-  unionFinalize(&rc, pStmt);
-  assert( rc==SQLITE_OK );
-  if( rc==SQLITE_OK ){
-    assert( (*pp)->bAttached && (*pp)->pNextAttached==0 );
-    (*pp)->bAttached = 0;
-    *pp = 0;
-    pTab->nAttach--;
+  pp = &pTab->pClosable;
+  while( (*pp)->pNextClosable ){
+    pp = &(*pp)->pNextClosable;
   }
 
+  assert( (*pp)->db );
+  rc = sqlite3_close((*pp)->db);
+  (*pp)->db = 0;
+  *pp = 0;
+  pTab->nOpen--;
+
   return rc;
 }
 
@@ -322,14 +328,12 @@ static int unionDisconnect(sqlite3_vtab *pVtab){
     UnionTab *pTab = (UnionTab*)pVtab;
     int i;
     for(i=0; i<pTab->nSrc; i++){
-      sqlite3_free(pTab->aSrc[i].zDb);
-      sqlite3_free(pTab->aSrc[i].zTab);
-      sqlite3_free(pTab->aSrc[i].zFile);
-    }
-    while( pTab->pAttached ){
-      if( unionDetachDatabase(pTab, 0)!=SQLITE_OK ) break;
+      UnionSrc *pSrc = &pTab->aSrc[i];
+      sqlite3_free(pSrc->zDb);
+      sqlite3_free(pSrc->zTab);
+      sqlite3_free(pSrc->zFile);
+      sqlite3_close(pSrc->db);
     }
-    sqlite3_finalize(pTab->pSourceStr);
     sqlite3_free(pTab->zSourceStr);
     sqlite3_free(pTab->aSrc);
     sqlite3_free(pTab);
@@ -394,21 +398,20 @@ static char *unionSourceToStr(
 ){
   char *zRet = 0;
   if( *pRc==SQLITE_OK ){
-    int rc = unionIsIntkeyTable(pTab->db, pSrc, pzErr);
-    if( rc==SQLITE_OK && pTab->pSourceStr==0 ){
-      pTab->pSourceStr = unionPrepare(&rc, pTab->db, 
-        "SELECT group_concat(quote(name) || '.' || quote(type)) "
-        "FROM pragma_table_info(?, ?)", pzErr
-      );
-    }
+    sqlite3 *db = unionGetDb(pTab, pSrc);
+    int rc = unionIsIntkeyTable(db, pSrc, pzErr);
     if( rc==SQLITE_OK ){
-      sqlite3_bind_text(pTab->pSourceStr, 1, pSrc->zTab, -1, SQLITE_STATIC);
-      sqlite3_bind_text(pTab->pSourceStr, 2, pSrc->zDb, -1, SQLITE_STATIC);
-      if( SQLITE_ROW==sqlite3_step(pTab->pSourceStr) ){
-        const char *z = (const char*)sqlite3_column_text(pTab->pSourceStr, 0);
+      sqlite3_stmt *pStmt = unionPrepare(&rc, db, 
+          "SELECT group_concat(quote(name) || '.' || quote(type)) "
+          "FROM pragma_table_info(?, ?)", pzErr
+      );
+      sqlite3_bind_text(pStmt, 1, pSrc->zTab, -1, SQLITE_STATIC);
+      sqlite3_bind_text(pStmt, 2, pSrc->zDb, -1, SQLITE_STATIC);
+      if( SQLITE_ROW==sqlite3_step(pStmt) ){
+        const char *z = (const char*)sqlite3_column_text(pStmt, 0);
         zRet = unionStrdup(&rc, z);
       }
-      unionReset(&rc, pTab->pSourceStr, pzErr);
+      unionFinalize(&rc, pStmt, pzErr);
     }
     *pRc = rc;
   }
@@ -426,77 +429,117 @@ static char *unionSourceToStr(
 */
 static int unionSourceCheck(UnionTab *pTab, char **pzErr){
   int rc = SQLITE_OK;
+  char *z0 = 0;
+  int i;
 
   assert( *pzErr==0 );
-  if( pTab->nSrc==0 ){
-    *pzErr = sqlite3_mprintf("no source tables configured");
-    rc = SQLITE_ERROR;
-  }else{
-    char *z0 = 0;
-    int i;
-
-    z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr);
-    for(i=1; i<pTab->nSrc; i++){
-      char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr);
-      if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
-        *pzErr = sqlite3_mprintf("source table schema mismatch");
-        rc = SQLITE_ERROR;
-      }
-      sqlite3_free(z);
+  z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr);
+  for(i=1; i<pTab->nSrc; i++){
+    char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr);
+    if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
+      *pzErr = sqlite3_mprintf("source table schema mismatch");
+      rc = SQLITE_ERROR;
     }
-
-    unionFinalize(&rc, pTab->pSourceStr);
-    pTab->pSourceStr = 0;
-    sqlite3_free(z0);
+    sqlite3_free(z);
   }
+  sqlite3_free(z0);
+
   return rc;
 }
 
-static int unionAttachDatabase(UnionTab *pTab, int iSrc, char **pzErr){
+static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
   int rc = SQLITE_OK;
   UnionSrc *pSrc = &pTab->aSrc[iSrc];
 
   assert( pTab->bSwarm && iSrc<pTab->nSrc );
-  if( pSrc->bAttached==0 ){
-    sqlite3_stmt *pStmt;
-
-    if( pTab->nAttach>=pTab->nMaxAttach ){
-      rc = unionDetachDatabase(pTab, pzErr);
+  if( pSrc->db==0 ){
+    while( rc==SQLITE_OK && pTab->pClosable && pTab->nOpen>=pTab->nMaxOpen ){
+      rc = unionCloseDatabase(pTab, pzErr);
     }
 
-    pStmt = unionPreparePrintf(
-        &rc, pzErr, pTab->db, "ATTACH %Q AS %s", pSrc->zFile, pSrc->zDb
-    );
     if( rc==SQLITE_OK ){
-      sqlite3_step(pStmt);
-      rc = sqlite3_finalize(pStmt);
-    }
-    if( rc!=SQLITE_OK ){
-      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
-    }else{
-      char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr);
-      if( rc==SQLITE_OK ){
-        if( pTab->zSourceStr==0 ){
-          pTab->zSourceStr = z;
-        }else{
-          if( sqlite3_stricmp(z, pTab->zSourceStr) ){
-            *pzErr = sqlite3_mprintf("source table schema mismatch");
-            rc = SQLITE_ERROR;
+      rc = sqlite3_open(pSrc->zFile, &pSrc->db);
+      if( rc!=SQLITE_OK ){
+        *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pSrc->db));
+      }else{
+        char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr);
+        if( rc==SQLITE_OK ){
+          if( pTab->zSourceStr==0 ){
+            pTab->zSourceStr = z;
+          }else{
+            if( sqlite3_stricmp(z, pTab->zSourceStr) ){
+              *pzErr = sqlite3_mprintf("source table schema mismatch");
+              rc = SQLITE_ERROR;
+            }
+            sqlite3_free(z);
           }
-          sqlite3_free(z);
         }
       }
+
+      if( rc==SQLITE_OK ){
+        pSrc->pNextClosable = pTab->pClosable;
+        pTab->pClosable = pSrc;
+        pTab->nOpen++;
+      }else{
+        sqlite3_close(pSrc->db);
+        pSrc->db = 0;
+      }
     }
+  }
+
+  return rc;
+}
+
 
-    pSrc->pNextAttached = pTab->pAttached;
-    pSrc->bAttached = 1;
-    pTab->pAttached = pSrc;
-    pTab->nAttach++;
+/*
+** This function is a no-op for unionvtab tables. For swarmvtab, increment 
+** the reference count for source table iTab. If the reference count was
+** zero before it was incremented, also remove the source from the closable
+** list.
+*/
+static void unionIncrRefcount(UnionTab *pTab, int iTab){
+  if( pTab->bSwarm ){
+    UnionSrc *pSrc = &pTab->aSrc[iTab];
+    assert( pSrc->nUser>=0 && pSrc->db );
+    if( pSrc->nUser==0 ){
+      UnionSrc **pp;
+      for(pp=&pTab->pClosable; *pp!=pSrc; pp=&(*pp)->pNextClosable);
+      *pp = pSrc->pNextClosable;
+      pSrc->pNextClosable = 0;
+    }
+    pSrc->nUser++;
   }
+}
 
+/*
+** Finalize the SQL statement pCsr->pStmt and return the result.
+**
+** If this is a swarmvtab table (not unionvtab) and pCsr->pStmt was not
+** NULL when this function was called, also decrement the reference
+** count on the associated source table. If this means the source tables
+** refcount is now zero, add it to the closable list.
+*/
+static int unionFinalizeCsrStmt(UnionCsr *pCsr){
+  int rc = SQLITE_OK;
+  if( pCsr->pStmt ){
+    UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
+    UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
+    rc = sqlite3_finalize(pCsr->pStmt);
+    pCsr->pStmt = 0;
+    if( pTab->bSwarm ){
+      pSrc->nUser--;
+      assert( pSrc->nUser>=0 );
+      if( pSrc->nUser==0 ){
+        pSrc->pNextClosable = pTab->pClosable;
+        pTab->pClosable = pSrc;
+      }
+    }
+  }
   return rc;
 }
 
+
+
 /* 
 ** xConnect/xCreate method.
 **
@@ -518,7 +561,6 @@ static int unionConnect(
   int rc = SQLITE_OK;
   int bSwarm = (pAux==0 ? 0 : 1);
   const char *zVtab = (bSwarm ? "swarmvtab" : "unionvtab");
-  const char *zName = argv[2];
 
   if( sqlite3_stricmp("temp", argv[1]) ){
     /* unionvtab tables may only be created in the temp schema */
@@ -582,15 +624,12 @@ static int unionConnect(
         pSrc->iMax = iMax;
         if( bSwarm ){
           pSrc->zFile = unionStrdup(&rc, zDb);
-          pSrc->zDb = sqlite3_mprintf("swm_%s_%d", zName, pTab->nSrc);
-          if( pSrc->zDb==0 ) rc = SQLITE_NOMEM;
         }else{
           pSrc->zDb = unionStrdup(&rc, zDb);
-          pSrc->bAttached = 1;
         }
       }
     }
-    unionFinalize(&rc, pStmt);
+    unionFinalize(&rc, pStmt, pzErr);
     pStmt = 0;
 
     /* It is an error if the SELECT statement returned zero rows. If only
@@ -607,9 +646,9 @@ static int unionConnect(
     if( rc==SQLITE_OK ){
       pTab->db = db;
       pTab->bSwarm = bSwarm;
-      pTab->nMaxAttach = SWARMVTAB_MAX_ATTACHED;
+      pTab->nMaxOpen = SWARMVTAB_MAX_ATTACHED;
       if( bSwarm ){
-        rc = unionAttachDatabase(pTab, 0, pzErr);
+        rc = unionOpenDatabase(pTab, 0, pzErr);
       }else{
         rc = unionSourceCheck(pTab, pzErr);
       }
@@ -617,13 +656,15 @@ static int unionConnect(
 
     /* Compose a CREATE TABLE statement and pass it to declare_vtab() */
     if( rc==SQLITE_OK ){
-      pStmt = unionPreparePrintf(&rc, pzErr, db, "SELECT "
+      UnionSrc *pSrc = &pTab->aSrc[0];
+      sqlite3 *tdb = unionGetDb(pTab, pSrc);
+      pStmt = unionPreparePrintf(&rc, pzErr, tdb, "SELECT "
           "'CREATE TABLE xyz('"
           "    || group_concat(quote(name) || ' ' || type, ', ')"
           "    || ')',"
           "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
           "FROM pragma_table_info(%Q, ?)", 
-          pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
+          pSrc->zTab, pSrc->zDb
       );
     }
     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
@@ -632,7 +673,7 @@ static int unionConnect(
       pTab->iPK = sqlite3_column_int(pStmt, 1);
     }
 
-    unionFinalize(&rc, pStmt);
+    unionFinalize(&rc, pStmt, pzErr);
   }
 
   if( rc!=SQLITE_OK ){
@@ -662,7 +703,7 @@ static int unionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
 */
 static int unionClose(sqlite3_vtab_cursor *cur){
   UnionCsr *pCsr = (UnionCsr*)cur;
-  sqlite3_finalize(pCsr->pStmt);
+  unionFinalizeCsrStmt(pCsr);
   sqlite3_free(pCsr);
   return SQLITE_OK;
 }
@@ -676,22 +717,27 @@ static int doUnionNext(UnionCsr *pCsr){
   assert( pCsr->pStmt );
   if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){
     UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
-    rc = sqlite3_finalize(pCsr->pStmt);
-    pCsr->pStmt = 0;
+    rc = unionFinalizeCsrStmt(pCsr);
     if( rc==SQLITE_OK && pTab->bSwarm ){
       pCsr->iTab++;
       if( pCsr->iTab<pTab->nSrc ){
         UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
         if( pCsr->iMaxRowid>=pSrc->iMin ){
           /* It is necessary to scan the next table. */
-          rc = unionAttachDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
-          pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pTab->db,
-              "SELECT rowid, * FROM %Q.%Q %s %lld",
-              pSrc->zDb, pSrc->zTab,
+          sqlite3 *db;
+          rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
+          db = unionGetDb(pTab, pSrc);
+          pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, db,
+              "SELECT rowid, * FROM %Q %s %lld",
+              pSrc->zTab,
               (pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "),
               pCsr->iMaxRowid
           );
-          if( rc==SQLITE_OK ) rc = SQLITE_ROW;
+          if( rc==SQLITE_OK ){
+            assert( pCsr->pStmt );
+            unionIncrRefcount(pTab, pCsr->iTab);
+            rc = SQLITE_ROW;
+          }
         }
       }
     }
@@ -797,8 +843,7 @@ static int unionFilter(
     }
   }
 
-  sqlite3_finalize(pCsr->pStmt);
-  pCsr->pStmt = 0;
+  unionFinalizeCsrStmt(pCsr);
   if( bZero ){
     return SQLITE_OK;
   }
@@ -838,15 +883,22 @@ static int unionFilter(
     if( pTab->bSwarm ){
       pCsr->iTab = i;
       pCsr->iMaxRowid = iMax;
-      rc = unionAttachDatabase(pTab, i, &pTab->base.zErrMsg);
+      rc = unionOpenDatabase(pTab, i, &pTab->base.zErrMsg);
       break;
     }
   }
 
 
-  if( zSql==0 ) return rc;
-  pCsr->pStmt = unionPrepare(&rc, pTab->db, zSql, &pTab->base.zErrMsg);
-  sqlite3_free(zSql);
+  if( zSql==0 ){
+    return rc;
+  }else{
+    sqlite3 *db = unionGetDb(pTab, &pTab->aSrc[pCsr->iTab]);
+    pCsr->pStmt = unionPrepare(&rc, db, zSql, &pTab->base.zErrMsg);
+    if( pCsr->pStmt ){
+      unionIncrRefcount(pTab, pCsr->iTab);
+    }
+    sqlite3_free(zSql);
+  }
   if( rc!=SQLITE_OK ) return rc;
   return unionNext(pVtabCursor);
 }
index e4cae44b96238a712abf26ca4cbb90b9866aa366..d6345db7a7819fef991a4834528f81f0c22b72eb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthe\scode\sin\sunionvtab.c\sto\salso\sprovide\sthe\s"swarmvtab"\svirtual\stable\nmodule.\sThere\sare\sstill\sseveral\sproblems\son\sthis\sbranch.
-D 2017-08-02T19:59:56.307
+C Modify\sswarmvtab\sto\suse\sa\sseparate\sdatabase\sconnection\sfor\seach\sdatabase\sfile.
+D 2017-08-03T20:13:00.017
 F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
@@ -281,7 +281,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
 F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
 F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c f9acc9c3e78e48171bd72735f08948585104b811546cee02d012cbd481432665
+F ext/misc/unionvtab.c 96add94bbccd52227e1b8c73457aee563f6da099aa77060a6d95737c00fe3cfa
 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
 F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
 F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
@@ -1231,7 +1231,7 @@ F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
 F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
 F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
-F test/swarmvtab.test 49dc94deb7363a375a980e9d52815533138e3046a4a21d5eb1c312552d408033
+F test/swarmvtab.test c12cda41c77dc3cee58a0f73721817894c6202cc61ce44af2c5d2131e232fa11
 F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
 F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
 F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
@@ -1641,10 +1641,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 527974d4caba8bce7c89a28ea04a573b14c558657c14d9ad3c64bf1e0884caf8
-R 31849be59b061a67f41a14392566e88f
-T *branch * union-vtab
-T *sym-union-vtab *
-T -sym-trunk *
+P 03d94388d62fd0f1fae377d273bbd5561208adc34bd97f7ce27783b30a369fd7
+R 625b97c97a5f8dd3636fd589eae8ca8e
 U dan
-Z 1bdb6d432069947ff558a9e41aa801b1
+Z 0d29a0f09a9580a6cb1bdb3e0e661b27
index f82310988f08cb9b6757f97a44cf5cdda92e681f..854ef35d5fdc4696ca71c3f107add013cb575425 100644 (file)
@@ -1 +1 @@
-03d94388d62fd0f1fae377d273bbd5561208adc34bd97f7ce27783b30a369fd7
\ No newline at end of file
+1f05ad29c3a540408470da7f8111f1319f961539c1a96b1a81abf1423af90f15
\ No newline at end of file
index c9b89a1df5b0905dd8f6e3160e3785238a431bf9..7486088073ad8d19ef0df1255ab774aa2416910d 100644 (file)
@@ -23,6 +23,8 @@ ifcapable !vtab {
 
 load_static_extension db unionvtab
 
+set nFile $sqlite_open_file_count
+
 do_execsql_test 1.0 {
   CREATE TABLE t0(a INTEGER PRIMARY KEY, b TEXT);
   WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<400) 
@@ -48,14 +50,12 @@ do_test 1.1 {
 
   execsql {
     CREATE VIRTUAL TABLE temp.s1 USING swarmvtab('SELECT * FROM dir');
-    SELECT count(*) FROM pragma_database_list;
   }
-} {3}
+} {}
 
 do_execsql_test 1.2 { 
   DROP TABLE s1; 
-  SELECT name FROM pragma_database_list;
-} {main temp}
+} {}
 
 do_execsql_test 1.3 {
   CREATE VIRTUAL TABLE temp.s1 USING swarmvtab('SELECT * FROM dir');
@@ -66,7 +66,7 @@ proc do_compare_test {tn where} {
   set sql [subst {
     SELECT (
         SELECT group_concat(a || ',' || b, ',') FROM t0 WHERE $where
-    )==(
+    ) IS (
         SELECT group_concat(a || ',' || b, ',') FROM s1 WHERE $where
     )
   }]
@@ -78,13 +78,17 @@ do_compare_test 1.4 "rowid = 55"
 do_compare_test 1.5 "rowid BETWEEN 20 AND 100"
 do_compare_test 1.6 "rowid > 350"
 do_compare_test 1.7 "rowid >= 350"
+do_compare_test 1.8 "rowid >= 200"
+do_compare_test 1.9 "1"
+do_compare_test 1.10 "rowid = 700"
+do_compare_test 1.11 "rowid = -1"
+do_compare_test 1.12 "rowid = 0"
 
-# The following both each an assert() in SQLite:
-#
-#do_compare_test 1.8 "rowid >= 200"
-#do_test 1.x { db close } {}
-#
-do_execsql_test 1.x { DROP TABLE s1 }
+do_test 1.x {
+  set sqlite_open_file_count
+} [expr $nFile+9]
+
+do_test 1.y { db close } {}
 
 
 finish_test