1 /*
2 ** 2017 July 15
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** This file contains the implementation of the "unionvtab" and "swarmvtab"
14 ** virtual tables. These modules provide read-only access to multiple tables,
15 ** possibly in multiple database files, via a single database object.
16 ** The source tables must have the following characteristics:
17 **
18 **   * They must all be rowid tables (not VIRTUAL or WITHOUT ROWID
19 **     tables or views).
20 **
21 **   * Each table must have the same set of columns, declared in
22 **     the same order and with the same declared types.
23 **
24 **   * The tables must not feature a user-defined column named "_rowid_".
25 **
26 **   * Each table must contain a distinct range of rowid values.
27 **
28 ** The difference between the two virtual table modules is that for
29 ** "unionvtab", all source tables must be located in the main database or
30 ** in databases ATTACHed to the main database by the user. For "swarmvtab",
31 ** the tables may be located in any database file on disk. The "swarmvtab"
32 ** implementation takes care of opening and closing database files
33 ** automatically.
34 **
35 ** UNIONVTAB
36 **
37 **   A "unionvtab" virtual table is created as follows:
38 **
39 **     CREATE VIRTUAL TABLE <name> USING unionvtab(<sql-statement>);
40 **
41 **   The implementation evalutes <sql statement> whenever a unionvtab virtual
42 **   table is created or opened. It should return one row for each source
43 **   database table. The four columns required of each row are:
44 **
45 **     1. The name of the database containing the table ("main" or "temp" or
46 **        the name of an attached database). Or NULL to indicate that all
47 **        databases should be searched for the table in the usual fashion.
48 **
49 **     2. The name of the database table.
50 **
51 **     3. The smallest rowid in the range of rowids that may be stored in the
52 **        database table (an integer).
53 **
54 **     4. The largest rowid in the range of rowids that may be stored in the
55 **        database table (an integer).
56 **
57 ** SWARMVTAB
58 **
59 **  LEGACY SYNTAX:
60 **
61 **   A "swarmvtab" virtual table is created similarly to a unionvtab table:
62 **
63 **     CREATE VIRTUAL TABLE <name>
64 **      USING swarmvtab(<sql-statement>, <callback>);
65 **
66 **   The difference is that for a swarmvtab table, the first column returned
67 **   by the <sql statement> must return a path or URI that can be used to open
68 **   the database file containing the source table.  The <callback> option
69 **   is optional.  If included, it is the name of an application-defined
70 **   SQL function that is invoked with the URI of the file, if the file
71 **   does not already exist on disk when required by swarmvtab.
72 **
73 **  NEW SYNTAX:
74 **
75 **   Using the new syntax, a swarmvtab table is created with:
76 **
77 **      CREATE VIRTUAL TABLE <name> USING swarmvtab(
78 **        <sql-statement> [, <options>]
79 **      );
80 **
81 **   where valid <options> are:
82 **
83 **      missing=<udf-function-name>
84 **      openclose=<udf-function-name>
85 **      maxopen=<integer>
86 **      <sql-parameter>=<text-value>
87 **
88 **   The <sql-statement> must return the same 4 columns as for a swarmvtab
89 **   table in legacy mode. However, it may also return a 5th column - the
90 **   "context" column. The text value returned in this column is not used
91 **   at all by the swarmvtab implementation, except that it is passed as
92 **   an additional argument to the two UDF functions that may be invoked
93 **   (see below).
94 **
95 **   The "missing" option, if present, specifies the name of an SQL UDF
96 **   function to be invoked if a database file is not already present on
97 **   disk when required by swarmvtab. If the <sql-statement> did not provide
98 **   a context column, it is invoked as:
99 **
100 **     SELECT <missing-udf>(<database filename/uri>);
101 **
102 **   Or, if there was a context column:
103 **
104 **     SELECT <missing-udf>(<database filename/uri>, <context>);
105 **
106 **   The "openclose" option may also specify a UDF function. This function
107 **   is invoked right before swarmvtab opens a database, and right after
108 **   it closes one. The first argument - or first two arguments, if
109 **   <sql-statement> supplied the context column - is the same as for
110 **   the "missing" UDF. Following this, the UDF is passed integer value
111 **   0 before a db is opened, and 1 right after it is closed. If both
112 **   a missing and openclose UDF is supplied, the application should expect
113 **   the following sequence of calls (for a single database):
114 **
115 **      SELECT <openclose-udf>(<db filename>, <context>, 0);
116 **      if( db not already on disk ){
117 **          SELECT <missing-udf>(<db filename>, <context>);
118 **      }
119 **      ... swarmvtab uses database ...
120 **      SELECT <openclose-udf>(<db filename>, <context>, 1);
121 **
122 **   The "maxopen" option is used to configure the maximum number of
123 **   database files swarmvtab will hold open simultaneously (default 9).
124 **
125 **   If an option name begins with a ":" character, then it is assumed
126 **   to be an SQL parameter. In this case, the specified text value is
127 **   bound to the same variable of the <sql-statement> before it is
128 **   executed. It is an error of the named SQL parameter does not exist.
129 **   For example:
130 **
131 **     CREATE VIRTUAL TABLE swarm USING swarmvtab(
132 **       'SELECT :path || localfile, tbl, min, max FROM swarmdir',
133 **       :path='/home/user/databases/'
134 **       missing='missing_func'
135 **     );
136 */
137 
138 #include "sqlite3ext.h"
139 SQLITE_EXTENSION_INIT1
140 #include <assert.h>
141 #include <string.h>
142 #include <stdlib.h>
143 
144 #ifndef SQLITE_OMIT_VIRTUALTABLE
145 
146 /*
147 ** Largest and smallest possible 64-bit signed integers. These macros
148 ** copied from sqliteInt.h.
149 */
150 #ifndef LARGEST_INT64
151 # define LARGEST_INT64  (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
152 #endif
153 #ifndef SMALLEST_INT64
154 # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
155 #endif
156 
157 /*
158 ** The following is also copied from sqliteInt.h. To facilitate coverage
159 ** testing.
160 */
161 #ifndef ALWAYS
162 # if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
163 #  define ALWAYS(X)      (1)
164 #  define NEVER(X)       (0)
165 # elif !defined(NDEBUG)
166 #  define ALWAYS(X)      ((X)?1:(assert(0),0))
167 #  define NEVER(X)       ((X)?(assert(0),1):0)
168 # else
169 #  define ALWAYS(X)      (X)
170 #  define NEVER(X)       (X)
171 # endif
172 #endif
173 
174 /*
175 ** The swarmvtab module attempts to keep the number of open database files
176 ** at or below this limit. This may not be possible if there are too many
177 ** simultaneous queries.
178 */
179 #define SWARMVTAB_MAX_OPEN 9
180 
181 typedef struct UnionCsr UnionCsr;
182 typedef struct UnionTab UnionTab;
183 typedef struct UnionSrc UnionSrc;
184 
185 /*
186 ** Each source table (row returned by the initialization query) is
187 ** represented by an instance of the following structure stored in the
188 ** UnionTab.aSrc[] array.
189 */
190 struct UnionSrc {
191   char *zDb;                      /* Database containing source table */
192   char *zTab;                     /* Source table name */
193   sqlite3_int64 iMin;             /* Minimum rowid */
194   sqlite3_int64 iMax;             /* Maximum rowid */
195 
196   /* Fields used by swarmvtab only */
197   char *zFile;                    /* Database file containing table zTab */
198   char *zContext;                 /* Context string, if any */
199   int nUser;                      /* Current number of users */
200   sqlite3 *db;                    /* Database handle */
201   UnionSrc *pNextClosable;        /* Next in list of closable sources */
202 };
203 
204 /*
205 ** Virtual table  type for union vtab.
206 */
207 struct UnionTab {
208   sqlite3_vtab base;              /* Base class - must be first */
209   sqlite3 *db;                    /* Database handle */
210   int bSwarm;                     /* 1 for "swarmvtab", 0 for "unionvtab" */
211   int iPK;                        /* INTEGER PRIMARY KEY column, or -1 */
212   int nSrc;                       /* Number of elements in the aSrc[] array */
213   UnionSrc *aSrc;                 /* Array of source tables, sorted by rowid */
214 
215   /* Used by swarmvtab only */
216   int bHasContext;                /* Has context strings */
217   char *zSourceStr;               /* Expected unionSourceToStr() value */
218   sqlite3_stmt *pNotFound;        /* UDF to invoke if file not found on open */
219   sqlite3_stmt *pOpenClose;       /* UDF to invoke on open and close */
220 
221   UnionSrc *pClosable;            /* First in list of closable sources */
222   int nOpen;                      /* Current number of open sources */
223   int nMaxOpen;                   /* Maximum number of open sources */
224 };
225 
226 /*
227 ** Virtual table cursor type for union vtab.
228 */
229 struct UnionCsr {
230   sqlite3_vtab_cursor base;       /* Base class - must be first */
231   sqlite3_stmt *pStmt;            /* SQL statement to run */
232 
233   /* Used by swarmvtab only */
234   sqlite3_int64 iMaxRowid;        /* Last rowid to visit */
235   int iTab;                       /* Index of table read by pStmt */
236 };
237 
238 /*
239 ** Given UnionTab table pTab and UnionSrc object pSrc, return the database
240 ** handle that should be used to access the table identified by pSrc. This
241 ** is the main db handle for "unionvtab" tables, or the source-specific
242 ** handle for "swarmvtab".
243 */
244 #define unionGetDb(pTab, pSrc) ((pTab)->bSwarm ? (pSrc)->db : (pTab)->db)
245 
246 /*
247 ** If *pRc is other than SQLITE_OK when this function is called, it
248 ** always returns NULL. Otherwise, it attempts to allocate and return
249 ** a pointer to nByte bytes of zeroed memory. If the memory allocation
250 ** is attempted but fails, NULL is returned and *pRc is set to
251 ** SQLITE_NOMEM.
252 */
unionMalloc(int * pRc,sqlite3_int64 nByte)253 static void *unionMalloc(int *pRc, sqlite3_int64 nByte){
254   void *pRet;
255   assert( nByte>0 );
256   if( *pRc==SQLITE_OK ){
257     pRet = sqlite3_malloc64(nByte);
258     if( pRet ){
259       memset(pRet, 0, (size_t)nByte);
260     }else{
261       *pRc = SQLITE_NOMEM;
262     }
263   }else{
264     pRet = 0;
265   }
266   return pRet;
267 }
268 
269 /*
270 ** If *pRc is other than SQLITE_OK when this function is called, it
271 ** always returns NULL. Otherwise, it attempts to allocate and return
272 ** a copy of the nul-terminated string passed as the second argument.
273 ** If the allocation is attempted but fails, NULL is returned and *pRc is
274 ** set to SQLITE_NOMEM.
275 */
unionStrdup(int * pRc,const char * zIn)276 static char *unionStrdup(int *pRc, const char *zIn){
277   char *zRet = 0;
278   if( zIn ){
279     sqlite3_int64 nByte = strlen(zIn) + 1;
280     zRet = unionMalloc(pRc, nByte);
281     if( zRet ){
282       memcpy(zRet, zIn, (size_t)nByte);
283     }
284   }
285   return zRet;
286 }
287 
288 /*
289 ** If the first character of the string passed as the only argument to this
290 ** function is one of the 4 that may be used as an open quote character
291 ** in SQL, this function assumes that the input is a well-formed quoted SQL
292 ** string. In this case the string is dequoted in place.
293 **
294 ** If the first character of the input is not an open quote, then this
295 ** function is a no-op.
296 */
unionDequote(char * z)297 static void unionDequote(char *z){
298   if( z ){
299     char q = z[0];
300 
301     /* Set stack variable q to the close-quote character */
302     if( q=='[' || q=='\'' || q=='"' || q=='`' ){
303       int iIn = 1;
304       int iOut = 0;
305       if( q=='[' ) q = ']';
306       while( ALWAYS(z[iIn]) ){
307         if( z[iIn]==q ){
308           if( z[iIn+1]!=q ){
309             /* Character iIn was the close quote. */
310             iIn++;
311             break;
312           }else{
313             /* Character iIn and iIn+1 form an escaped quote character. Skip
314             ** the input cursor past both and copy a single quote character
315             ** to the output buffer. */
316             iIn += 2;
317             z[iOut++] = q;
318           }
319         }else{
320           z[iOut++] = z[iIn++];
321         }
322       }
323       z[iOut] = '\0';
324     }
325   }
326 }
327 
328 /*
329 ** This function is a no-op if *pRc is set to other than SQLITE_OK when it
330 ** is called. NULL is returned in this case.
331 **
332 ** Otherwise, the SQL statement passed as the third argument is prepared
333 ** against the database handle passed as the second. If the statement is
334 ** successfully prepared, a pointer to the new statement handle is
335 ** returned. It is the responsibility of the caller to eventually free the
336 ** statement by calling sqlite3_finalize(). Alternatively, if statement
337 ** compilation fails, NULL is returned, *pRc is set to an SQLite error
338 ** code and *pzErr may be set to an error message buffer allocated by
339 ** sqlite3_malloc().
340 */
unionPrepare(int * pRc,sqlite3 * db,const char * zSql,char ** pzErr)341 static sqlite3_stmt *unionPrepare(
342   int *pRc,                       /* IN/OUT: Error code */
343   sqlite3 *db,                    /* Database handle */
344   const char *zSql,               /* SQL statement to prepare */
345   char **pzErr                    /* OUT: Error message */
346 ){
347   sqlite3_stmt *pRet = 0;
348   assert( pzErr );
349   if( *pRc==SQLITE_OK ){
350     int rc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
351     if( rc!=SQLITE_OK ){
352       *pzErr = sqlite3_mprintf("sql error: %s", sqlite3_errmsg(db));
353       *pRc = rc;
354     }
355   }
356   return pRet;
357 }
358 
359 /*
360 ** Like unionPrepare(), except prepare the results of vprintf(zFmt, ...)
361 ** instead of a constant SQL string.
362 */
unionPreparePrintf(int * pRc,char ** pzErr,sqlite3 * db,const char * zFmt,...)363 static sqlite3_stmt *unionPreparePrintf(
364   int *pRc,                       /* IN/OUT: Error code */
365   char **pzErr,                   /* OUT: Error message */
366   sqlite3 *db,                    /* Database handle */
367   const char *zFmt,               /* printf() format string */
368   ...                             /* Trailing printf args */
369 ){
370   sqlite3_stmt *pRet = 0;
371   char *zSql;
372   va_list ap;
373   va_start(ap, zFmt);
374 
375   zSql = sqlite3_vmprintf(zFmt, ap);
376   if( *pRc==SQLITE_OK ){
377     if( zSql==0 ){
378       *pRc = SQLITE_NOMEM;
379     }else{
380       pRet = unionPrepare(pRc, db, zSql, pzErr);
381     }
382   }
383   sqlite3_free(zSql);
384 
385   va_end(ap);
386   return pRet;
387 }
388 
389 
390 /*
391 ** Call sqlite3_reset() on SQL statement pStmt. If *pRc is set to
392 ** SQLITE_OK when this function is called, then it is set to the
393 ** value returned by sqlite3_reset() before this function exits.
394 ** In this case, *pzErr may be set to point to an error message
395 ** buffer allocated by sqlite3_malloc().
396 */
397 #if 0
398 static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
399   int rc = sqlite3_reset(pStmt);
400   if( *pRc==SQLITE_OK ){
401     *pRc = rc;
402     if( rc ){
403       *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt)));
404     }
405   }
406 }
407 #endif
408 
409 /*
410 ** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to
411 ** SQLITE_OK when this function is called, then it is set to the
412 ** value returned by sqlite3_finalize() before this function exits.
413 */
unionFinalize(int * pRc,sqlite3_stmt * pStmt,char ** pzErr)414 static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
415   sqlite3 *db = sqlite3_db_handle(pStmt);
416   int rc = sqlite3_finalize(pStmt);
417   if( *pRc==SQLITE_OK ){
418     *pRc = rc;
419     if( rc ){
420       *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
421     }
422   }
423 }
424 
425 /*
426 ** If an "openclose" UDF was supplied when this virtual table was created,
427 ** invoke it now. The first argument passed is the name of the database
428 ** file for source pSrc. The second is integer value bClose.
429 **
430 ** If successful, return SQLITE_OK. Otherwise an SQLite error code. In this
431 ** case if argument pzErr is not NULL, also set (*pzErr) to an English
432 ** language error message. The caller is responsible for eventually freeing
433 ** any error message using sqlite3_free().
434 */
unionInvokeOpenClose(UnionTab * pTab,UnionSrc * pSrc,int bClose,char ** pzErr)435 static int unionInvokeOpenClose(
436   UnionTab *pTab,
437   UnionSrc *pSrc,
438   int bClose,
439   char **pzErr
440 ){
441   int rc = SQLITE_OK;
442   if( pTab->pOpenClose ){
443     sqlite3_bind_text(pTab->pOpenClose, 1, pSrc->zFile, -1, SQLITE_STATIC);
444     if( pTab->bHasContext ){
445       sqlite3_bind_text(pTab->pOpenClose, 2, pSrc->zContext, -1, SQLITE_STATIC);
446     }
447     sqlite3_bind_int(pTab->pOpenClose, 2+pTab->bHasContext, bClose);
448     sqlite3_step(pTab->pOpenClose);
449     if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pOpenClose)) ){
450       if( pzErr ){
451         *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
452       }
453     }
454   }
455   return rc;
456 }
457 
458 /*
459 ** This function is a no-op for unionvtab. For swarmvtab, it attempts to
460 ** close open database files until at most nMax are open. An SQLite error
461 ** code is returned if an error occurs, or SQLITE_OK otherwise.
462 */
unionCloseSources(UnionTab * pTab,int nMax)463 static void unionCloseSources(UnionTab *pTab, int nMax){
464   while( pTab->pClosable && pTab->nOpen>nMax ){
465     UnionSrc *p;
466     UnionSrc **pp;
467     for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
468     p = *pp;
469     assert( p->db );
470     sqlite3_close(p->db);
471     p->db = 0;
472     *pp = 0;
473     pTab->nOpen--;
474     unionInvokeOpenClose(pTab, p, 1, 0);
475   }
476 }
477 
478 /*
479 ** xDisconnect method.
480 */
unionDisconnect(sqlite3_vtab * pVtab)481 static int unionDisconnect(sqlite3_vtab *pVtab){
482   if( pVtab ){
483     UnionTab *pTab = (UnionTab*)pVtab;
484     int i;
485     for(i=0; i<pTab->nSrc; i++){
486       UnionSrc *pSrc = &pTab->aSrc[i];
487       int bHaveSrcDb = (pSrc->db!=0);
488       sqlite3_close(pSrc->db);
489       if( bHaveSrcDb ){
490         unionInvokeOpenClose(pTab, pSrc, 1, 0);
491       }
492       sqlite3_free(pSrc->zDb);
493       sqlite3_free(pSrc->zTab);
494       sqlite3_free(pSrc->zFile);
495       sqlite3_free(pSrc->zContext);
496     }
497     sqlite3_finalize(pTab->pNotFound);
498     sqlite3_finalize(pTab->pOpenClose);
499     sqlite3_free(pTab->zSourceStr);
500     sqlite3_free(pTab->aSrc);
501     sqlite3_free(pTab);
502   }
503   return SQLITE_OK;
504 }
505 
506 /*
507 ** Check that the table identified by pSrc is a rowid table. If not,
508 ** return SQLITE_ERROR and set (*pzErr) to point to an English language
509 ** error message. If the table is a rowid table and no error occurs,
510 ** return SQLITE_OK and leave (*pzErr) unmodified.
511 */
unionIsIntkeyTable(sqlite3 * db,UnionSrc * pSrc,char ** pzErr)512 static int unionIsIntkeyTable(
513   sqlite3 *db,                    /* Database handle */
514   UnionSrc *pSrc,                 /* Source table to test */
515   char **pzErr                    /* OUT: Error message */
516 ){
517   int bPk = 0;
518   const char *zType = 0;
519   int rc;
520 
521   sqlite3_table_column_metadata(
522       db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
523   );
524   rc = sqlite3_errcode(db);
525   if( rc==SQLITE_ERROR
526    || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
527   ){
528     rc = SQLITE_ERROR;
529     *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
530         (pSrc->zDb ? pSrc->zDb : ""),
531         (pSrc->zDb ? "." : ""),
532         pSrc->zTab
533     );
534   }
535   return rc;
536 }
537 
538 /*
539 ** This function is a no-op if *pRc is other than SQLITE_OK when it is
540 ** called. In this case it returns NULL.
541 **
542 ** Otherwise, this function checks that the source table passed as the
543 ** second argument (a) exists, (b) is not a view and (c) has a column
544 ** named "_rowid_" of type "integer" that is the primary key.
545 ** If this is not the case, *pRc is set to SQLITE_ERROR and NULL is
546 ** returned.
547 **
548 ** Finally, if the source table passes the checks above, a nul-terminated
549 ** string describing the column names and types belonging to the source
550 ** table is returned. Tables with the same set of column names and types
551 ** cause this function to return identical strings. Is is the responsibility
552 ** of the caller to free the returned string using sqlite3_free() when
553 ** it is no longer required.
554 */
unionSourceToStr(int * pRc,UnionTab * pTab,UnionSrc * pSrc,char ** pzErr)555 static char *unionSourceToStr(
556   int *pRc,                       /* IN/OUT: Error code */
557   UnionTab *pTab,                 /* Virtual table object */
558   UnionSrc *pSrc,                 /* Source table to test */
559   char **pzErr                    /* OUT: Error message */
560 ){
561   char *zRet = 0;
562   if( *pRc==SQLITE_OK ){
563     sqlite3 *db = unionGetDb(pTab, pSrc);
564     int rc = unionIsIntkeyTable(db, pSrc, pzErr);
565     sqlite3_stmt *pStmt = unionPrepare(&rc, db,
566         "SELECT group_concat(quote(name) || '.' || quote(type)) "
567         "FROM pragma_table_info(?, ?)", pzErr
568     );
569     if( rc==SQLITE_OK ){
570       sqlite3_bind_text(pStmt, 1, pSrc->zTab, -1, SQLITE_STATIC);
571       sqlite3_bind_text(pStmt, 2, pSrc->zDb, -1, SQLITE_STATIC);
572       if( SQLITE_ROW==sqlite3_step(pStmt) ){
573         const char *z = (const char*)sqlite3_column_text(pStmt, 0);
574         zRet = unionStrdup(&rc, z);
575       }
576       unionFinalize(&rc, pStmt, pzErr);
577     }
578     *pRc = rc;
579   }
580 
581   return zRet;
582 }
583 
584 /*
585 ** Check that all configured source tables exist and have the same column
586 ** names and datatypes. If this is not the case, or if some other error
587 ** occurs, return an SQLite error code. In this case *pzErr may be set
588 ** to point to an error message buffer allocated by sqlite3_mprintf().
589 ** Or, if no problems regarding the source tables are detected and no
590 ** other error occurs, SQLITE_OK is returned.
591 */
unionSourceCheck(UnionTab * pTab,char ** pzErr)592 static int unionSourceCheck(UnionTab *pTab, char **pzErr){
593   int rc = SQLITE_OK;
594   char *z0 = 0;
595   int i;
596 
597   assert( *pzErr==0 );
598   z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr);
599   for(i=1; i<pTab->nSrc; i++){
600     char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr);
601     if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
602       *pzErr = sqlite3_mprintf("source table schema mismatch");
603       rc = SQLITE_ERROR;
604     }
605     sqlite3_free(z);
606   }
607   sqlite3_free(z0);
608 
609   return rc;
610 }
611 
612 /*
613 ** Try to open the swarmvtab database.  If initially unable, invoke the
614 ** not-found callback UDF and then try again.
615 */
unionOpenDatabaseInner(UnionTab * pTab,UnionSrc * pSrc,char ** pzErr)616 static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){
617   static const int openFlags = SQLITE_OPEN_READONLY | SQLITE_OPEN_URI;
618   int rc;
619 
620   rc = unionInvokeOpenClose(pTab, pSrc, 0, pzErr);
621   if( rc!=SQLITE_OK ) return rc;
622 
623   rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
624   if( rc==SQLITE_OK ) return rc;
625   if( pTab->pNotFound ){
626     sqlite3_close(pSrc->db);
627     pSrc->db = 0;
628     sqlite3_bind_text(pTab->pNotFound, 1, pSrc->zFile, -1, SQLITE_STATIC);
629     if( pTab->bHasContext ){
630       sqlite3_bind_text(pTab->pNotFound, 2, pSrc->zContext, -1, SQLITE_STATIC);
631     }
632     sqlite3_step(pTab->pNotFound);
633     if( SQLITE_OK!=(rc = sqlite3_reset(pTab->pNotFound)) ){
634       *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
635       return rc;
636     }
637     rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
638   }
639   if( rc!=SQLITE_OK ){
640     *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pSrc->db));
641   }
642   return rc;
643 }
644 
645 /*
646 ** This function may only be called for swarmvtab tables. The results of
647 ** calling it on a unionvtab table are undefined.
648 **
649 ** For a swarmvtab table, this function ensures that source database iSrc
650 ** is open. If the database is opened successfully and the schema is as
651 ** expected, or if it is already open when this function is called, SQLITE_OK
652 ** is returned.
653 **
654 ** Alternatively If an error occurs while opening the databases, or if the
655 ** database schema is unsuitable, an SQLite error code is returned and (*pzErr)
656 ** may be set to point to an English language error message. In this case it is
657 ** the responsibility of the caller to eventually free the error message buffer
658 ** using sqlite3_free().
659 */
unionOpenDatabase(UnionTab * pTab,int iSrc,char ** pzErr)660 static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
661   int rc = SQLITE_OK;
662   UnionSrc *pSrc = &pTab->aSrc[iSrc];
663 
664   assert( pTab->bSwarm && iSrc<pTab->nSrc );
665   if( pSrc->db==0 ){
666     unionCloseSources(pTab, pTab->nMaxOpen-1);
667     rc = unionOpenDatabaseInner(pTab, pSrc, pzErr);
668     if( rc==SQLITE_OK ){
669       char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr);
670       if( rc==SQLITE_OK ){
671         if( pTab->zSourceStr==0 ){
672           pTab->zSourceStr = z;
673         }else{
674           if( sqlite3_stricmp(z, pTab->zSourceStr) ){
675             *pzErr = sqlite3_mprintf("source table schema mismatch");
676             rc = SQLITE_ERROR;
677           }
678           sqlite3_free(z);
679         }
680       }
681     }
682 
683     if( rc==SQLITE_OK ){
684       pSrc->pNextClosable = pTab->pClosable;
685       pTab->pClosable = pSrc;
686       pTab->nOpen++;
687     }else{
688       sqlite3_close(pSrc->db);
689       pSrc->db = 0;
690       unionInvokeOpenClose(pTab, pSrc, 1, 0);
691     }
692   }
693 
694   return rc;
695 }
696 
697 
698 /*
699 ** This function is a no-op for unionvtab tables. For swarmvtab, increment
700 ** the reference count for source table iTab. If the reference count was
701 ** zero before it was incremented, also remove the source from the closable
702 ** list.
703 */
unionIncrRefcount(UnionTab * pTab,int iTab)704 static void unionIncrRefcount(UnionTab *pTab, int iTab){
705   if( pTab->bSwarm ){
706     UnionSrc *pSrc = &pTab->aSrc[iTab];
707     assert( pSrc->nUser>=0 && pSrc->db );
708     if( pSrc->nUser==0 ){
709       UnionSrc **pp;
710       for(pp=&pTab->pClosable; *pp!=pSrc; pp=&(*pp)->pNextClosable);
711       *pp = pSrc->pNextClosable;
712       pSrc->pNextClosable = 0;
713     }
714     pSrc->nUser++;
715   }
716 }
717 
718 /*
719 ** Finalize the SQL statement pCsr->pStmt and return the result.
720 **
721 ** If this is a swarmvtab table (not unionvtab) and pCsr->pStmt was not
722 ** NULL when this function was called, also decrement the reference
723 ** count on the associated source table. If this means the source tables
724 ** refcount is now zero, add it to the closable list.
725 */
unionFinalizeCsrStmt(UnionCsr * pCsr)726 static int unionFinalizeCsrStmt(UnionCsr *pCsr){
727   int rc = SQLITE_OK;
728   if( pCsr->pStmt ){
729     UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
730     UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
731     rc = sqlite3_finalize(pCsr->pStmt);
732     pCsr->pStmt = 0;
733     if( pTab->bSwarm ){
734       pSrc->nUser--;
735       assert( pSrc->nUser>=0 );
736       if( pSrc->nUser==0 ){
737         pSrc->pNextClosable = pTab->pClosable;
738         pTab->pClosable = pSrc;
739       }
740       unionCloseSources(pTab, pTab->nMaxOpen);
741     }
742   }
743   return rc;
744 }
745 
746 /*
747 ** Return true if the argument is a space, tab, CR or LF character.
748 */
union_isspace(char c)749 static int union_isspace(char c){
750   return (c==' ' || c=='\n' || c=='\r' || c=='\t');
751 }
752 
753 /*
754 ** Return true if the argument is an alphanumeric character in the
755 ** ASCII range.
756 */
union_isidchar(char c)757 static int union_isidchar(char c){
758   return ((c>='a' && c<='z') || (c>='A' && c<'Z') || (c>='0' && c<='9'));
759 }
760 
761 /*
762 ** This function is called to handle all arguments following the first
763 ** (the SQL statement) passed to a swarmvtab (not unionvtab) CREATE
764 ** VIRTUAL TABLE statement. It may bind parameters to the SQL statement
765 ** or configure members of the UnionTab object passed as the second
766 ** argument.
767 **
768 ** Refer to header comments at the top of this file for a description
769 ** of the arguments parsed.
770 **
771 ** This function is a no-op if *pRc is other than SQLITE_OK when it is
772 ** called. Otherwise, if an error occurs, *pRc is set to an SQLite error
773 ** code. In this case *pzErr may be set to point to a buffer containing
774 ** an English language error message. It is the responsibility of the
775 ** caller to eventually free the buffer using sqlite3_free().
776 */
unionConfigureVtab(int * pRc,UnionTab * pTab,sqlite3_stmt * pStmt,int nArg,const char * const * azArg,char ** pzErr)777 static void unionConfigureVtab(
778   int *pRc,                       /* IN/OUT: Error code */
779   UnionTab *pTab,                 /* Table to configure */
780   sqlite3_stmt *pStmt,            /* SQL statement to find sources */
781   int nArg,                       /* Number of entries in azArg[] array */
782   const char * const *azArg,      /* Array of arguments to consider */
783   char **pzErr                    /* OUT: Error message */
784 ){
785   int rc = *pRc;
786   int i;
787   if( rc==SQLITE_OK ){
788     pTab->bHasContext = (sqlite3_column_count(pStmt)>4);
789   }
790   for(i=0; rc==SQLITE_OK && i<nArg; i++){
791     char *zArg = unionStrdup(&rc, azArg[i]);
792     if( zArg ){
793       int nOpt = 0;               /* Size of option name in bytes */
794       char *zOpt;                 /* Pointer to option name */
795       char *zVal;                 /* Pointer to value */
796 
797       unionDequote(zArg);
798       zOpt = zArg;
799       while( union_isspace(*zOpt) ) zOpt++;
800       zVal = zOpt;
801       if( *zVal==':' ) zVal++;
802       while( union_isidchar(*zVal) ) zVal++;
803       nOpt = (int)(zVal-zOpt);
804 
805       while( union_isspace(*zVal) ) zVal++;
806       if( *zVal=='=' ){
807         zOpt[nOpt] = '\0';
808         zVal++;
809         while( union_isspace(*zVal) ) zVal++;
810         zVal = unionStrdup(&rc, zVal);
811         if( zVal ){
812           unionDequote(zVal);
813           if( zOpt[0]==':' ){
814             /* A value to bind to the SQL statement */
815             int iParam = sqlite3_bind_parameter_index(pStmt, zOpt);
816             if( iParam==0 ){
817               *pzErr = sqlite3_mprintf(
818                   "swarmvtab: no such SQL parameter: %s", zOpt
819               );
820               rc = SQLITE_ERROR;
821             }else{
822               rc = sqlite3_bind_text(pStmt, iParam, zVal, -1, SQLITE_TRANSIENT);
823             }
824           }else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "maxopen", 7) ){
825             pTab->nMaxOpen = atoi(zVal);
826             if( pTab->nMaxOpen<=0 ){
827               *pzErr = sqlite3_mprintf("swarmvtab: illegal maxopen value");
828               rc = SQLITE_ERROR;
829             }
830           }else if( nOpt==7 && 0==sqlite3_strnicmp(zOpt, "missing", 7) ){
831             if( pTab->pNotFound ){
832               *pzErr = sqlite3_mprintf(
833                   "swarmvtab: duplicate \"missing\" option");
834               rc = SQLITE_ERROR;
835             }else{
836               pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
837                   "SELECT \"%w\"(?%s)", zVal, pTab->bHasContext ? ",?" : ""
838               );
839             }
840           }else if( nOpt==9 && 0==sqlite3_strnicmp(zOpt, "openclose", 9) ){
841             if( pTab->pOpenClose ){
842               *pzErr = sqlite3_mprintf(
843                   "swarmvtab: duplicate \"openclose\" option");
844               rc = SQLITE_ERROR;
845             }else{
846               pTab->pOpenClose = unionPreparePrintf(&rc, pzErr, pTab->db,
847                   "SELECT \"%w\"(?,?%s)", zVal, pTab->bHasContext ? ",?" : ""
848               );
849             }
850           }else{
851             *pzErr = sqlite3_mprintf("swarmvtab: unrecognized option: %s",zOpt);
852             rc = SQLITE_ERROR;
853           }
854           sqlite3_free(zVal);
855         }
856       }else{
857         if( i==0 && nArg==1 ){
858           pTab->pNotFound = unionPreparePrintf(&rc, pzErr, pTab->db,
859               "SELECT \"%w\"(?)", zArg
860           );
861         }else{
862           *pzErr = sqlite3_mprintf( "swarmvtab: parse error: %s", azArg[i]);
863           rc = SQLITE_ERROR;
864         }
865       }
866       sqlite3_free(zArg);
867     }
868   }
869   *pRc = rc;
870 }
871 
872 /*
873 ** xConnect/xCreate method.
874 **
875 ** The argv[] array contains the following:
876 **
877 **   argv[0]   -> module name  ("unionvtab" or "swarmvtab")
878 **   argv[1]   -> database name
879 **   argv[2]   -> table name
880 **   argv[3]   -> SQL statement
881 **   argv[4]   -> not-found callback UDF name
882 */
unionConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)883 static int unionConnect(
884   sqlite3 *db,
885   void *pAux,
886   int argc, const char *const*argv,
887   sqlite3_vtab **ppVtab,
888   char **pzErr
889 ){
890   UnionTab *pTab = 0;
891   int rc = SQLITE_OK;
892   int bSwarm = (pAux==0 ? 0 : 1);
893   const char *zVtab = (bSwarm ? "swarmvtab" : "unionvtab");
894 
895   if( sqlite3_stricmp("temp", argv[1]) ){
896     /* unionvtab tables may only be created in the temp schema */
897     *pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab);
898     rc = SQLITE_ERROR;
899   }else if( argc<4 || (argc>4 && bSwarm==0) ){
900     *pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab);
901     rc = SQLITE_ERROR;
902   }else{
903     int nAlloc = 0;               /* Allocated size of pTab->aSrc[] */
904     sqlite3_stmt *pStmt = 0;      /* Argument statement */
905     char *zArg = unionStrdup(&rc, argv[3]);      /* Copy of argument to CVT */
906 
907     /* Prepare the SQL statement. Instead of executing it directly, sort
908     ** the results by the "minimum rowid" field. This makes it easier to
909     ** check that there are no rowid range overlaps between source tables
910     ** and that the UnionTab.aSrc[] array is always sorted by rowid.  */
911     unionDequote(zArg);
912     pStmt = unionPreparePrintf(&rc, pzErr, db,
913         "SELECT * FROM (%z) ORDER BY 3", zArg
914     );
915 
916     /* Allocate the UnionTab structure */
917     pTab = unionMalloc(&rc, sizeof(UnionTab));
918     if( pTab ){
919       assert( rc==SQLITE_OK );
920       pTab->db = db;
921       pTab->bSwarm = bSwarm;
922       pTab->nMaxOpen = SWARMVTAB_MAX_OPEN;
923     }
924 
925     /* Parse other CVT arguments, if any */
926     if( bSwarm ){
927       unionConfigureVtab(&rc, pTab, pStmt, argc-4, &argv[4], pzErr);
928     }
929 
930     /* Iterate through the rows returned by the SQL statement specified
931     ** as an argument to the CREATE VIRTUAL TABLE statement. */
932     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
933       const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
934       const char *zTab = (const char*)sqlite3_column_text(pStmt, 1);
935       sqlite3_int64 iMin = sqlite3_column_int64(pStmt, 2);
936       sqlite3_int64 iMax = sqlite3_column_int64(pStmt, 3);
937       UnionSrc *pSrc;
938 
939       /* Grow the pTab->aSrc[] array if required. */
940       if( nAlloc<=pTab->nSrc ){
941         int nNew = nAlloc ? nAlloc*2 : 8;
942         UnionSrc *aNew = (UnionSrc*)sqlite3_realloc64(
943             pTab->aSrc, nNew*sizeof(UnionSrc)
944         );
945         if( aNew==0 ){
946           rc = SQLITE_NOMEM;
947           break;
948         }else{
949           memset(&aNew[pTab->nSrc], 0, (nNew-pTab->nSrc)*sizeof(UnionSrc));
950           pTab->aSrc = aNew;
951           nAlloc = nNew;
952         }
953       }
954 
955       /* Check for problems with the specified range of rowids */
956       if( iMax<iMin || (pTab->nSrc>0 && iMin<=pTab->aSrc[pTab->nSrc-1].iMax) ){
957         *pzErr = sqlite3_mprintf("rowid range mismatch error");
958         rc = SQLITE_ERROR;
959       }
960 
961       if( rc==SQLITE_OK ){
962         pSrc = &pTab->aSrc[pTab->nSrc++];
963         pSrc->zTab = unionStrdup(&rc, zTab);
964         pSrc->iMin = iMin;
965         pSrc->iMax = iMax;
966         if( bSwarm ){
967           pSrc->zFile = unionStrdup(&rc, zDb);
968         }else{
969           pSrc->zDb = unionStrdup(&rc, zDb);
970         }
971         if( pTab->bHasContext ){
972           const char *zContext = (const char*)sqlite3_column_text(pStmt, 4);
973           pSrc->zContext = unionStrdup(&rc, zContext);
974         }
975       }
976     }
977     unionFinalize(&rc, pStmt, pzErr);
978     pStmt = 0;
979 
980     /* It is an error if the SELECT statement returned zero rows. If only
981     ** because there is no way to determine the schema of the virtual
982     ** table in this case.  */
983     if( rc==SQLITE_OK && pTab->nSrc==0 ){
984       *pzErr = sqlite3_mprintf("no source tables configured");
985       rc = SQLITE_ERROR;
986     }
987 
988     /* For unionvtab, verify that all source tables exist and have
989     ** compatible schemas. For swarmvtab, attach the first database and
990     ** check that the first table is a rowid table only.  */
991     if( rc==SQLITE_OK ){
992       if( bSwarm ){
993         rc = unionOpenDatabase(pTab, 0, pzErr);
994       }else{
995         rc = unionSourceCheck(pTab, pzErr);
996       }
997     }
998 
999     /* Compose a CREATE TABLE statement and pass it to declare_vtab() */
1000     if( rc==SQLITE_OK ){
1001       UnionSrc *pSrc = &pTab->aSrc[0];
1002       sqlite3 *tdb = unionGetDb(pTab, pSrc);
1003       pStmt = unionPreparePrintf(&rc, pzErr, tdb, "SELECT "
1004           "'CREATE TABLE xyz('"
1005           "    || group_concat(quote(name) || ' ' || type, ', ')"
1006           "    || ')',"
1007           "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
1008           "FROM pragma_table_info(%Q, ?)",
1009           pSrc->zTab, pSrc->zDb
1010       );
1011     }
1012     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
1013       const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0);
1014       rc = sqlite3_declare_vtab(db, zDecl);
1015       pTab->iPK = sqlite3_column_int(pStmt, 1);
1016     }
1017 
1018     unionFinalize(&rc, pStmt, pzErr);
1019   }
1020 
1021   if( rc!=SQLITE_OK ){
1022     unionDisconnect((sqlite3_vtab*)pTab);
1023     pTab = 0;
1024   }
1025 
1026   *ppVtab = (sqlite3_vtab*)pTab;
1027   return rc;
1028 }
1029 
1030 /*
1031 ** xOpen
1032 */
unionOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)1033 static int unionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
1034   UnionCsr *pCsr;
1035   int rc = SQLITE_OK;
1036   (void)p;  /* Suppress harmless warning */
1037   pCsr = (UnionCsr*)unionMalloc(&rc, sizeof(UnionCsr));
1038   *ppCursor = &pCsr->base;
1039   return rc;
1040 }
1041 
1042 /*
1043 ** xClose
1044 */
unionClose(sqlite3_vtab_cursor * cur)1045 static int unionClose(sqlite3_vtab_cursor *cur){
1046   UnionCsr *pCsr = (UnionCsr*)cur;
1047   unionFinalizeCsrStmt(pCsr);
1048   sqlite3_free(pCsr);
1049   return SQLITE_OK;
1050 }
1051 
1052 /*
1053 ** This function does the work of the xNext() method. Except that, if it
1054 ** returns SQLITE_ROW, it should be called again within the same xNext()
1055 ** method call. See unionNext() for details.
1056 */
doUnionNext(UnionCsr * pCsr)1057 static int doUnionNext(UnionCsr *pCsr){
1058   int rc = SQLITE_OK;
1059   assert( pCsr->pStmt );
1060   if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){
1061     UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
1062     rc = unionFinalizeCsrStmt(pCsr);
1063     if( rc==SQLITE_OK && pTab->bSwarm ){
1064       pCsr->iTab++;
1065       if( pCsr->iTab<pTab->nSrc ){
1066         UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
1067         if( pCsr->iMaxRowid>=pSrc->iMin ){
1068           /* It is necessary to scan the next table. */
1069           rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
1070           pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pSrc->db,
1071               "SELECT rowid, * FROM %Q %s %lld",
1072               pSrc->zTab,
1073               (pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "),
1074               pCsr->iMaxRowid
1075           );
1076           if( rc==SQLITE_OK ){
1077             assert( pCsr->pStmt );
1078             unionIncrRefcount(pTab, pCsr->iTab);
1079             rc = SQLITE_ROW;
1080           }
1081         }
1082       }
1083     }
1084   }
1085 
1086   return rc;
1087 }
1088 
1089 /*
1090 ** xNext
1091 */
unionNext(sqlite3_vtab_cursor * cur)1092 static int unionNext(sqlite3_vtab_cursor *cur){
1093   int rc;
1094   do {
1095     rc = doUnionNext((UnionCsr*)cur);
1096   }while( rc==SQLITE_ROW );
1097   return rc;
1098 }
1099 
1100 /*
1101 ** xColumn
1102 */
unionColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)1103 static int unionColumn(
1104   sqlite3_vtab_cursor *cur,
1105   sqlite3_context *ctx,
1106   int i
1107 ){
1108   UnionCsr *pCsr = (UnionCsr*)cur;
1109   sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1));
1110   return SQLITE_OK;
1111 }
1112 
1113 /*
1114 ** xRowid
1115 */
unionRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)1116 static int unionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
1117   UnionCsr *pCsr = (UnionCsr*)cur;
1118   *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
1119   return SQLITE_OK;
1120 }
1121 
1122 /*
1123 ** xEof
1124 */
unionEof(sqlite3_vtab_cursor * cur)1125 static int unionEof(sqlite3_vtab_cursor *cur){
1126   UnionCsr *pCsr = (UnionCsr*)cur;
1127   return pCsr->pStmt==0;
1128 }
1129 
1130 /*
1131 ** xFilter
1132 */
unionFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)1133 static int unionFilter(
1134   sqlite3_vtab_cursor *pVtabCursor,
1135   int idxNum, const char *idxStr,
1136   int argc, sqlite3_value **argv
1137 ){
1138   UnionTab *pTab = (UnionTab*)(pVtabCursor->pVtab);
1139   UnionCsr *pCsr = (UnionCsr*)pVtabCursor;
1140   int rc = SQLITE_OK;
1141   int i;
1142   char *zSql = 0;
1143   int bZero = 0;
1144 
1145   sqlite3_int64 iMin = SMALLEST_INT64;
1146   sqlite3_int64 iMax = LARGEST_INT64;
1147 
1148   assert( idxNum==0
1149        || idxNum==SQLITE_INDEX_CONSTRAINT_EQ
1150        || idxNum==SQLITE_INDEX_CONSTRAINT_LE
1151        || idxNum==SQLITE_INDEX_CONSTRAINT_GE
1152        || idxNum==SQLITE_INDEX_CONSTRAINT_LT
1153        || idxNum==SQLITE_INDEX_CONSTRAINT_GT
1154        || idxNum==(SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_LE)
1155   );
1156 
1157   (void)idxStr;  /* Suppress harmless warning */
1158 
1159   if( idxNum==SQLITE_INDEX_CONSTRAINT_EQ ){
1160     assert( argc==1 );
1161     iMin = iMax = sqlite3_value_int64(argv[0]);
1162   }else{
1163 
1164     if( idxNum & (SQLITE_INDEX_CONSTRAINT_LE|SQLITE_INDEX_CONSTRAINT_LT) ){
1165       assert( argc>=1 );
1166       iMax = sqlite3_value_int64(argv[0]);
1167       if( idxNum & SQLITE_INDEX_CONSTRAINT_LT ){
1168         if( iMax==SMALLEST_INT64 ){
1169           bZero = 1;
1170         }else{
1171           iMax--;
1172         }
1173       }
1174     }
1175 
1176     if( idxNum & (SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_GT) ){
1177       assert( argc>=1 );
1178       iMin = sqlite3_value_int64(argv[argc-1]);
1179       if( idxNum & SQLITE_INDEX_CONSTRAINT_GT ){
1180         if( iMin==LARGEST_INT64 ){
1181           bZero = 1;
1182         }else{
1183           iMin++;
1184         }
1185       }
1186     }
1187   }
1188 
1189   unionFinalizeCsrStmt(pCsr);
1190   if( bZero ){
1191     return SQLITE_OK;
1192   }
1193 
1194   for(i=0; i<pTab->nSrc; i++){
1195     UnionSrc *pSrc = &pTab->aSrc[i];
1196     if( iMin>pSrc->iMax || iMax<pSrc->iMin ){
1197       continue;
1198     }
1199 
1200     zSql = sqlite3_mprintf("%z%sSELECT rowid, * FROM %s%q%s%Q"
1201         , zSql
1202         , (zSql ? " UNION ALL " : "")
1203         , (pSrc->zDb ? "'" : "")
1204         , (pSrc->zDb ? pSrc->zDb : "")
1205         , (pSrc->zDb ? "'." : "")
1206         , pSrc->zTab
1207     );
1208     if( zSql==0 ){
1209       rc = SQLITE_NOMEM;
1210       break;
1211     }
1212 
1213     if( iMin==iMax ){
1214       zSql = sqlite3_mprintf("%z WHERE rowid=%lld", zSql, iMin);
1215     }else{
1216       const char *zWhere = "WHERE";
1217       if( iMin!=SMALLEST_INT64 && iMin>pSrc->iMin ){
1218         zSql = sqlite3_mprintf("%z WHERE rowid>=%lld", zSql, iMin);
1219         zWhere = "AND";
1220       }
1221       if( iMax!=LARGEST_INT64 && iMax<pSrc->iMax ){
1222         zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax);
1223       }
1224     }
1225 
1226     if( pTab->bSwarm ){
1227       pCsr->iTab = i;
1228       pCsr->iMaxRowid = iMax;
1229       rc = unionOpenDatabase(pTab, i, &pTab->base.zErrMsg);
1230       break;
1231     }
1232   }
1233 
1234   if( zSql==0 ){
1235     return rc;
1236   }else{
1237     sqlite3 *db = unionGetDb(pTab, &pTab->aSrc[pCsr->iTab]);
1238     pCsr->pStmt = unionPrepare(&rc, db, zSql, &pTab->base.zErrMsg);
1239     if( pCsr->pStmt ){
1240       unionIncrRefcount(pTab, pCsr->iTab);
1241     }
1242     sqlite3_free(zSql);
1243   }
1244   if( rc!=SQLITE_OK ) return rc;
1245   return unionNext(pVtabCursor);
1246 }
1247 
1248 /*
1249 ** xBestIndex.
1250 **
1251 ** This implementation searches for constraints on the rowid field. EQ,
1252 ** LE, LT, GE and GT are handled.
1253 **
1254 ** If there is an EQ comparison, then idxNum is set to INDEX_CONSTRAINT_EQ.
1255 ** In this case the only argument passed to xFilter is the rhs of the ==
1256 ** operator.
1257 **
1258 ** Otherwise, if an LE or LT constraint is found, then the INDEX_CONSTRAINT_LE
1259 ** or INDEX_CONSTRAINT_LT (but not both) bit is set in idxNum. The first
1260 ** argument to xFilter is the rhs of the <= or < operator.  Similarly, if
1261 ** an GE or GT constraint is found, then the INDEX_CONSTRAINT_GE or
1262 ** INDEX_CONSTRAINT_GT bit is set in idxNum. The rhs of the >= or > operator
1263 ** is passed as either the first or second argument to xFilter, depending
1264 ** on whether or not there is also a LT|LE constraint.
1265 */
unionBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)1266 static int unionBestIndex(
1267   sqlite3_vtab *tab,
1268   sqlite3_index_info *pIdxInfo
1269 ){
1270   UnionTab *pTab = (UnionTab*)tab;
1271   int iEq = -1;
1272   int iLt = -1;
1273   int iGt = -1;
1274   int i;
1275 
1276   for(i=0; i<pIdxInfo->nConstraint; i++){
1277     struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
1278     if( p->usable && (p->iColumn<0 || p->iColumn==pTab->iPK) ){
1279       switch( p->op ){
1280         case SQLITE_INDEX_CONSTRAINT_EQ:
1281           iEq = i;
1282           break;
1283         case SQLITE_INDEX_CONSTRAINT_LE:
1284         case SQLITE_INDEX_CONSTRAINT_LT:
1285           iLt = i;
1286           break;
1287         case SQLITE_INDEX_CONSTRAINT_GE:
1288         case SQLITE_INDEX_CONSTRAINT_GT:
1289           iGt = i;
1290           break;
1291       }
1292     }
1293   }
1294 
1295   if( iEq>=0 ){
1296     pIdxInfo->estimatedRows = 1;
1297     pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
1298     pIdxInfo->estimatedCost = 3.0;
1299     pIdxInfo->idxNum = SQLITE_INDEX_CONSTRAINT_EQ;
1300     pIdxInfo->aConstraintUsage[iEq].argvIndex = 1;
1301     pIdxInfo->aConstraintUsage[iEq].omit = 1;
1302   }else{
1303     int iCons = 1;
1304     int idxNum = 0;
1305     sqlite3_int64 nRow = 1000000;
1306     if( iLt>=0 ){
1307       nRow = nRow / 2;
1308       pIdxInfo->aConstraintUsage[iLt].argvIndex = iCons++;
1309       pIdxInfo->aConstraintUsage[iLt].omit = 1;
1310       idxNum |= pIdxInfo->aConstraint[iLt].op;
1311     }
1312     if( iGt>=0 ){
1313       nRow = nRow / 2;
1314       pIdxInfo->aConstraintUsage[iGt].argvIndex = iCons++;
1315       pIdxInfo->aConstraintUsage[iGt].omit = 1;
1316       idxNum |= pIdxInfo->aConstraint[iGt].op;
1317     }
1318     pIdxInfo->estimatedRows = nRow;
1319     pIdxInfo->estimatedCost = 3.0 * (double)nRow;
1320     pIdxInfo->idxNum = idxNum;
1321   }
1322 
1323   return SQLITE_OK;
1324 }
1325 
1326 /*
1327 ** Register the unionvtab virtual table module with database handle db.
1328 */
createUnionVtab(sqlite3 * db)1329 static int createUnionVtab(sqlite3 *db){
1330   static sqlite3_module unionModule = {
1331     0,                            /* iVersion */
1332     unionConnect,
1333     unionConnect,
1334     unionBestIndex,               /* xBestIndex - query planner */
1335     unionDisconnect,
1336     unionDisconnect,
1337     unionOpen,                    /* xOpen - open a cursor */
1338     unionClose,                   /* xClose - close a cursor */
1339     unionFilter,                  /* xFilter - configure scan constraints */
1340     unionNext,                    /* xNext - advance a cursor */
1341     unionEof,                     /* xEof - check for end of scan */
1342     unionColumn,                  /* xColumn - read data */
1343     unionRowid,                   /* xRowid - read data */
1344     0,                            /* xUpdate */
1345     0,                            /* xBegin */
1346     0,                            /* xSync */
1347     0,                            /* xCommit */
1348     0,                            /* xRollback */
1349     0,                            /* xFindMethod */
1350     0,                            /* xRename */
1351     0,                            /* xSavepoint */
1352     0,                            /* xRelease */
1353     0,                            /* xRollbackTo */
1354     0                             /* xShadowName */
1355   };
1356   int rc;
1357 
1358   rc = sqlite3_create_module(db, "unionvtab", &unionModule, 0);
1359   if( rc==SQLITE_OK ){
1360     rc = sqlite3_create_module(db, "swarmvtab", &unionModule, (void*)db);
1361   }
1362   return rc;
1363 }
1364 
1365 #endif /* SQLITE_OMIT_VIRTUALTABLE */
1366 
1367 #ifdef _WIN32
1368 __declspec(dllexport)
1369 #endif
sqlite3_unionvtab_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)1370 int sqlite3_unionvtab_init(
1371   sqlite3 *db,
1372   char **pzErrMsg,
1373   const sqlite3_api_routines *pApi
1374 ){
1375   int rc = SQLITE_OK;
1376   SQLITE_EXTENSION_INIT2(pApi);
1377   (void)pzErrMsg;  /* Suppress harmless warning */
1378 #ifndef SQLITE_OMIT_VIRTUALTABLE
1379   rc = createUnionVtab(db);
1380 #endif
1381   return rc;
1382 }
1383