aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/unionvtab.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2017-08-04 17:39:13 +0000
committerdan <dan@noemail.net>2017-08-04 17:39:13 +0000
commitd83e082524d56d8138ef84c7ff0fa02c0c6172dc (patch)
tree5e756a9d9bcb52f40d51ca05d319f09741b738e6 /ext/misc/unionvtab.c
parent0ff2217035501f00d1c3137016721f0c5a5da106 (diff)
downloadsqlite-d83e082524d56d8138ef84c7ff0fa02c0c6172dc.tar.gz
sqlite-d83e082524d56d8138ef84c7ff0fa02c0c6172dc.zip
Add further test cases for swarmvtab. And minor code changes.
FossilOrigin-Name: 0f82d3b9dd5bd2e34a984c78e4a4a87921cf3e15b01b611133378c0ea9901010
Diffstat (limited to 'ext/misc/unionvtab.c')
-rw-r--r--ext/misc/unionvtab.c106
1 files changed, 59 insertions, 47 deletions
diff --git a/ext/misc/unionvtab.c b/ext/misc/unionvtab.c
index 2df3c30e0..c4e3fff03 100644
--- a/ext/misc/unionvtab.c
+++ b/ext/misc/unionvtab.c
@@ -85,6 +85,23 @@ SQLITE_EXTENSION_INIT1
#endif
/*
+** The following is also copied from sqliteInt.h. To facilitate coverage
+** testing.
+*/
+#ifndef ALWAYS
+# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define ALWAYS(X) (1)
+# define NEVER(X) (0)
+# elif !defined(NDEBUG)
+# define ALWAYS(X) ((X)?1:(assert(0),0))
+# define NEVER(X) ((X)?(assert(0),1):0)
+# else
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
+# endif
+#endif
+
+/*
** The swarmvtab module attempts to keep the number of open database files
** at or below this limit. This may not be possible if there are too many
** simultaneous queries.
@@ -211,7 +228,7 @@ static void unionDequote(char *z){
int iIn = 1;
int iOut = 0;
if( q=='[' ) q = ']';
- while( z[iIn] ){
+ while( ALWAYS(z[iIn]) ){
if( z[iIn]==q ){
if( z[iIn+1]!=q ){
/* Character iIn was the close quote. */
@@ -253,9 +270,10 @@ static sqlite3_stmt *unionPrepare(
char **pzErr /* OUT: Error message */
){
sqlite3_stmt *pRet = 0;
+ assert( pzErr );
if( *pRc==SQLITE_OK ){
int rc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
- if( rc!=SQLITE_OK && pzErr ){
+ if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("sql error: %s", sqlite3_errmsg(db));
*pRc = rc;
}
@@ -301,6 +319,7 @@ static sqlite3_stmt *unionPreparePrintf(
** In this case, *pzErr may be set to point to an error message
** buffer allocated by sqlite3_malloc().
*/
+#if 0
static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
int rc = sqlite3_reset(pStmt);
if( *pRc==SQLITE_OK ){
@@ -310,6 +329,7 @@ static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
}
}
}
+#endif
/*
** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to
@@ -332,20 +352,16 @@ static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
** close open database files until at most nMax are open. An SQLite error
** code is returned if an error occurs, or SQLITE_OK otherwise.
*/
-static int unionCloseSources(UnionTab *pTab, int nMax){
- int rc = SQLITE_OK;
- if( pTab->bSwarm ){
- while( rc==SQLITE_OK && pTab->pClosable && pTab->nOpen>nMax ){
- UnionSrc **pp;
- for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
- assert( (*pp)->db );
- rc = sqlite3_close((*pp)->db);
- (*pp)->db = 0;
- *pp = 0;
- pTab->nOpen--;
- }
+static void unionCloseSources(UnionTab *pTab, int nMax){
+ while( pTab->pClosable && pTab->nOpen>nMax ){
+ UnionSrc **pp;
+ for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
+ assert( (*pp)->db );
+ sqlite3_close((*pp)->db);
+ (*pp)->db = 0;
+ *pp = 0;
+ pTab->nOpen--;
}
- return rc;
}
/*
@@ -428,11 +444,11 @@ static char *unionSourceToStr(
if( *pRc==SQLITE_OK ){
sqlite3 *db = unionGetDb(pTab, pSrc);
int rc = unionIsIntkeyTable(db, pSrc, pzErr);
+ sqlite3_stmt *pStmt = unionPrepare(&rc, db,
+ "SELECT group_concat(quote(name) || '.' || quote(type)) "
+ "FROM pragma_table_info(?, ?)", pzErr
+ );
if( rc==SQLITE_OK ){
- 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) ){
@@ -496,35 +512,32 @@ static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
assert( pTab->bSwarm && iSrc<pTab->nSrc );
if( pSrc->db==0 ){
- rc = unionCloseSources(pTab, pTab->nMaxOpen-1);
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, SQLITE_OPEN_READONLY, 0);
- 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);
+ unionCloseSources(pTab, pTab->nMaxOpen-1);
+ rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, SQLITE_OPEN_READONLY, 0);
+ 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);
}
}
+ }
- if( rc==SQLITE_OK ){
- pSrc->pNextClosable = pTab->pClosable;
- pTab->pClosable = pSrc;
- pTab->nOpen++;
- }else{
- sqlite3_close(pSrc->db);
- pSrc->db = 0;
- }
+ if( rc==SQLITE_OK ){
+ pSrc->pNextClosable = pTab->pClosable;
+ pTab->pClosable = pSrc;
+ pTab->nOpen++;
+ }else{
+ sqlite3_close(pSrc->db);
+ pSrc->db = 0;
}
}
@@ -574,6 +587,7 @@ static int unionFinalizeCsrStmt(UnionCsr *pCsr){
pSrc->pNextClosable = pTab->pClosable;
pTab->pClosable = pSrc;
}
+ unionCloseSources(pTab, pTab->nMaxOpen);
}
}
return rc;
@@ -763,10 +777,8 @@ static int doUnionNext(UnionCsr *pCsr){
UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
if( pCsr->iMaxRowid>=pSrc->iMin ){
/* It is necessary to scan the next table. */
- sqlite3 *db;
rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
- db = unionGetDb(pTab, pSrc);
- pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, db,
+ pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pSrc->db,
"SELECT rowid, * FROM %Q %s %lld",
pSrc->zTab,
(pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "),