modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/unionvtab.c (about) 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 ** A "swarmvtab" virtual table is created similarly to a unionvtab table: 60 ** 61 ** CREATE VIRTUAL TABLE <name> 62 ** USING swarmvtab(<sql-statement>, <callback>); 63 ** 64 ** The difference is that for a swarmvtab table, the first column returned 65 ** by the <sql statement> must return a path or URI that can be used to open 66 ** the database file containing the source table. The <callback> option 67 ** is optional. If included, it is the name of an application-defined 68 ** SQL function that is invoked with the URI of the file, if the file 69 ** does not already exist on disk. 70 */ 71 72 #include "sqlite3ext.h" 73 SQLITE_EXTENSION_INIT1 74 #include <assert.h> 75 #include <string.h> 76 77 #ifndef SQLITE_OMIT_VIRTUALTABLE 78 79 /* 80 ** Largest and smallest possible 64-bit signed integers. These macros 81 ** copied from sqliteInt.h. 82 */ 83 #ifndef LARGEST_INT64 84 # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) 85 #endif 86 #ifndef SMALLEST_INT64 87 # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) 88 #endif 89 90 /* 91 ** The following is also copied from sqliteInt.h. To facilitate coverage 92 ** testing. 93 */ 94 #ifndef ALWAYS 95 # if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) 96 # define ALWAYS(X) (1) 97 # define NEVER(X) (0) 98 # elif !defined(NDEBUG) 99 # define ALWAYS(X) ((X)?1:(assert(0),0)) 100 # define NEVER(X) ((X)?(assert(0),1):0) 101 # else 102 # define ALWAYS(X) (X) 103 # define NEVER(X) (X) 104 # endif 105 #endif 106 107 /* 108 ** The swarmvtab module attempts to keep the number of open database files 109 ** at or below this limit. This may not be possible if there are too many 110 ** simultaneous queries. 111 */ 112 #define SWARMVTAB_MAX_OPEN 9 113 114 typedef struct UnionCsr UnionCsr; 115 typedef struct UnionTab UnionTab; 116 typedef struct UnionSrc UnionSrc; 117 118 /* 119 ** Each source table (row returned by the initialization query) is 120 ** represented by an instance of the following structure stored in the 121 ** UnionTab.aSrc[] array. 122 */ 123 struct UnionSrc { 124 char *zDb; /* Database containing source table */ 125 char *zTab; /* Source table name */ 126 sqlite3_int64 iMin; /* Minimum rowid */ 127 sqlite3_int64 iMax; /* Maximum rowid */ 128 129 /* Fields used by swarmvtab only */ 130 char *zFile; /* Database file containing table zTab */ 131 int nUser; /* Current number of users */ 132 sqlite3 *db; /* Database handle */ 133 UnionSrc *pNextClosable; /* Next in list of closable sources */ 134 }; 135 136 /* 137 ** Virtual table type for union vtab. 138 */ 139 struct UnionTab { 140 sqlite3_vtab base; /* Base class - must be first */ 141 sqlite3 *db; /* Database handle */ 142 int bSwarm; /* 1 for "swarmvtab", 0 for "unionvtab" */ 143 int iPK; /* INTEGER PRIMARY KEY column, or -1 */ 144 int nSrc; /* Number of elements in the aSrc[] array */ 145 UnionSrc *aSrc; /* Array of source tables, sorted by rowid */ 146 147 /* Used by swarmvtab only */ 148 char *zSourceStr; /* Expected unionSourceToStr() value */ 149 char *zNotFoundCallback; /* UDF to invoke if file not found on open */ 150 UnionSrc *pClosable; /* First in list of closable sources */ 151 int nOpen; /* Current number of open sources */ 152 int nMaxOpen; /* Maximum number of open sources */ 153 }; 154 155 /* 156 ** Virtual table cursor type for union vtab. 157 */ 158 struct UnionCsr { 159 sqlite3_vtab_cursor base; /* Base class - must be first */ 160 sqlite3_stmt *pStmt; /* SQL statement to run */ 161 162 /* Used by swarmvtab only */ 163 sqlite3_int64 iMaxRowid; /* Last rowid to visit */ 164 int iTab; /* Index of table read by pStmt */ 165 }; 166 167 /* 168 ** Given UnionTab table pTab and UnionSrc object pSrc, return the database 169 ** handle that should be used to access the table identified by pSrc. This 170 ** is the main db handle for "unionvtab" tables, or the source-specific 171 ** handle for "swarmvtab". 172 */ 173 #define unionGetDb(pTab, pSrc) ((pTab)->bSwarm ? (pSrc)->db : (pTab)->db) 174 175 /* 176 ** If *pRc is other than SQLITE_OK when this function is called, it 177 ** always returns NULL. Otherwise, it attempts to allocate and return 178 ** a pointer to nByte bytes of zeroed memory. If the memory allocation 179 ** is attempted but fails, NULL is returned and *pRc is set to 180 ** SQLITE_NOMEM. 181 */ 182 static void *unionMalloc(int *pRc, int nByte){ 183 void *pRet; 184 assert( nByte>0 ); 185 if( *pRc==SQLITE_OK ){ 186 pRet = sqlite3_malloc(nByte); 187 if( pRet ){ 188 memset(pRet, 0, nByte); 189 }else{ 190 *pRc = SQLITE_NOMEM; 191 } 192 }else{ 193 pRet = 0; 194 } 195 return pRet; 196 } 197 198 /* 199 ** If *pRc is other than SQLITE_OK when this function is called, it 200 ** always returns NULL. Otherwise, it attempts to allocate and return 201 ** a copy of the nul-terminated string passed as the second argument. 202 ** If the allocation is attempted but fails, NULL is returned and *pRc is 203 ** set to SQLITE_NOMEM. 204 */ 205 static char *unionStrdup(int *pRc, const char *zIn){ 206 char *zRet = 0; 207 if( zIn ){ 208 int nByte = (int)strlen(zIn) + 1; 209 zRet = unionMalloc(pRc, nByte); 210 if( zRet ){ 211 memcpy(zRet, zIn, nByte); 212 } 213 } 214 return zRet; 215 } 216 217 /* 218 ** If the first character of the string passed as the only argument to this 219 ** function is one of the 4 that may be used as an open quote character 220 ** in SQL, this function assumes that the input is a well-formed quoted SQL 221 ** string. In this case the string is dequoted in place. 222 ** 223 ** If the first character of the input is not an open quote, then this 224 ** function is a no-op. 225 */ 226 static void unionDequote(char *z){ 227 if( z ){ 228 char q = z[0]; 229 230 /* Set stack variable q to the close-quote character */ 231 if( q=='[' || q=='\'' || q=='"' || q=='`' ){ 232 int iIn = 1; 233 int iOut = 0; 234 if( q=='[' ) q = ']'; 235 while( ALWAYS(z[iIn]) ){ 236 if( z[iIn]==q ){ 237 if( z[iIn+1]!=q ){ 238 /* Character iIn was the close quote. */ 239 iIn++; 240 break; 241 }else{ 242 /* Character iIn and iIn+1 form an escaped quote character. Skip 243 ** the input cursor past both and copy a single quote character 244 ** to the output buffer. */ 245 iIn += 2; 246 z[iOut++] = q; 247 } 248 }else{ 249 z[iOut++] = z[iIn++]; 250 } 251 } 252 z[iOut] = '\0'; 253 } 254 } 255 } 256 257 /* 258 ** This function is a no-op if *pRc is set to other than SQLITE_OK when it 259 ** is called. NULL is returned in this case. 260 ** 261 ** Otherwise, the SQL statement passed as the third argument is prepared 262 ** against the database handle passed as the second. If the statement is 263 ** successfully prepared, a pointer to the new statement handle is 264 ** returned. It is the responsibility of the caller to eventually free the 265 ** statement by calling sqlite3_finalize(). Alternatively, if statement 266 ** compilation fails, NULL is returned, *pRc is set to an SQLite error 267 ** code and *pzErr may be set to an error message buffer allocated by 268 ** sqlite3_malloc(). 269 */ 270 static sqlite3_stmt *unionPrepare( 271 int *pRc, /* IN/OUT: Error code */ 272 sqlite3 *db, /* Database handle */ 273 const char *zSql, /* SQL statement to prepare */ 274 char **pzErr /* OUT: Error message */ 275 ){ 276 sqlite3_stmt *pRet = 0; 277 assert( pzErr ); 278 if( *pRc==SQLITE_OK ){ 279 int rc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0); 280 if( rc!=SQLITE_OK ){ 281 *pzErr = sqlite3_mprintf("sql error: %s", sqlite3_errmsg(db)); 282 *pRc = rc; 283 } 284 } 285 return pRet; 286 } 287 288 /* 289 ** Like unionPrepare(), except prepare the results of vprintf(zFmt, ...) 290 ** instead of a constant SQL string. 291 */ 292 static sqlite3_stmt *unionPreparePrintf( 293 int *pRc, /* IN/OUT: Error code */ 294 char **pzErr, /* OUT: Error message */ 295 sqlite3 *db, /* Database handle */ 296 const char *zFmt, /* printf() format string */ 297 ... /* Trailing printf args */ 298 ){ 299 sqlite3_stmt *pRet = 0; 300 char *zSql; 301 va_list ap; 302 va_start(ap, zFmt); 303 304 zSql = sqlite3_vmprintf(zFmt, ap); 305 if( *pRc==SQLITE_OK ){ 306 if( zSql==0 ){ 307 *pRc = SQLITE_NOMEM; 308 }else{ 309 pRet = unionPrepare(pRc, db, zSql, pzErr); 310 } 311 } 312 sqlite3_free(zSql); 313 314 va_end(ap); 315 return pRet; 316 } 317 318 319 /* 320 ** Call sqlite3_reset() on SQL statement pStmt. If *pRc is set to 321 ** SQLITE_OK when this function is called, then it is set to the 322 ** value returned by sqlite3_reset() before this function exits. 323 ** In this case, *pzErr may be set to point to an error message 324 ** buffer allocated by sqlite3_malloc(). 325 */ 326 #if 0 327 static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){ 328 int rc = sqlite3_reset(pStmt); 329 if( *pRc==SQLITE_OK ){ 330 *pRc = rc; 331 if( rc ){ 332 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt))); 333 } 334 } 335 } 336 #endif 337 338 /* 339 ** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to 340 ** SQLITE_OK when this function is called, then it is set to the 341 ** value returned by sqlite3_finalize() before this function exits. 342 */ 343 static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){ 344 sqlite3 *db = sqlite3_db_handle(pStmt); 345 int rc = sqlite3_finalize(pStmt); 346 if( *pRc==SQLITE_OK ){ 347 *pRc = rc; 348 if( rc ){ 349 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 350 } 351 } 352 } 353 354 /* 355 ** This function is a no-op for unionvtab. For swarmvtab, it attempts to 356 ** close open database files until at most nMax are open. An SQLite error 357 ** code is returned if an error occurs, or SQLITE_OK otherwise. 358 */ 359 static void unionCloseSources(UnionTab *pTab, int nMax){ 360 while( pTab->pClosable && pTab->nOpen>nMax ){ 361 UnionSrc **pp; 362 for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable); 363 assert( (*pp)->db ); 364 sqlite3_close((*pp)->db); 365 (*pp)->db = 0; 366 *pp = 0; 367 pTab->nOpen--; 368 } 369 } 370 371 /* 372 ** xDisconnect method. 373 */ 374 static int unionDisconnect(sqlite3_vtab *pVtab){ 375 if( pVtab ){ 376 UnionTab *pTab = (UnionTab*)pVtab; 377 int i; 378 for(i=0; i<pTab->nSrc; i++){ 379 UnionSrc *pSrc = &pTab->aSrc[i]; 380 sqlite3_free(pSrc->zDb); 381 sqlite3_free(pSrc->zTab); 382 sqlite3_free(pSrc->zFile); 383 sqlite3_close(pSrc->db); 384 } 385 sqlite3_free(pTab->zSourceStr); 386 sqlite3_free(pTab->zNotFoundCallback); 387 sqlite3_free(pTab->aSrc); 388 sqlite3_free(pTab); 389 } 390 return SQLITE_OK; 391 } 392 393 /* 394 ** Check that the table identified by pSrc is a rowid table. If not, 395 ** return SQLITE_ERROR and set (*pzErr) to point to an English language 396 ** error message. If the table is a rowid table and no error occurs, 397 ** return SQLITE_OK and leave (*pzErr) unmodified. 398 */ 399 static int unionIsIntkeyTable( 400 sqlite3 *db, /* Database handle */ 401 UnionSrc *pSrc, /* Source table to test */ 402 char **pzErr /* OUT: Error message */ 403 ){ 404 int bPk = 0; 405 const char *zType = 0; 406 int rc; 407 408 sqlite3_table_column_metadata( 409 db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0 410 ); 411 rc = sqlite3_errcode(db); 412 if( rc==SQLITE_ERROR 413 || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType))) 414 ){ 415 rc = SQLITE_ERROR; 416 *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s", 417 (pSrc->zDb ? pSrc->zDb : ""), 418 (pSrc->zDb ? "." : ""), 419 pSrc->zTab 420 ); 421 } 422 return rc; 423 } 424 425 /* 426 ** This function is a no-op if *pRc is other than SQLITE_OK when it is 427 ** called. In this case it returns NULL. 428 ** 429 ** Otherwise, this function checks that the source table passed as the 430 ** second argument (a) exists, (b) is not a view and (c) has a column 431 ** named "_rowid_" of type "integer" that is the primary key. 432 ** If this is not the case, *pRc is set to SQLITE_ERROR and NULL is 433 ** returned. 434 ** 435 ** Finally, if the source table passes the checks above, a nul-terminated 436 ** string describing the column names and types belonging to the source 437 ** table is returned. Tables with the same set of column names and types 438 ** cause this function to return identical strings. Is is the responsibility 439 ** of the caller to free the returned string using sqlite3_free() when 440 ** it is no longer required. 441 */ 442 static char *unionSourceToStr( 443 int *pRc, /* IN/OUT: Error code */ 444 UnionTab *pTab, /* Virtual table object */ 445 UnionSrc *pSrc, /* Source table to test */ 446 char **pzErr /* OUT: Error message */ 447 ){ 448 char *zRet = 0; 449 if( *pRc==SQLITE_OK ){ 450 sqlite3 *db = unionGetDb(pTab, pSrc); 451 int rc = unionIsIntkeyTable(db, pSrc, pzErr); 452 sqlite3_stmt *pStmt = unionPrepare(&rc, db, 453 "SELECT group_concat(quote(name) || '.' || quote(type)) " 454 "FROM pragma_table_info(?, ?)", pzErr 455 ); 456 if( rc==SQLITE_OK ){ 457 sqlite3_bind_text(pStmt, 1, pSrc->zTab, -1, SQLITE_STATIC); 458 sqlite3_bind_text(pStmt, 2, pSrc->zDb, -1, SQLITE_STATIC); 459 if( SQLITE_ROW==sqlite3_step(pStmt) ){ 460 const char *z = (const char*)sqlite3_column_text(pStmt, 0); 461 zRet = unionStrdup(&rc, z); 462 } 463 unionFinalize(&rc, pStmt, pzErr); 464 } 465 *pRc = rc; 466 } 467 468 return zRet; 469 } 470 471 /* 472 ** Check that all configured source tables exist and have the same column 473 ** names and datatypes. If this is not the case, or if some other error 474 ** occurs, return an SQLite error code. In this case *pzErr may be set 475 ** to point to an error message buffer allocated by sqlite3_mprintf(). 476 ** Or, if no problems regarding the source tables are detected and no 477 ** other error occurs, SQLITE_OK is returned. 478 */ 479 static int unionSourceCheck(UnionTab *pTab, char **pzErr){ 480 int rc = SQLITE_OK; 481 char *z0 = 0; 482 int i; 483 484 assert( *pzErr==0 ); 485 z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr); 486 for(i=1; i<pTab->nSrc; i++){ 487 char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr); 488 if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){ 489 *pzErr = sqlite3_mprintf("source table schema mismatch"); 490 rc = SQLITE_ERROR; 491 } 492 sqlite3_free(z); 493 } 494 sqlite3_free(z0); 495 496 return rc; 497 } 498 499 500 /* 501 ** Try to open the swarmvtab database. If initially unable, invoke the 502 ** not-found callback UDF and then try again. 503 */ 504 static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){ 505 int rc = SQLITE_OK; 506 static const int openFlags = 507 SQLITE_OPEN_READONLY | SQLITE_OPEN_URI; 508 rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0); 509 if( rc==SQLITE_OK ) return rc; 510 if( pTab->zNotFoundCallback ){ 511 char *zSql = sqlite3_mprintf("SELECT \"%w\"(%Q);", 512 pTab->zNotFoundCallback, pSrc->zFile); 513 sqlite3_close(pSrc->db); 514 pSrc->db = 0; 515 if( zSql==0 ){ 516 *pzErr = sqlite3_mprintf("out of memory"); 517 return SQLITE_NOMEM; 518 } 519 rc = sqlite3_exec(pTab->db, zSql, 0, 0, pzErr); 520 sqlite3_free(zSql); 521 if( rc ) return rc; 522 rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0); 523 } 524 if( rc!=SQLITE_OK ){ 525 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pSrc->db)); 526 } 527 return rc; 528 } 529 530 /* 531 ** This function may only be called for swarmvtab tables. The results of 532 ** calling it on a unionvtab table are undefined. 533 ** 534 ** For a swarmvtab table, this function ensures that source database iSrc 535 ** is open. If the database is opened successfully and the schema is as 536 ** expected, or if it is already open when this function is called, SQLITE_OK 537 ** is returned. 538 ** 539 ** Alternatively If an error occurs while opening the databases, or if the 540 ** database schema is unsuitable, an SQLite error code is returned and (*pzErr) 541 ** may be set to point to an English language error message. In this case it is 542 ** the responsibility of the caller to eventually free the error message buffer 543 ** using sqlite3_free(). 544 */ 545 static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){ 546 int rc = SQLITE_OK; 547 UnionSrc *pSrc = &pTab->aSrc[iSrc]; 548 549 assert( pTab->bSwarm && iSrc<pTab->nSrc ); 550 if( pSrc->db==0 ){ 551 unionCloseSources(pTab, pTab->nMaxOpen-1); 552 rc = unionOpenDatabaseInner(pTab, pSrc, pzErr); 553 if( rc==SQLITE_OK ){ 554 char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr); 555 if( rc==SQLITE_OK ){ 556 if( pTab->zSourceStr==0 ){ 557 pTab->zSourceStr = z; 558 }else{ 559 if( sqlite3_stricmp(z, pTab->zSourceStr) ){ 560 *pzErr = sqlite3_mprintf("source table schema mismatch"); 561 rc = SQLITE_ERROR; 562 } 563 sqlite3_free(z); 564 } 565 } 566 } 567 568 if( rc==SQLITE_OK ){ 569 pSrc->pNextClosable = pTab->pClosable; 570 pTab->pClosable = pSrc; 571 pTab->nOpen++; 572 }else{ 573 sqlite3_close(pSrc->db); 574 pSrc->db = 0; 575 } 576 } 577 578 return rc; 579 } 580 581 582 /* 583 ** This function is a no-op for unionvtab tables. For swarmvtab, increment 584 ** the reference count for source table iTab. If the reference count was 585 ** zero before it was incremented, also remove the source from the closable 586 ** list. 587 */ 588 static void unionIncrRefcount(UnionTab *pTab, int iTab){ 589 if( pTab->bSwarm ){ 590 UnionSrc *pSrc = &pTab->aSrc[iTab]; 591 assert( pSrc->nUser>=0 && pSrc->db ); 592 if( pSrc->nUser==0 ){ 593 UnionSrc **pp; 594 for(pp=&pTab->pClosable; *pp!=pSrc; pp=&(*pp)->pNextClosable); 595 *pp = pSrc->pNextClosable; 596 pSrc->pNextClosable = 0; 597 } 598 pSrc->nUser++; 599 } 600 } 601 602 /* 603 ** Finalize the SQL statement pCsr->pStmt and return the result. 604 ** 605 ** If this is a swarmvtab table (not unionvtab) and pCsr->pStmt was not 606 ** NULL when this function was called, also decrement the reference 607 ** count on the associated source table. If this means the source tables 608 ** refcount is now zero, add it to the closable list. 609 */ 610 static int unionFinalizeCsrStmt(UnionCsr *pCsr){ 611 int rc = SQLITE_OK; 612 if( pCsr->pStmt ){ 613 UnionTab *pTab = (UnionTab*)pCsr->base.pVtab; 614 UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab]; 615 rc = sqlite3_finalize(pCsr->pStmt); 616 pCsr->pStmt = 0; 617 if( pTab->bSwarm ){ 618 pSrc->nUser--; 619 assert( pSrc->nUser>=0 ); 620 if( pSrc->nUser==0 ){ 621 pSrc->pNextClosable = pTab->pClosable; 622 pTab->pClosable = pSrc; 623 } 624 unionCloseSources(pTab, pTab->nMaxOpen); 625 } 626 } 627 return rc; 628 } 629 630 /* 631 ** xConnect/xCreate method. 632 ** 633 ** The argv[] array contains the following: 634 ** 635 ** argv[0] -> module name ("unionvtab" or "swarmvtab") 636 ** argv[1] -> database name 637 ** argv[2] -> table name 638 ** argv[3] -> SQL statement 639 ** argv[4] -> not-found callback UDF name 640 */ 641 static int unionConnect( 642 sqlite3 *db, 643 void *pAux, 644 int argc, const char *const*argv, 645 sqlite3_vtab **ppVtab, 646 char **pzErr 647 ){ 648 UnionTab *pTab = 0; 649 int rc = SQLITE_OK; 650 int bSwarm = (pAux==0 ? 0 : 1); 651 const char *zVtab = (bSwarm ? "swarmvtab" : "unionvtab"); 652 653 if( sqlite3_stricmp("temp", argv[1]) ){ 654 /* unionvtab tables may only be created in the temp schema */ 655 *pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab); 656 rc = SQLITE_ERROR; 657 }else if( argc!=4 && argc!=5 ){ 658 *pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab); 659 rc = SQLITE_ERROR; 660 }else{ 661 int nAlloc = 0; /* Allocated size of pTab->aSrc[] */ 662 sqlite3_stmt *pStmt = 0; /* Argument statement */ 663 char *zArg = unionStrdup(&rc, argv[3]); /* Copy of argument to CVT */ 664 665 /* Prepare the SQL statement. Instead of executing it directly, sort 666 ** the results by the "minimum rowid" field. This makes it easier to 667 ** check that there are no rowid range overlaps between source tables 668 ** and that the UnionTab.aSrc[] array is always sorted by rowid. */ 669 unionDequote(zArg); 670 pStmt = unionPreparePrintf(&rc, pzErr, db, 671 "SELECT * FROM (%z) ORDER BY 3", zArg 672 ); 673 674 /* Allocate the UnionTab structure */ 675 pTab = unionMalloc(&rc, sizeof(UnionTab)); 676 677 /* Iterate through the rows returned by the SQL statement specified 678 ** as an argument to the CREATE VIRTUAL TABLE statement. */ 679 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ 680 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); 681 const char *zTab = (const char*)sqlite3_column_text(pStmt, 1); 682 sqlite3_int64 iMin = sqlite3_column_int64(pStmt, 2); 683 sqlite3_int64 iMax = sqlite3_column_int64(pStmt, 3); 684 UnionSrc *pSrc; 685 686 /* Grow the pTab->aSrc[] array if required. */ 687 if( nAlloc<=pTab->nSrc ){ 688 int nNew = nAlloc ? nAlloc*2 : 8; 689 UnionSrc *aNew = (UnionSrc*)sqlite3_realloc( 690 pTab->aSrc, nNew*sizeof(UnionSrc) 691 ); 692 if( aNew==0 ){ 693 rc = SQLITE_NOMEM; 694 break; 695 }else{ 696 memset(&aNew[pTab->nSrc], 0, (nNew-pTab->nSrc)*sizeof(UnionSrc)); 697 pTab->aSrc = aNew; 698 nAlloc = nNew; 699 } 700 } 701 702 /* Check for problems with the specified range of rowids */ 703 if( iMax<iMin || (pTab->nSrc>0 && iMin<=pTab->aSrc[pTab->nSrc-1].iMax) ){ 704 *pzErr = sqlite3_mprintf("rowid range mismatch error"); 705 rc = SQLITE_ERROR; 706 } 707 708 if( rc==SQLITE_OK ){ 709 pSrc = &pTab->aSrc[pTab->nSrc++]; 710 pSrc->zTab = unionStrdup(&rc, zTab); 711 pSrc->iMin = iMin; 712 pSrc->iMax = iMax; 713 if( bSwarm ){ 714 pSrc->zFile = unionStrdup(&rc, zDb); 715 }else{ 716 pSrc->zDb = unionStrdup(&rc, zDb); 717 } 718 } 719 } 720 unionFinalize(&rc, pStmt, pzErr); 721 pStmt = 0; 722 723 /* Capture the not-found callback UDF name */ 724 if( rc==SQLITE_OK && argc>=5 ){ 725 pTab->zNotFoundCallback = unionStrdup(&rc, argv[4]); 726 unionDequote(pTab->zNotFoundCallback); 727 } 728 729 /* It is an error if the SELECT statement returned zero rows. If only 730 ** because there is no way to determine the schema of the virtual 731 ** table in this case. */ 732 if( rc==SQLITE_OK && pTab->nSrc==0 ){ 733 *pzErr = sqlite3_mprintf("no source tables configured"); 734 rc = SQLITE_ERROR; 735 } 736 737 /* For unionvtab, verify that all source tables exist and have 738 ** compatible schemas. For swarmvtab, attach the first database and 739 ** check that the first table is a rowid table only. */ 740 if( rc==SQLITE_OK ){ 741 pTab->db = db; 742 pTab->bSwarm = bSwarm; 743 pTab->nMaxOpen = SWARMVTAB_MAX_OPEN; 744 if( bSwarm ){ 745 rc = unionOpenDatabase(pTab, 0, pzErr); 746 }else{ 747 rc = unionSourceCheck(pTab, pzErr); 748 } 749 } 750 751 /* Compose a CREATE TABLE statement and pass it to declare_vtab() */ 752 if( rc==SQLITE_OK ){ 753 UnionSrc *pSrc = &pTab->aSrc[0]; 754 sqlite3 *tdb = unionGetDb(pTab, pSrc); 755 pStmt = unionPreparePrintf(&rc, pzErr, tdb, "SELECT " 756 "'CREATE TABLE xyz('" 757 " || group_concat(quote(name) || ' ' || type, ', ')" 758 " || ')'," 759 "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 " 760 "FROM pragma_table_info(%Q, ?)", 761 pSrc->zTab, pSrc->zDb 762 ); 763 } 764 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ 765 const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0); 766 rc = sqlite3_declare_vtab(db, zDecl); 767 pTab->iPK = sqlite3_column_int(pStmt, 1); 768 } 769 770 unionFinalize(&rc, pStmt, pzErr); 771 } 772 773 if( rc!=SQLITE_OK ){ 774 unionDisconnect((sqlite3_vtab*)pTab); 775 pTab = 0; 776 } 777 778 *ppVtab = (sqlite3_vtab*)pTab; 779 return rc; 780 } 781 782 /* 783 ** xOpen 784 */ 785 static int unionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 786 UnionCsr *pCsr; 787 int rc = SQLITE_OK; 788 (void)p; /* Suppress harmless warning */ 789 pCsr = (UnionCsr*)unionMalloc(&rc, sizeof(UnionCsr)); 790 *ppCursor = &pCsr->base; 791 return rc; 792 } 793 794 /* 795 ** xClose 796 */ 797 static int unionClose(sqlite3_vtab_cursor *cur){ 798 UnionCsr *pCsr = (UnionCsr*)cur; 799 unionFinalizeCsrStmt(pCsr); 800 sqlite3_free(pCsr); 801 return SQLITE_OK; 802 } 803 804 /* 805 ** This function does the work of the xNext() method. Except that, if it 806 ** returns SQLITE_ROW, it should be called again within the same xNext() 807 ** method call. See unionNext() for details. 808 */ 809 static int doUnionNext(UnionCsr *pCsr){ 810 int rc = SQLITE_OK; 811 assert( pCsr->pStmt ); 812 if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){ 813 UnionTab *pTab = (UnionTab*)pCsr->base.pVtab; 814 rc = unionFinalizeCsrStmt(pCsr); 815 if( rc==SQLITE_OK && pTab->bSwarm ){ 816 pCsr->iTab++; 817 if( pCsr->iTab<pTab->nSrc ){ 818 UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab]; 819 if( pCsr->iMaxRowid>=pSrc->iMin ){ 820 /* It is necessary to scan the next table. */ 821 rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg); 822 pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pSrc->db, 823 "SELECT rowid, * FROM %Q %s %lld", 824 pSrc->zTab, 825 (pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "), 826 pCsr->iMaxRowid 827 ); 828 if( rc==SQLITE_OK ){ 829 assert( pCsr->pStmt ); 830 unionIncrRefcount(pTab, pCsr->iTab); 831 rc = SQLITE_ROW; 832 } 833 } 834 } 835 } 836 } 837 838 return rc; 839 } 840 841 /* 842 ** xNext 843 */ 844 static int unionNext(sqlite3_vtab_cursor *cur){ 845 int rc; 846 do { 847 rc = doUnionNext((UnionCsr*)cur); 848 }while( rc==SQLITE_ROW ); 849 return rc; 850 } 851 852 /* 853 ** xColumn 854 */ 855 static int unionColumn( 856 sqlite3_vtab_cursor *cur, 857 sqlite3_context *ctx, 858 int i 859 ){ 860 UnionCsr *pCsr = (UnionCsr*)cur; 861 sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1)); 862 return SQLITE_OK; 863 } 864 865 /* 866 ** xRowid 867 */ 868 static int unionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 869 UnionCsr *pCsr = (UnionCsr*)cur; 870 *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); 871 return SQLITE_OK; 872 } 873 874 /* 875 ** xEof 876 */ 877 static int unionEof(sqlite3_vtab_cursor *cur){ 878 UnionCsr *pCsr = (UnionCsr*)cur; 879 return pCsr->pStmt==0; 880 } 881 882 /* 883 ** xFilter 884 */ 885 static int unionFilter( 886 sqlite3_vtab_cursor *pVtabCursor, 887 int idxNum, const char *idxStr, 888 int argc, sqlite3_value **argv 889 ){ 890 UnionTab *pTab = (UnionTab*)(pVtabCursor->pVtab); 891 UnionCsr *pCsr = (UnionCsr*)pVtabCursor; 892 int rc = SQLITE_OK; 893 int i; 894 char *zSql = 0; 895 int bZero = 0; 896 897 sqlite3_int64 iMin = SMALLEST_INT64; 898 sqlite3_int64 iMax = LARGEST_INT64; 899 900 assert( idxNum==0 901 || idxNum==SQLITE_INDEX_CONSTRAINT_EQ 902 || idxNum==SQLITE_INDEX_CONSTRAINT_LE 903 || idxNum==SQLITE_INDEX_CONSTRAINT_GE 904 || idxNum==SQLITE_INDEX_CONSTRAINT_LT 905 || idxNum==SQLITE_INDEX_CONSTRAINT_GT 906 || idxNum==(SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_LE) 907 ); 908 909 (void)idxStr; /* Suppress harmless warning */ 910 911 if( idxNum==SQLITE_INDEX_CONSTRAINT_EQ ){ 912 assert( argc==1 ); 913 iMin = iMax = sqlite3_value_int64(argv[0]); 914 }else{ 915 916 if( idxNum & (SQLITE_INDEX_CONSTRAINT_LE|SQLITE_INDEX_CONSTRAINT_LT) ){ 917 assert( argc>=1 ); 918 iMax = sqlite3_value_int64(argv[0]); 919 if( idxNum & SQLITE_INDEX_CONSTRAINT_LT ){ 920 if( iMax==SMALLEST_INT64 ){ 921 bZero = 1; 922 }else{ 923 iMax--; 924 } 925 } 926 } 927 928 if( idxNum & (SQLITE_INDEX_CONSTRAINT_GE|SQLITE_INDEX_CONSTRAINT_GT) ){ 929 assert( argc>=1 ); 930 iMin = sqlite3_value_int64(argv[argc-1]); 931 if( idxNum & SQLITE_INDEX_CONSTRAINT_GT ){ 932 if( iMin==LARGEST_INT64 ){ 933 bZero = 1; 934 }else{ 935 iMin++; 936 } 937 } 938 } 939 } 940 941 unionFinalizeCsrStmt(pCsr); 942 if( bZero ){ 943 return SQLITE_OK; 944 } 945 946 for(i=0; i<pTab->nSrc; i++){ 947 UnionSrc *pSrc = &pTab->aSrc[i]; 948 if( iMin>pSrc->iMax || iMax<pSrc->iMin ){ 949 continue; 950 } 951 952 zSql = sqlite3_mprintf("%z%sSELECT rowid, * FROM %s%q%s%Q" 953 , zSql 954 , (zSql ? " UNION ALL " : "") 955 , (pSrc->zDb ? "'" : "") 956 , (pSrc->zDb ? pSrc->zDb : "") 957 , (pSrc->zDb ? "'." : "") 958 , pSrc->zTab 959 ); 960 if( zSql==0 ){ 961 rc = SQLITE_NOMEM; 962 break; 963 } 964 965 if( iMin==iMax ){ 966 zSql = sqlite3_mprintf("%z WHERE rowid=%lld", zSql, iMin); 967 }else{ 968 const char *zWhere = "WHERE"; 969 if( iMin!=SMALLEST_INT64 && iMin>pSrc->iMin ){ 970 zSql = sqlite3_mprintf("%z WHERE rowid>=%lld", zSql, iMin); 971 zWhere = "AND"; 972 } 973 if( iMax!=LARGEST_INT64 && iMax<pSrc->iMax ){ 974 zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax); 975 } 976 } 977 978 if( pTab->bSwarm ){ 979 pCsr->iTab = i; 980 pCsr->iMaxRowid = iMax; 981 rc = unionOpenDatabase(pTab, i, &pTab->base.zErrMsg); 982 break; 983 } 984 } 985 986 if( zSql==0 ){ 987 return rc; 988 }else{ 989 sqlite3 *db = unionGetDb(pTab, &pTab->aSrc[pCsr->iTab]); 990 pCsr->pStmt = unionPrepare(&rc, db, zSql, &pTab->base.zErrMsg); 991 if( pCsr->pStmt ){ 992 unionIncrRefcount(pTab, pCsr->iTab); 993 } 994 sqlite3_free(zSql); 995 } 996 if( rc!=SQLITE_OK ) return rc; 997 return unionNext(pVtabCursor); 998 } 999 1000 /* 1001 ** xBestIndex. 1002 ** 1003 ** This implementation searches for constraints on the rowid field. EQ, 1004 ** LE, LT, GE and GT are handled. 1005 ** 1006 ** If there is an EQ comparison, then idxNum is set to INDEX_CONSTRAINT_EQ. 1007 ** In this case the only argument passed to xFilter is the rhs of the == 1008 ** operator. 1009 ** 1010 ** Otherwise, if an LE or LT constraint is found, then the INDEX_CONSTRAINT_LE 1011 ** or INDEX_CONSTRAINT_LT (but not both) bit is set in idxNum. The first 1012 ** argument to xFilter is the rhs of the <= or < operator. Similarly, if 1013 ** an GE or GT constraint is found, then the INDEX_CONSTRAINT_GE or 1014 ** INDEX_CONSTRAINT_GT bit is set in idxNum. The rhs of the >= or > operator 1015 ** is passed as either the first or second argument to xFilter, depending 1016 ** on whether or not there is also a LT|LE constraint. 1017 */ 1018 static int unionBestIndex( 1019 sqlite3_vtab *tab, 1020 sqlite3_index_info *pIdxInfo 1021 ){ 1022 UnionTab *pTab = (UnionTab*)tab; 1023 int iEq = -1; 1024 int iLt = -1; 1025 int iGt = -1; 1026 int i; 1027 1028 for(i=0; i<pIdxInfo->nConstraint; i++){ 1029 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; 1030 if( p->usable && (p->iColumn<0 || p->iColumn==pTab->iPK) ){ 1031 switch( p->op ){ 1032 case SQLITE_INDEX_CONSTRAINT_EQ: 1033 iEq = i; 1034 break; 1035 case SQLITE_INDEX_CONSTRAINT_LE: 1036 case SQLITE_INDEX_CONSTRAINT_LT: 1037 iLt = i; 1038 break; 1039 case SQLITE_INDEX_CONSTRAINT_GE: 1040 case SQLITE_INDEX_CONSTRAINT_GT: 1041 iGt = i; 1042 break; 1043 } 1044 } 1045 } 1046 1047 if( iEq>=0 ){ 1048 pIdxInfo->estimatedRows = 1; 1049 pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; 1050 pIdxInfo->estimatedCost = 3.0; 1051 pIdxInfo->idxNum = SQLITE_INDEX_CONSTRAINT_EQ; 1052 pIdxInfo->aConstraintUsage[iEq].argvIndex = 1; 1053 pIdxInfo->aConstraintUsage[iEq].omit = 1; 1054 }else{ 1055 int iCons = 1; 1056 int idxNum = 0; 1057 sqlite3_int64 nRow = 1000000; 1058 if( iLt>=0 ){ 1059 nRow = nRow / 2; 1060 pIdxInfo->aConstraintUsage[iLt].argvIndex = iCons++; 1061 pIdxInfo->aConstraintUsage[iLt].omit = 1; 1062 idxNum |= pIdxInfo->aConstraint[iLt].op; 1063 } 1064 if( iGt>=0 ){ 1065 nRow = nRow / 2; 1066 pIdxInfo->aConstraintUsage[iGt].argvIndex = iCons++; 1067 pIdxInfo->aConstraintUsage[iGt].omit = 1; 1068 idxNum |= pIdxInfo->aConstraint[iGt].op; 1069 } 1070 pIdxInfo->estimatedRows = nRow; 1071 pIdxInfo->estimatedCost = 3.0 * (double)nRow; 1072 pIdxInfo->idxNum = idxNum; 1073 } 1074 1075 return SQLITE_OK; 1076 } 1077 1078 /* 1079 ** Register the unionvtab virtual table module with database handle db. 1080 */ 1081 static int createUnionVtab(sqlite3 *db){ 1082 static sqlite3_module unionModule = { 1083 0, /* iVersion */ 1084 unionConnect, 1085 unionConnect, 1086 unionBestIndex, /* xBestIndex - query planner */ 1087 unionDisconnect, 1088 unionDisconnect, 1089 unionOpen, /* xOpen - open a cursor */ 1090 unionClose, /* xClose - close a cursor */ 1091 unionFilter, /* xFilter - configure scan constraints */ 1092 unionNext, /* xNext - advance a cursor */ 1093 unionEof, /* xEof - check for end of scan */ 1094 unionColumn, /* xColumn - read data */ 1095 unionRowid, /* xRowid - read data */ 1096 0, /* xUpdate */ 1097 0, /* xBegin */ 1098 0, /* xSync */ 1099 0, /* xCommit */ 1100 0, /* xRollback */ 1101 0, /* xFindMethod */ 1102 0, /* xRename */ 1103 0, /* xSavepoint */ 1104 0, /* xRelease */ 1105 0 /* xRollbackTo */ 1106 }; 1107 int rc; 1108 1109 rc = sqlite3_create_module(db, "unionvtab", &unionModule, 0); 1110 if( rc==SQLITE_OK ){ 1111 rc = sqlite3_create_module(db, "swarmvtab", &unionModule, (void*)db); 1112 } 1113 return rc; 1114 } 1115 1116 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 1117 1118 #ifdef _WIN32 1119 __declspec(dllexport) 1120 #endif 1121 int sqlite3_unionvtab_init( 1122 sqlite3 *db, 1123 char **pzErrMsg, 1124 const sqlite3_api_routines *pApi 1125 ){ 1126 int rc = SQLITE_OK; 1127 SQLITE_EXTENSION_INIT2(pApi); 1128 (void)pzErrMsg; /* Suppress harmless warning */ 1129 #ifndef SQLITE_OMIT_VIRTUALTABLE 1130 rc = createUnionVtab(db); 1131 #endif 1132 return rc; 1133 }