Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch reuse-schema1 Excluding Merge-Ins
This is equivalent to a diff from ae88f8e1ff to dfab7170ed
2019-02-02
| ||
21:02 | Try new approach ensuring that each Schema object is only used by one connection/database at any one time. (check-in: 9e8e5f52cf user: dan tags: reuse-schema) | |
2018-11-20
| ||
16:02 | Consolidate the two sqlite3SchemaToIndex() routines. (Leaf check-in: dfab7170ed user: dan tags: reuse-schema1) | |
2018-11-19
| ||
20:41 | Fix a problem with virtual tables in shared schemas. (check-in: 84be9220db user: dan tags: reuse-schema1) | |
2018-11-15
| ||
21:20 | Fix some problems with the feature on this branch. Many problems remain. (check-in: 31b6aee755 user: dan tags: reuse-schema1) | |
2018-11-09
| ||
18:44 | Merge latest trunk changes with this branch. (check-in: ae88f8e1ff user: dan tags: reuse-schema) | |
14:17 | Fix for ticket [787fa716be3a7f650cac] (check-in: 531eca6104 user: drh tags: trunk) | |
2018-10-08
| ||
23:29 | Add the ability to open a database connection in -reuseschema mode in the CLI. Adjust memory allocation accounting so that a shared schema is allocated across each database sharing it. (check-in: 3869b2106b user: drh tags: reuse-schema) | |
Changes to Makefile.in.
︙ | ︙ | |||
673 674 675 676 677 678 679 | -DSQLITE_DEBUG \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_EANBLE_FTS5 dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | -DSQLITE_DEBUG \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_EANBLE_FTS5 dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c mkdir -p dbfuzz2-dir cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \ $(TLIBS) -rpath "$(libdir)" |
︙ | ︙ | |||
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | showshm$(TEXE): $(TOP)/tool/showshm.c $(LTLINK) -o $@ $(TOP)/tool/showshm.c changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS) rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS) atrc$(TEXX): $(TOP)/test/atrc.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/test/atrc.c sqlite3.lo $(TLIBS) LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h | > > > | 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 | showshm$(TEXE): $(TOP)/tool/showshm.c $(LTLINK) -o $@ $(TOP)/tool/showshm.c changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS) changesetfuzz$(TEXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(TLIBS) rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS) atrc$(TEXX): $(TOP)/test/atrc.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/test/atrc.c sqlite3.lo $(TLIBS) LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 | $(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS) changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \ $(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) | > > > > > | 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 | $(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS) changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \ $(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) changesetfuzz.exe: $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \ $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) |
︙ | ︙ |
Changes to ext/expert/sqlite3expert.c.
︙ | ︙ | |||
640 641 642 643 644 645 646 647 648 649 650 651 652 653 | 0, /* xCommit - commit transaction */ 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); } /* ** End of virtual table implementation. *************************************************************************/ | > | 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 | 0, /* xCommit - commit transaction */ 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); } /* ** End of virtual table implementation. *************************************************************************/ |
︙ | ︙ |
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
3841 3842 3843 3844 3845 3846 3847 3848 3849 | UNUSED_PARAMETER(iSavepoint); assert( p->inTransaction ); assert( p->mxSavepoint >= iSavepoint ); TESTONLY( p->mxSavepoint = iSavepoint ); sqlite3Fts3PendingTermsClear(p); return SQLITE_OK; } static const sqlite3_module fts3Module = { | > > > > > > > > > > > > > > > | | 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 | UNUSED_PARAMETER(iSavepoint); assert( p->inTransaction ); assert( p->mxSavepoint >= iSavepoint ); TESTONLY( p->mxSavepoint = iSavepoint ); sqlite3Fts3PendingTermsClear(p); return SQLITE_OK; } /* ** Return true if zName is the extension on one of the shadow tables used ** by this module. */ static int fts3ShadowName(const char *zName){ static const char *azName[] = { "content", "docsize", "segdir", "segments", "stat", }; unsigned int i; for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; } return 0; } static const sqlite3_module fts3Module = { /* iVersion */ 3, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, /* xDisconnect */ fts3DisconnectMethod, /* xDestroy */ fts3DestroyMethod, /* xOpen */ fts3OpenMethod, /* xClose */ fts3CloseMethod, |
︙ | ︙ | |||
3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 | /* xCommit */ fts3CommitMethod, /* xRollback */ fts3RollbackMethod, /* xFindFunction */ fts3FindFunctionMethod, /* xRename */ fts3RenameMethod, /* xSavepoint */ fts3SavepointMethod, /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, }; /* ** This function is registered as the module destructor (called when an ** FTS3 enabled database connection is closed). It frees the memory ** allocated for the tokenizer hash table. */ | > | 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 | /* xCommit */ fts3CommitMethod, /* xRollback */ fts3RollbackMethod, /* xFindFunction */ fts3FindFunctionMethod, /* xRename */ fts3RenameMethod, /* xSavepoint */ fts3SavepointMethod, /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, /* xShadowName */ fts3ShadowName, }; /* ** This function is registered as the module destructor (called when an ** FTS3 enabled database connection is closed). It frees the memory ** allocated for the tokenizer hash table. */ |
︙ | ︙ |
Changes to ext/fts3/fts3_aux.c.
︙ | ︙ | |||
535 536 537 538 539 540 541 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; int rc; /* Return code */ rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); return rc; } |
︙ | ︙ |
Changes to ext/fts3/fts3_term.c.
︙ | ︙ | |||
357 358 359 360 361 362 363 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; int rc; /* Return code */ rc = sqlite3_create_module(db, "fts4term", &fts3term_module, 0); return rc; } |
︙ | ︙ |
Changes to ext/fts3/fts3_tokenize_vtab.c.
︙ | ︙ | |||
439 440 441 442 443 444 445 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; int rc; /* Return code */ rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); return rc; } |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
5398 5399 5400 5401 5402 5403 5404 | if( p->rc ){ sqlite3Fts5IterClose((Fts5IndexIter*)pRet); pRet = 0; fts5CloseReader(p); } | | | 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 | if( p->rc ){ sqlite3Fts5IterClose((Fts5IndexIter*)pRet); pRet = 0; fts5CloseReader(p); } *ppIter = (Fts5IndexIter*)pRet; sqlite3Fts5BufferFree(&buf); } return fts5IndexReturn(p); } /* ** Return true if the iterator passed as the only argument is at EOF. |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 | int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { | > > > > > > > > > > > > > > > | | 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 | int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); } /* ** Return true if zName is the extension on one of the shadow tables used ** by this module. */ static int fts5ShadowName(const char *zName){ static const char *azName[] = { "config", "content", "data", "docsize", "idx" }; unsigned int i; for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; } return 0; } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { /* iVersion */ 3, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, /* xDisconnect */ fts5DisconnectMethod, /* xDestroy */ fts5DestroyMethod, /* xOpen */ fts5OpenMethod, /* xClose */ fts5CloseMethod, |
︙ | ︙ | |||
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 | /* xCommit */ fts5CommitMethod, /* xRollback */ fts5RollbackMethod, /* xFindFunction */ fts5FindFunctionMethod, /* xRename */ fts5RenameMethod, /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, }; int rc; Fts5Global *pGlobal = 0; pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global)); if( pGlobal==0 ){ | > | 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 | /* xCommit */ fts5CommitMethod, /* xRollback */ fts5RollbackMethod, /* xFindFunction */ fts5FindFunctionMethod, /* xRename */ fts5RenameMethod, /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, /* xShadowName */ fts5ShadowName }; int rc; Fts5Global *pGlobal = 0; pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global)); if( pGlobal==0 ){ |
︙ | ︙ |
Changes to ext/fts5/fts5_test_tok.c.
︙ | ︙ | |||
467 468 469 470 471 472 473 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; int rc; /* Return code */ rc = sqlite3_create_module(db, "fts5tokenize", &fts5tok_module, (void*)pApi); return rc; } |
︙ | ︙ |
Changes to ext/fts5/fts5_vocab.c.
︙ | ︙ | |||
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){ int eDetail = pCsr->pConfig->eDetail; int rc = SQLITE_OK; Fts5IndexIter *pIter = pCsr->pIter; i64 *pp = &pCsr->iInstPos; int *po = &pCsr->iInstOff; while( eDetail==FTS5_DETAIL_NONE || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) ){ pCsr->iInstPos = 0; pCsr->iInstOff = 0; rc = sqlite3Fts5IterNextScan(pCsr->pIter); if( rc==SQLITE_OK ){ rc = fts5VocabInstanceNewTerm(pCsr); | > > | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){ int eDetail = pCsr->pConfig->eDetail; int rc = SQLITE_OK; Fts5IndexIter *pIter = pCsr->pIter; i64 *pp = &pCsr->iInstPos; int *po = &pCsr->iInstOff; assert( sqlite3Fts5IterEof(pIter)==0 ); assert( pCsr->bEof==0 ); while( eDetail==FTS5_DETAIL_NONE || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) ){ pCsr->iInstPos = 0; pCsr->iInstOff = 0; rc = sqlite3Fts5IterNextScan(pCsr->pIter); if( rc==SQLITE_OK ){ rc = fts5VocabInstanceNewTerm(pCsr); if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; } if( rc ){ pCsr->bEof = 1; break; } } |
︙ | ︙ | |||
751 752 753 754 755 756 757 758 759 760 761 762 | /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, }; void *p = (void*)pGlobal; return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); } | > < < | 753 754 755 756 757 758 759 760 761 762 763 764 765 | /* xCommit */ 0, /* xRollback */ 0, /* xFindFunction */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ 0 }; void *p = (void*)pGlobal; return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); } |
Changes to ext/fts5/test/fts5aa.test.
︙ | ︙ | |||
405 406 407 408 409 410 411 412 413 414 415 416 417 418 | } set nRow } {200} do_execsql_test 15.0 { INSERT INTO t1(t1) VALUES('integrity-check'); } do_execsql_test 15.1 { UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; } do_catchsql_test 15.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} | > | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | } set nRow } {200} do_execsql_test 15.0 { INSERT INTO t1(t1) VALUES('integrity-check'); } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 15.1 { UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; } do_catchsql_test 15.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} |
︙ | ︙ |
Changes to ext/fts5/test/fts5connect.test.
︙ | ︙ | |||
240 241 242 243 244 245 246 | do_execsql_test 4.$tn.3 { INSERT INTO ft3(ft3) VALUES('integrity-check'); } } finish_test | < | 240 241 242 243 244 245 246 | do_execsql_test 4.$tn.3 { INSERT INTO ft3(ft3) VALUES('integrity-check'); } } finish_test |
Changes to ext/fts5/test/fts5corrupt.test.
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | fts5_level_segs t1 } {1} db_save do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') } set segid [lindex [fts5_level_segids t1] 0] do_test 1.3 { execsql { DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {database disk image is malformed}} do_test 1.4 { db_restore_and_reopen execsql { UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {database disk image is malformed}} | > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | fts5_level_segs t1 } {1} db_save do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') } set segid [lindex [fts5_level_segids t1] 0] sqlite3_db_config db DEFENSIVE 0 do_test 1.3 { execsql { DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {database disk image is malformed}} do_test 1.4 { db_restore_and_reopen sqlite3_db_config db DEFENSIVE 0 execsql { UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {database disk image is malformed}} |
︙ | ︙ | |||
85 86 87 88 89 90 91 | INSERT INTO t3 VALUES('three o'); INSERT INTO t3 VALUES('four e'); INSERT INTO t3 VALUES('five o'); } do_execsql_test 3.1 { SELECT * FROM t3 WHERE t3 MATCH 'o' } {{one o} {three o} {five o}} | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | INSERT INTO t3 VALUES('three o'); INSERT INTO t3 VALUES('four e'); INSERT INTO t3 VALUES('five o'); } do_execsql_test 3.1 { SELECT * FROM t3 WHERE t3 MATCH 'o' } {{one o} {three o} {five o}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 3.1 { DELETE FROM t3_content WHERE rowid = 3; SELECT * FROM t3 WHERE t3 MATCH 'o'; } {1 {database disk image is malformed}} finish_test |
Changes to ext/fts5/test/fts5corrupt2.test.
︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # Also tested is that "MATCH 'x*'" does not crash and sometimes reports # corruption. It may not report the db as corrupt because truncating the # final leaf to some sizes may create a valid leaf page. # set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}] set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}] set all [db eval {SELECT rowid FROM t1}] for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} { do_execsql_test 2.$i.1 { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE rowid=$lrowid; } do_catchsql_test 2.$i.2 { | > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # Also tested is that "MATCH 'x*'" does not crash and sometimes reports # corruption. It may not report the db as corrupt because truncating the # final leaf to some sizes may create a valid leaf page. # set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}] set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}] set all [db eval {SELECT rowid FROM t1}] sqlite3_db_config db DEFENSIVE 0 for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} { do_execsql_test 2.$i.1 { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE rowid=$lrowid; } do_catchsql_test 2.$i.2 { |
︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 256 257 | execsql ROLLBACK } } #-------------------------------------------------------------------- reset_db do_execsql_test 6.1 { CREATE VIRTUAL TABLE x5 USING fts5(tt); INSERT INTO x5 VALUES('a'); INSERT INTO x5 VALUES('a a'); INSERT INTO x5 VALUES('a a a'); INSERT INTO x5 VALUES('a a a a'); | > | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | execsql ROLLBACK } } #-------------------------------------------------------------------- reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.1 { CREATE VIRTUAL TABLE x5 USING fts5(tt); INSERT INTO x5 VALUES('a'); INSERT INTO x5 VALUES('a a'); INSERT INTO x5 VALUES('a a a'); INSERT INTO x5 VALUES('a a a a'); |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt3.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 | set rowid [db one { SELECT max(rowid) FROM t1_data WHERE ((rowid>>31) & 0x0F)==1 }] set L [db one {SELECT length(block) FROM t1_data WHERE rowid = $rowid}] set {} {} } {} for {set i 0} {$i < $L} {incr i} { do_test 1.2.$i { catchsql { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid; INSERT INTO t1(t1) VALUES('integrity-check'); } | > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | set rowid [db one { SELECT max(rowid) FROM t1_data WHERE ((rowid>>31) & 0x0F)==1 }] set L [db one {SELECT length(block) FROM t1_data WHERE rowid = $rowid}] set {} {} } {} sqlite3_db_config db DEFENSIVE 0 for {set i 0} {$i < $L} {incr i} { do_test 1.2.$i { catchsql { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid; INSERT INTO t1(t1) VALUES('integrity-check'); } |
︙ | ︙ | |||
82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #------------------------------------------------------------------------- # Test that missing leaf pages are recognized as corruption. # reset_db do_test 3.0 { create_t1 } {} do_execsql_test 3.1 { SELECT count(*) FROM t1_data; } {105} proc do_3_test {tn} { set i 0 | > | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #------------------------------------------------------------------------- # Test that missing leaf pages are recognized as corruption. # reset_db do_test 3.0 { create_t1 } {} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.1 { SELECT count(*) FROM t1_data; } {105} proc do_3_test {tn} { set i 0 |
︙ | ︙ | |||
154 155 156 157 158 159 160 161 162 163 164 165 166 167 | do_3_test 3.10 #------------------------------------------------------------------------- # Test that segments that end unexpectedly are identified as corruption. # reset_db do_test 4.0 { execsql { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); } for {set i 0} {$i < 100} {incr i} { set rnd [expr int(rand() * 100)] | > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | do_3_test 3.10 #------------------------------------------------------------------------- # Test that segments that end unexpectedly are identified as corruption. # reset_db sqlite3_db_config db DEFENSIVE 0 do_test 4.0 { execsql { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); } for {set i 0} {$i < 100} {incr i} { set rnd [expr int(rand() * 100)] |
︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 | set end [lindex $var end] if {$end<=$i} break lset var end [expr $end - $i] set struct [binary format c* $var] db close sqlite3 db test.db db eval { BEGIN; UPDATE t1_data SET block = $struct WHERE id=10; } do_test 4.1.$i { incr nErr [catch { db eval { SELECT rowid FROM t1 WHERE t1 MATCH 'x*' } }] | > | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | set end [lindex $var end] if {$end<=$i} break lset var end [expr $end - $i] set struct [binary format c* $var] db close sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { BEGIN; UPDATE t1_data SET block = $struct WHERE id=10; } do_test 4.1.$i { incr nErr [catch { db eval { SELECT rowid FROM t1 WHERE t1 MATCH 'x*' } }] |
︙ | ︙ | |||
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | catch { db eval ROLLBACK } } } #------------------------------------------------------------------------ # reset_db do_execsql_test 6.1.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('bbbbb ccccc'); SELECT quote(block) FROM t1_data WHERE rowid>100; } {X'000000180630626262626201020201056363636363010203040A'} do_execsql_test 6.1.1 { UPDATE t1_data SET block = X'000000180630626262626201020201056161616161010203040A' WHERE rowid>100; } do_catchsql_test 6.1.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #------- reset_db do_execsql_test 6.2.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); INSERT INTO t1 VALUES('aa bb cc dd ee'); SELECT pgno, quote(term) FROM t1_idx; } {2 X'' 4 X'3064'} do_execsql_test 6.2.1 { UPDATE t1_idx SET term = X'3065' WHERE pgno=4; } do_catchsql_test 6.2.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #------- reset_db do_execsql_test 6.3.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('abc abcdef abcdefghi'); SELECT quote(block) FROM t1_data WHERE id>100; } {X'0000001C043061626301020204036465660102030703676869010204040808'} do_execsql_test 6.3.1 { BEGIN; | > > > | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | catch { db eval ROLLBACK } } } #------------------------------------------------------------------------ # reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.1.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('bbbbb ccccc'); SELECT quote(block) FROM t1_data WHERE rowid>100; } {X'000000180630626262626201020201056363636363010203040A'} do_execsql_test 6.1.1 { UPDATE t1_data SET block = X'000000180630626262626201020201056161616161010203040A' WHERE rowid>100; } do_catchsql_test 6.1.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #------- reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.2.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); INSERT INTO t1 VALUES('aa bb cc dd ee'); SELECT pgno, quote(term) FROM t1_idx; } {2 X'' 4 X'3064'} do_execsql_test 6.2.1 { UPDATE t1_idx SET term = X'3065' WHERE pgno=4; } do_catchsql_test 6.2.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #------- reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.3.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('abc abcdef abcdefghi'); SELECT quote(block) FROM t1_data WHERE id>100; } {X'0000001C043061626301020204036465660102030703676869010204040808'} do_execsql_test 6.3.1 { BEGIN; |
︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 | INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5(t5) VALUES('optimize'); } } {} do_test 7.1 { foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { db eval BEGIN db eval {DELETE FROM t5_data WHERE rowid = $i} set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ] if {$r != "1 {database disk image is malformed}"} { error $r } db eval ROLLBACK | > | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5 VALUES( rnddoc(10000) ); INSERT INTO t5(t5) VALUES('optimize'); } } {} sqlite3_db_config db DEFENSIVE 0 do_test 7.1 { foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { db eval BEGIN db eval {DELETE FROM t5_data WHERE rowid = $i} set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ] if {$r != "1 {database disk image is malformed}"} { error $r } db eval ROLLBACK |
︙ | ︙ | |||
379 380 381 382 383 384 385 386 387 388 389 390 391 392 | # reset_db do_execsql_test 8.1 { CREATE VIRTUAL TABLE t1 USING fts5(x, y); INSERT INTO t1 VALUES('one', 'two'); } do_test 9.1.1 { set blob "12345678" ;# cookie append blob "0105" ;# 1 level, total of 5 segments append blob "06" ;# write counter append blob "0002" ;# first level has 0 segments merging, 2 other. append blob "450108" ;# first segment execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" | > | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | # reset_db do_execsql_test 8.1 { CREATE VIRTUAL TABLE t1 USING fts5(x, y); INSERT INTO t1 VALUES('one', 'two'); } sqlite3_db_config db DEFENSIVE 0 do_test 9.1.1 { set blob "12345678" ;# cookie append blob "0105" ;# 1 level, total of 5 segments append blob "06" ;# write counter append blob "0002" ;# first level has 0 segments merging, 2 other. append blob "450108" ;# first segment execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" |
︙ | ︙ |
Changes to ext/fts5/test/fts5first.test.
︙ | ︙ | |||
89 90 91 92 93 94 95 | SELECT * FROM x2('a + b'); } {1 {fts5: phrase queries are not supported (detail!=full)}} do_catchsql_test 3.3 { SELECT * FROM x2('^a'); } {1 {fts5: phrase queries are not supported (detail!=full)}} finish_test | < | 89 90 91 92 93 94 95 | SELECT * FROM x2('a + b'); } {1 {fts5: phrase queries are not supported (detail!=full)}} do_catchsql_test 3.3 { SELECT * FROM x2('^a'); } {1 {fts5: phrase queries are not supported (detail!=full)}} finish_test |
Changes to ext/fts5/test/fts5integrity.test.
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | INSERT INTO aa(zz) VALUES('a'); SELECT length(sz) FROM aa_docsize; } {1 1 1 1 1} do_execsql_test 4.1 { INSERT INTO aa(aa) VALUES('integrity-check'); } do_catchsql_test 4.2 { BEGIN; UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3; INSERT INTO aa(aa) VALUES('integrity-check'); } {1 {database disk image is malformed}} do_catchsql_test 4.3 { | > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | INSERT INTO aa(zz) VALUES('a'); SELECT length(sz) FROM aa_docsize; } {1 1 1 1 1} do_execsql_test 4.1 { INSERT INTO aa(aa) VALUES('integrity-check'); } sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 4.2 { BEGIN; UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3; INSERT INTO aa(aa) VALUES('integrity-check'); } {1 {database disk image is malformed}} do_catchsql_test 4.3 { |
︙ | ︙ |
Changes to ext/fts5/test/fts5rank.test.
︙ | ︙ | |||
159 160 161 162 163 164 165 | } do_execsql_test 5.1 { SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank; } {30 31 32 33 34 35 36 37 38 39 40} finish_test | < | 159 160 161 162 163 164 165 | } do_execsql_test 5.1 { SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank; } {30 31 32 33 34 35 36 37 38 39 40} finish_test |
Changes to ext/fts5/test/fts5rebuild.test.
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | INSERT INTO f1(f1) VALUES('rebuild'); } {} do_execsql_test 1.4 { INSERT INTO f1(f1) VALUES('integrity-check'); } {} do_execsql_test 1.5 { DELETE FROM f1_data; } {} do_catchsql_test 1.6 { INSERT INTO f1(f1) VALUES('integrity-check'); } {1 {database disk image is malformed}} | > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | INSERT INTO f1(f1) VALUES('rebuild'); } {} do_execsql_test 1.4 { INSERT INTO f1(f1) VALUES('integrity-check'); } {} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.5 { DELETE FROM f1_data; } {} do_catchsql_test 1.6 { INSERT INTO f1(f1) VALUES('integrity-check'); } {1 {database disk image is malformed}} |
︙ | ︙ |
Changes to ext/fts5/test/fts5rowid.test.
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 | DELETE FROM x1 WHERE (rowid%2); } set res [db one {SELECT count(*) FROM x1_data}] do_execsql_test 2.3 { SELECT count(fts5_decode(rowid, block)) FROM x1_data; } $res do_execsql_test 2.4 { UPDATE x1_data SET block = X''; SELECT count(fts5_decode(rowid, block)) FROM x1_data; } $res do_execsql_test 2.5 { INSERT INTO x1(x1, rank) VALUES('pgsz', 1024); | > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | DELETE FROM x1 WHERE (rowid%2); } set res [db one {SELECT count(*) FROM x1_data}] do_execsql_test 2.3 { SELECT count(fts5_decode(rowid, block)) FROM x1_data; } $res sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.4 { UPDATE x1_data SET block = X''; SELECT count(fts5_decode(rowid, block)) FROM x1_data; } $res do_execsql_test 2.5 { INSERT INTO x1(x1, rank) VALUES('pgsz', 1024); |
︙ | ︙ |
Changes to ext/fts5/test/fts5version.test.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 | SELECT * FROM t1_config WHERE k='version' } {version 4} do_execsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'a'; } {1} do_execsql_test 1.4 { UPDATE t1_config set v=5 WHERE k='version'; | > | > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | SELECT * FROM t1_config WHERE k='version' } {version 4} do_execsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'a'; } {1} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.4 { UPDATE t1_config set v=5 WHERE k='version'; } do_test 1.5 { db close sqlite3 db test.db catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } } {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} do_test 1.6 { db close sqlite3 db test.db catchsql { INSERT INTO t1 VALUES('x y z') } } {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} do_test 1.7 { sqlite3_db_config db DEFENSIVE 0 execsql { DELETE FROM t1_config WHERE k='version' } db close sqlite3 db test.db catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } } {1 {invalid fts5 file format (found 0, expected 4) - run 'rebuild'}} finish_test |
Changes to ext/fts5/test/fts5vocab.test.
︙ | ︙ | |||
416 417 418 419 420 421 422 423 424 425 426 427 428 429 | i a 1 1 i b 1 1 i c 1 1 }] if {[detail_is_none]} { set resc [row_to_col $resr] } do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc do_execsql_test 8.2 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(a, detail=%DETAIL%)' WHERE name = 'x1'; } db close | > | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | i a 1 1 i b 1 1 i c 1 1 }] if {[detail_is_none]} { set resc [row_to_col $resr] } do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc sqlite3_db_config db DEFENSIVE 0 do_execsql_test 8.2 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(a, detail=%DETAIL%)' WHERE name = 'x1'; } db close |
︙ | ︙ | |||
477 478 479 480 481 482 483 | set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term DESC }] expr [lsearch $e2 SorterSort]<0 } 0 finish_test | < | 478 479 480 481 482 483 484 | set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term DESC }] expr [lsearch $e2 SorterSort]<0 } 0 finish_test |
Changes to ext/fts5/test/fts5vocab2.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # The tests in this file focus on testing the fts5vocab module. # source [file join [file dirname [info script]] fts5_common.tcl] | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # # The tests in this file focus on testing the fts5vocab module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5vocab2 # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { finish_test return } |
︙ | ︙ | |||
202 203 204 205 206 207 208 | do_execsql_test 3.5 { DELETE FROM t1; SELECT * FROM v1; } { } finish_test | < | 202 203 204 205 206 207 208 | do_execsql_test 3.5 { DELETE FROM t1; SELECT * FROM v1; } { } finish_test |
Changes to ext/misc/amatch.c.
︙ | ︙ | |||
1469 1470 1471 1472 1473 1474 1475 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Register the amatch virtual table */ |
︙ | ︙ |
Changes to ext/misc/btreeinfo.c.
︙ | ︙ | |||
407 408 409 410 411 412 413 414 415 416 417 418 419 420 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0); } #ifdef _WIN32 __declspec(dllexport) #endif | > | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0); } #ifdef _WIN32 __declspec(dllexport) #endif |
︙ | ︙ |
Changes to ext/misc/closure.c.
︙ | ︙ | |||
934 935 936 937 938 939 940 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Register the closure virtual table */ |
︙ | ︙ |
Changes to ext/misc/completion.c.
︙ | ︙ | |||
464 465 466 467 468 469 470 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3CompletionVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ |
Changes to ext/misc/csv.c.
︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ** Usage: ** ** .load ./csv ** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME); ** SELECT * FROM csv; ** | | | | | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ** ** Usage: ** ** .load ./csv ** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME); ** SELECT * FROM csv; ** ** The columns are named "c1", "c2", "c3", ... by default. Or the ** application can define its own CREATE TABLE statement using the ** schema= parameter, like this: ** ** CREATE VIRTUAL TABLE temp.csv2 USING csv( ** filename = "../http.log", ** schema = "CREATE TABLE x(date,ipaddr,url,referrer,userAgent)" ** ); ** ** Instead of specifying a file, the text of the CSV can be loaded using ** the data= parameter. ** ** If the columns=N parameter is supplied, then the CSV file is assumed to have ** N columns. If both the columns= and schema= parameters are omitted, then ** the number and names of the columns is determined by the first line of ** the CSV input. ** ** Some extra debugging features (used for testing virtual tables) are available ** if this module is compiled with -DSQLITE_TEST. */ #include <sqlite3ext.h> SQLITE_EXTENSION_INIT1 #include <string.h> |
︙ | ︙ | |||
432 433 434 435 436 437 438 439 440 441 442 443 444 445 | || (z[0]=='0' && z[1]==0) ){ return 0; } return -1; } /* ** Parameters: ** filename=FILENAME Name of file containing CSV content ** data=TEXT Direct CSV content. ** schema=SCHEMA Alternative CSV schema. ** header=YES|NO First row of CSV defines the names of | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | || (z[0]=='0' && z[1]==0) ){ return 0; } return -1; } /* Check to see if the string is of the form: "TAG = BOOLEAN" or just "TAG". ** If it is, set *pValue to be the value of the boolean ("true" if there is ** not "= BOOLEAN" component) and return non-zero. If the input string ** does not begin with TAG, return zero. */ static int csv_boolean_parameter( const char *zTag, /* Tag we are looking for */ int nTag, /* Size of the tag in bytes */ const char *z, /* Input parameter */ int *pValue /* Write boolean value here */ ){ int b; z = csv_skip_whitespace(z); if( strncmp(zTag, z, nTag)!=0 ) return 0; z = csv_skip_whitespace(z + nTag); if( z[0]==0 ){ *pValue = 1; return 1; } if( z[0]!='=' ) return 0; z = csv_skip_whitespace(z+1); b = csv_boolean(z); if( b>=0 ){ *pValue = b; return 1; } return 0; } /* ** Parameters: ** filename=FILENAME Name of file containing CSV content ** data=TEXT Direct CSV content. ** schema=SCHEMA Alternative CSV schema. ** header=YES|NO First row of CSV defines the names of |
︙ | ︙ | |||
465 466 467 468 469 470 471 472 473 474 475 476 477 478 | CsvTable *pNew = 0; /* The CsvTable object to construct */ int bHeader = -1; /* header= flags. -1 means not seen yet */ int rc = SQLITE_OK; /* Result code from this routine */ int i, j; /* Loop counters */ #ifdef SQLITE_TEST int tstFlags = 0; /* Value for testflags=N parameter */ #endif int nCol = -99; /* Value of the columns= parameter */ CsvReader sRdr; /* A CSV file reader used to store an error ** message and/or to count the number of columns */ static const char *azParam[] = { "filename", "data", "schema", }; char *azPValue[3]; /* Parameter values */ | > | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | CsvTable *pNew = 0; /* The CsvTable object to construct */ int bHeader = -1; /* header= flags. -1 means not seen yet */ int rc = SQLITE_OK; /* Result code from this routine */ int i, j; /* Loop counters */ #ifdef SQLITE_TEST int tstFlags = 0; /* Value for testflags=N parameter */ #endif int b; /* Value of a boolean parameter */ int nCol = -99; /* Value of the columns= parameter */ CsvReader sRdr; /* A CSV file reader used to store an error ** message and/or to count the number of columns */ static const char *azParam[] = { "filename", "data", "schema", }; char *azPValue[3]; /* Parameter values */ |
︙ | ︙ | |||
489 490 491 492 493 494 495 | const char *zValue; for(j=0; j<sizeof(azParam)/sizeof(azParam[0]); j++){ if( csv_string_parameter(&sRdr, azParam[j], z, &azPValue[j]) ) break; } if( j<sizeof(azParam)/sizeof(azParam[0]) ){ if( sRdr.zErr[0] ) goto csvtab_connect_error; }else | | < < < | < < < < < < | | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > > > > > > > > > | < | < < < | < < | < > > > > | > | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | const char *zValue; for(j=0; j<sizeof(azParam)/sizeof(azParam[0]); j++){ if( csv_string_parameter(&sRdr, azParam[j], z, &azPValue[j]) ) break; } if( j<sizeof(azParam)/sizeof(azParam[0]) ){ if( sRdr.zErr[0] ) goto csvtab_connect_error; }else if( csv_boolean_parameter("header",6,z,&b) ){ if( bHeader>=0 ){ csv_errmsg(&sRdr, "more than one 'header' parameter"); goto csvtab_connect_error; } bHeader = b; }else #ifdef SQLITE_TEST if( (zValue = csv_parameter("testflags",9,z))!=0 ){ tstFlags = (unsigned int)atoi(zValue); }else #endif if( (zValue = csv_parameter("columns",7,z))!=0 ){ if( nCol>0 ){ csv_errmsg(&sRdr, "more than one 'columns' parameter"); goto csvtab_connect_error; } nCol = atoi(zValue); if( nCol<=0 ){ csv_errmsg(&sRdr, "column= value must be positive"); goto csvtab_connect_error; } }else { csv_errmsg(&sRdr, "bad parameter: '%s'", z); goto csvtab_connect_error; } } if( (CSV_FILENAME==0)==(CSV_DATA==0) ){ csv_errmsg(&sRdr, "must specify either filename= or data= but not both"); goto csvtab_connect_error; } if( (nCol<=0 || bHeader==1) && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) ){ goto csvtab_connect_error; } pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) goto csvtab_connect_oom; memset(pNew, 0, sizeof(*pNew)); if( CSV_SCHEMA==0 ){ sqlite3_str *pStr = sqlite3_str_new(0); char *zSep = ""; int iCol = 0; sqlite3_str_appendf(pStr, "CREATE TABLE x("); if( nCol<0 && bHeader<1 ){ nCol = 0; do{ csv_read_one_field(&sRdr); nCol++; }while( sRdr.cTerm==',' ); } if( nCol>0 && bHeader<1 ){ for(iCol=0; iCol<nCol; iCol++){ sqlite3_str_appendf(pStr, "%sc%d TEXT", zSep, iCol); zSep = ","; } }else{ do{ char *z = csv_read_one_field(&sRdr); if( (nCol>0 && iCol<nCol) || (nCol<0 && bHeader) ){ sqlite3_str_appendf(pStr,"%s\"%w\" TEXT", zSep, z); zSep = ","; iCol++; } }while( sRdr.cTerm==',' ); if( nCol<0 ){ nCol = iCol; }else{ while( iCol<nCol ){ sqlite3_str_appendf(pStr,"%sc%d TEXT", zSep, ++iCol); zSep = ","; } } } pNew->nCol = nCol; sqlite3_str_appendf(pStr, ")"); CSV_SCHEMA = sqlite3_str_finish(pStr); if( CSV_SCHEMA==0 ) goto csvtab_connect_oom; }else if( nCol<0 ){ do{ csv_read_one_field(&sRdr); pNew->nCol++; }while( sRdr.cTerm==',' ); }else{ pNew->nCol = nCol; } pNew->zFilename = CSV_FILENAME; CSV_FILENAME = 0; pNew->zData = CSV_DATA; CSV_DATA = 0; #ifdef SQLITE_TEST pNew->tstFlags = tstFlags; #endif if( bHeader!=1 ){ pNew->iStart = 0; }else if( pNew->zData ){ pNew->iStart = (int)sRdr.iIn; }else{ pNew->iStart = ftell(sRdr.in); } csv_reader_reset(&sRdr); rc = sqlite3_declare_vtab(db, CSV_SCHEMA); if( rc ){ csv_errmsg(&sRdr, "bad schema: '%s' - %s", CSV_SCHEMA, sqlite3_errmsg(db)); goto csvtab_connect_error; } for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){ sqlite3_free(azPValue[i]); } return SQLITE_OK; csvtab_connect_oom: rc = SQLITE_NOMEM; |
︙ | ︙ |
Changes to ext/misc/explain.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ** EXPLAIN output from an SQL statement. ** ** Usage example: ** ** .load ./explain ** SELECT p2 FROM explain('SELECT * FROM sqlite_master') ** WHERE opcode='OpenRead'; */ #if !defined(SQLITEINT_H) #include "sqlite3ext.h" #endif SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> | > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ** EXPLAIN output from an SQL statement. ** ** Usage example: ** ** .load ./explain ** SELECT p2 FROM explain('SELECT * FROM sqlite_master') ** WHERE opcode='OpenRead'; ** ** This module was originally written to help simplify SQLite testing, ** by providing an easier means of verifying certain patterns in the ** generated bytecode. */ #if !defined(SQLITEINT_H) #include "sqlite3ext.h" #endif SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> |
︙ | ︙ | |||
228 229 230 231 232 233 234 | ** a query plan for each invocation and compute an estimated cost for that ** plan. */ static int explainBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ | | > > < > | < > | > > > | > | | | | > > > | < | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | ** a query plan for each invocation and compute an estimated cost for that ** plan. */ static int explainBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop counter */ int idx = -1; /* Index of a usable == constraint against SQL */ int unusable = 0; /* True if there are unusable constraints on SQL */ pIdxInfo->estimatedRows = 500; for(i=0; i<pIdxInfo->nConstraint; i++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; if( p->iColumn!=EXPLN_COLUMN_SQL ) continue; if( !p->usable ){ unusable = 1; }else if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idx = i; } } if( idx>=0 ){ /* There exists a usable == constraint against the SQL column */ pIdxInfo->estimatedCost = 10.0; pIdxInfo->idxNum = 1; pIdxInfo->aConstraintUsage[idx].argvIndex = 1; pIdxInfo->aConstraintUsage[idx].omit = 1; }else if( unusable ){ /* There are unusable constraints against the SQL column. Do not allow ** this plan to continue forward. */ return SQLITE_CONSTRAINT; } return SQLITE_OK; } /* ** This following structure defines all the methods for the ** explain virtual table. |
︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3ExplainVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE | > | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3ExplainVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ |
Changes to ext/misc/fileio.c.
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # define mkdir(path,mode) _mkdir(path) # define lstat(path,buf) stat(path,buf) #endif #include <time.h> #include <errno.h> #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" /* ** Set the result stored by context ctx to a blob containing the ** contents of file zName. */ static void readFileContents(sqlite3_context *ctx, const char *zName){ FILE *in; | > > > > > > > > > > > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | # define mkdir(path,mode) _mkdir(path) # define lstat(path,buf) stat(path,buf) #endif #include <time.h> #include <errno.h> /* ** Structure of the fsdir() table-valued function */ /* 0 1 2 3 4 5 */ #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" #define FSDIR_COLUMN_NAME 0 /* Name of the file */ #define FSDIR_COLUMN_MODE 1 /* Access mode */ #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ #define FSDIR_COLUMN_DATA 3 /* File content */ #define FSDIR_COLUMN_PATH 4 /* Path to top of search */ #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ /* ** Set the result stored by context ctx to a blob containing the ** contents of file zName. */ static void readFileContents(sqlite3_context *ctx, const char *zName){ FILE *in; |
︙ | ︙ | |||
691 692 693 694 695 696 697 | static int fsdirColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ fsdir_cursor *pCur = (fsdir_cursor*)cur; switch( i ){ | | | | | | 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 | static int fsdirColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ fsdir_cursor *pCur = (fsdir_cursor*)cur; switch( i ){ case FSDIR_COLUMN_NAME: { sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); break; } case FSDIR_COLUMN_MODE: sqlite3_result_int64(ctx, pCur->sStat.st_mode); break; case FSDIR_COLUMN_MTIME: sqlite3_result_int64(ctx, pCur->sStat.st_mtime); break; case FSDIR_COLUMN_DATA: { mode_t m = pCur->sStat.st_mode; if( S_ISDIR(m) ){ sqlite3_result_null(ctx); #if !defined(_WIN32) && !defined(WIN32) }else if( S_ISLNK(m) ){ char aStatic[64]; char *aBuf = aStatic; |
︙ | ︙ | |||
734 735 736 737 738 739 740 741 742 743 744 745 746 747 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); if( aBuf!=aStatic ) sqlite3_free(aBuf); #endif }else{ readFileContents(ctx, pCur->zPath); } } } return SQLITE_OK; } /* ** Return the rowid for the current row. In this implementation, the ** first row returned is assigned rowid value 1, and each subsequent | > > > > > > | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); if( aBuf!=aStatic ) sqlite3_free(aBuf); #endif }else{ readFileContents(ctx, pCur->zPath); } } case FSDIR_COLUMN_PATH: default: { /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ** always return their values as NULL */ break; } } return SQLITE_OK; } /* ** Return the rowid for the current row. In this implementation, the ** first row returned is assigned rowid value 1, and each subsequent |
︙ | ︙ | |||
760 761 762 763 764 765 766 767 768 769 770 771 772 773 | static int fsdirEof(sqlite3_vtab_cursor *cur){ fsdir_cursor *pCur = (fsdir_cursor*)cur; return (pCur->zPath==0); } /* ** xFilter callback. */ static int fsdirFilter( sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ const char *zDir = 0; | > > > | 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | static int fsdirEof(sqlite3_vtab_cursor *cur){ fsdir_cursor *pCur = (fsdir_cursor*)cur; return (pCur->zPath==0); } /* ** xFilter callback. ** ** idxNum==1 PATH parameter only ** idxNum==2 Both PATH and DIR supplied */ static int fsdirFilter( sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ const char *zDir = 0; |
︙ | ︙ | |||
812 813 814 815 816 817 818 | ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. ** ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** | | | | < < | | > > < > > | > > > > > > > > | > > > > | > | > > > > > > > | > > | | | | | | | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 | ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. ** ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** ** The query plan is represented by values of idxNum: ** ** (1) The path value is supplied by argv[0] ** (2) Path is in argv[0] and dir is in argv[1] */ static int fsdirBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop over constraints */ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ int seenPath = 0; /* True if an unusable PATH= constraint is seen */ int seenDir = 0; /* True if an unusable DIR= constraint is seen */ const struct sqlite3_index_constraint *pConstraint; (void)tab; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; switch( pConstraint->iColumn ){ case FSDIR_COLUMN_PATH: { if( pConstraint->usable ){ idxPath = i; seenPath = 0; }else if( idxPath<0 ){ seenPath = 1; } break; } case FSDIR_COLUMN_DIR: { if( pConstraint->usable ){ idxDir = i; seenDir = 0; }else if( idxDir<0 ){ seenDir = 1; } break; } } } if( seenPath || seenDir ){ /* If input parameters are unusable, disallow this plan */ return SQLITE_CONSTRAINT; } if( idxPath<0 ){ pIdxInfo->idxNum = 0; /* The pIdxInfo->estimatedCost should have been initialized to a huge ** number. Leave it unchanged. */ pIdxInfo->estimatedRows = 0x7fffffff; }else{ pIdxInfo->aConstraintUsage[idxPath].omit = 1; pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; if( idxDir>=0 ){ pIdxInfo->aConstraintUsage[idxDir].omit = 1; pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; pIdxInfo->idxNum = 2; pIdxInfo->estimatedCost = 10.0; }else{ pIdxInfo->idxNum = 1; pIdxInfo->estimatedCost = 100.0; } } |
︙ | ︙ | |||
884 885 886 887 888 889 890 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); return rc; } #else /* SQLITE_OMIT_VIRTUALTABLE */ # define fsdirRegister(x) SQLITE_OK |
︙ | ︙ |
Changes to ext/misc/json1.c.
︙ | ︙ | |||
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 | #define JEACH_VALUE 1 #define JEACH_TYPE 2 #define JEACH_ATOM 3 #define JEACH_ID 4 #define JEACH_PARENT 5 #define JEACH_FULLKEY 6 #define JEACH_PATH 7 #define JEACH_JSON 8 #define JEACH_ROOT 9 UNUSED_PARAM(pzErr); UNUSED_PARAM(argv); UNUSED_PARAM(argc); UNUSED_PARAM(pAux); | > > > | 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 | #define JEACH_VALUE 1 #define JEACH_TYPE 2 #define JEACH_ATOM 3 #define JEACH_ID 4 #define JEACH_PARENT 5 #define JEACH_FULLKEY 6 #define JEACH_PATH 7 /* The xBestIndex method assumes that the JSON and ROOT columns are ** the last two columns in the table. Should this ever changes, be ** sure to update the xBestIndex method. */ #define JEACH_JSON 8 #define JEACH_ROOT 9 UNUSED_PARAM(pzErr); UNUSED_PARAM(argv); UNUSED_PARAM(argc); UNUSED_PARAM(pAux); |
︙ | ︙ | |||
2247 2248 2249 2250 2251 2252 2253 | ** 1 if the constraint is found, 3 if the constraint and zRoot are found, ** and 0 otherwise. */ static int jsonEachBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ | | | | > > > > > > > > > > > | > | | | < < > > > > > | > > > < > | | | | > | | | | 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 | ** 1 if the constraint is found, 3 if the constraint and zRoot are found, ** and 0 otherwise. */ static int jsonEachBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop counter or computed array index */ int aIdx[2]; /* Index of constraints for JSON and ROOT */ int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ const struct sqlite3_index_constraint *pConstraint; /* This implementation assumes that JSON and ROOT are the last two ** columns in the table */ assert( JEACH_ROOT == JEACH_JSON+1 ); UNUSED_PARAM(tab); aIdx[0] = aIdx[1] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ int iCol; int iMask; if( pConstraint->iColumn < JEACH_JSON ) continue; iCol = pConstraint->iColumn - JEACH_JSON; assert( iCol==0 || iCol==1 ); iMask = 1 << iCol; if( pConstraint->usable==0 ){ unusableMask |= iMask; }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ aIdx[iCol] = i; idxMask |= iMask; } } if( (unusableMask & ~idxMask)!=0 ){ /* If there are any unusable constraints on JSON or ROOT, then reject ** this entire plan */ return SQLITE_CONSTRAINT; } if( aIdx[0]<0 ){ /* No JSON input. Leave estimatedCost at the huge value that it was ** initialized to to discourage the query planner from selecting this ** plan. */ pIdxInfo->idxNum = 0; }else{ pIdxInfo->estimatedCost = 1.0; i = aIdx[0]; pIdxInfo->aConstraintUsage[i].argvIndex = 1; pIdxInfo->aConstraintUsage[i].omit = 1; if( aIdx[1]<0 ){ pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ }else{ i = aIdx[1]; pIdxInfo->aConstraintUsage[i].argvIndex = 2; pIdxInfo->aConstraintUsage[i].omit = 1; pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ } } return SQLITE_OK; } /* Start a search on a new JSON string */ static int jsonEachFilter( |
︙ | ︙ | |||
2384 2385 2386 2387 2388 2389 2390 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; /* The methods of the json_tree virtual table. */ static sqlite3_module jsonTreeModule = { 0, /* iVersion */ 0, /* xCreate */ jsonEachConnect, /* xConnect */ |
︙ | ︙ | |||
2411 2412 2413 2414 2415 2416 2417 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ /**************************************************************************** ** The following routines are the only publically visible identifiers in this ** file. Call the following routines in order to register the various SQL ** functions and the virtual table implemented by this file. |
︙ | ︙ |
Changes to ext/misc/memstat.c.
︙ | ︙ | |||
391 392 393 394 395 396 397 398 399 400 401 402 403 404 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3MemstatVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE | > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3MemstatVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ |
Changes to ext/misc/series.c.
︙ | ︙ | |||
309 310 311 312 313 314 315 | ** (4) step = $value -- constraint exists ** (8) output in descending order */ static int seriesBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ | | | < < | > > > > > > | | | | > | > | | < < > | < < | < < > | | | | < < < | > | > | < | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | ** (4) step = $value -- constraint exists ** (8) output in descending order */ static int seriesBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i, j; /* Loop over constraints */ int idxNum = 0; /* The query plan bitmask */ int unusableMask = 0; /* Mask of unusable constraints */ int nArg = 0; /* Number of arguments that seriesFilter() expects */ int aIdx[3]; /* Constraints on start, stop, and step */ const struct sqlite3_index_constraint *pConstraint; /* This implementation assumes that the start, stop, and step columns ** are the last three columns in the virtual table. */ assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); aIdx[0] = aIdx[1] = aIdx[2] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ int iCol; /* 0 for start, 1 for stop, 2 for step */ int iMask; /* bitmask for those column */ if( pConstraint->iColumn<SERIES_COLUMN_START ) continue; iCol = pConstraint->iColumn - SERIES_COLUMN_START; assert( iCol>=0 && iCol<=2 ); iMask = 1 << iCol; if( pConstraint->usable==0 ){ unusableMask |= iMask; continue; }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idxNum |= iMask; aIdx[iCol] = i; } } for(i=0; i<3; i++){ if( (j = aIdx[i])>=0 ){ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } } if( (unusableMask & ~idxNum)!=0 ){ /* The start, stop, and step columns are inputs. Therefore if there ** are unusable constraints on any of start, stop, or step then ** this plan is unusable */ return SQLITE_CONSTRAINT; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the ** the preferred case */ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; if( pIdxInfo->nOrderBy==1 ){ if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8; pIdxInfo->orderByConsumed = 1; } }else{ /* If either boundary is missing, we have to generate a huge span ** of numbers. Make this case very expensive so that the query ** planner will work hard to avoid it. */ pIdxInfo->estimatedRows = 2147483647; } pIdxInfo->idxNum = idxNum; return SQLITE_OK; } /* |
︙ | ︙ |
Changes to ext/misc/stmt.c.
︙ | ︙ | |||
262 263 264 265 266 267 268 269 270 271 272 273 274 275 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3StmtVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE | > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3StmtVtabInit(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ |
Changes to ext/misc/templatevtab.c.
︙ | ︙ | |||
244 245 246 247 248 249 250 | /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, | | > | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ 0 }; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_templatevtab_init( |
︙ | ︙ |
Changes to ext/misc/unionvtab.c.
︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 | 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; int rc; rc = sqlite3_create_module(db, "unionvtab", &unionModule, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_module(db, "swarmvtab", &unionModule, (void*)db); } |
︙ | ︙ |
Changes to ext/misc/vtablog.c.
︙ | ︙ | |||
488 489 490 491 492 493 494 495 496 497 498 499 500 501 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_vtablog_init( sqlite3 *db, | > | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ }; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_vtablog_init( sqlite3 *db, |
︙ | ︙ |
Changes to ext/misc/zipfile.c.
︙ | ︙ | |||
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | ** xBestIndex callback. */ static int zipfileBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; for(i=0; i<pIdxInfo->nConstraint; i++){ const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; | > > > | > | < < > | | | | | | < | < | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | ** xBestIndex callback. */ static int zipfileBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; int idx = -1; int unusable = 0; for(i=0; i<pIdxInfo->nConstraint; i++){ const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; if( pCons->usable==0 ){ unusable = 1; }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idx = i; } } if( idx>=0 ){ pIdxInfo->aConstraintUsage[idx].argvIndex = 1; pIdxInfo->aConstraintUsage[idx].omit = 1; pIdxInfo->estimatedCost = 1000.0; pIdxInfo->idxNum = 1; }else if( unusable ){ return SQLITE_CONSTRAINT; } return SQLITE_OK; } static ZipfileEntry *zipfileNewEntry(const char *zPath){ ZipfileEntry *pNew; pNew = sqlite3_malloc(sizeof(ZipfileEntry)); if( pNew ){ |
︙ | ︙ |
Changes to ext/rbu/rbu1.test.
︙ | ︙ | |||
666 667 668 669 670 671 672 | catch { db close } eval $destroy_vfs } finish_test | < | 666 667 668 669 670 671 672 | catch { db close } eval $destroy_vfs } finish_test |
Changes to ext/rbu/rbu10.test.
︙ | ︙ | |||
181 182 183 184 185 186 187 | INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0); } list [catch { apply_rbu $rbu } msg] $msg } {0 SQLITE_DONE} finish_test | < | 181 182 183 184 185 186 187 | INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0); } list [catch { apply_rbu $rbu } msg] $msg } {0 SQLITE_DONE} finish_test |
Changes to ext/rbu/rbu11.test.
︙ | ︙ | |||
191 192 193 194 195 196 197 | rbu step } {SQLITE_ERROR} do_test 4.7.2 { list [catch {rbu close} msg] $msg } {1 {SQLITE_ERROR - rbu_state mismatch error}} finish_test | < | 191 192 193 194 195 196 197 | rbu step } {SQLITE_ERROR} do_test 4.7.2 { list [catch {rbu close} msg] $msg } {1 {SQLITE_ERROR - rbu_state mismatch error}} finish_test |
Changes to ext/rbu/rbu12.test.
︙ | ︙ | |||
228 229 230 231 232 233 234 | do_test 2.$tn.6 { list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] } [list $V1 $V2] } finish_test | < | 228 229 230 231 232 233 234 | do_test 2.$tn.6 { list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}] } [list $V1 $V2] } finish_test |
Changes to ext/rbu/rbu13.test.
︙ | ︙ | |||
58 59 60 61 62 63 64 | do_execsql_test 1.4 { SELECT count(*) FROM t1 WHERE a == ( (b<<6) + (c<<5) + (d<<4) + (e<<3) + (f<<2) + (g<<1) + (h<<0) ) } {128} finish_test | < | 58 59 60 61 62 63 64 | do_execsql_test 1.4 { SELECT count(*) FROM t1 WHERE a == ( (b<<6) + (c<<5) + (d<<4) + (e<<3) + (f<<2) + (g<<1) + (h<<0) ) } {128} finish_test |
Changes to ext/rbu/rbu14.test.
︙ | ︙ | |||
88 89 90 91 92 93 94 | } {4 5 6 50 50 50} integrity_check $tn.4 } finish_test | < | 88 89 90 91 92 93 94 | } {4 5 6 50 50 50} integrity_check $tn.4 } finish_test |
Changes to ext/rbu/rbu3.test.
︙ | ︙ | |||
199 200 201 202 203 204 205 | do_test 5.3 { expr {[file size test.db-wal] > (1024 * 1200)} } 1 do_test 6.1 { sqlite3rbu_internal_test } {} finish_test | < < | 199 200 201 202 203 204 205 | do_test 5.3 { expr {[file size test.db-wal] > (1024 * 1200)} } 1 do_test 6.1 { sqlite3rbu_internal_test } {} finish_test |
Changes to ext/rbu/rbu5.test.
︙ | ︙ | |||
296 297 298 299 300 301 302 | db close } } finish_test | < < < < | 296 297 298 299 300 301 302 | db close } } finish_test |
Changes to ext/rbu/rbu6.test.
︙ | ︙ | |||
96 97 98 99 100 101 102 | do_execsql_test 1.$nStep.5 { SELECT * FROM t1; } {1 t1 5 hello} } finish_test | < | 96 97 98 99 100 101 102 | do_execsql_test 1.$nStep.5 { SELECT * FROM t1; } {1 t1 5 hello} } finish_test |
Changes to ext/rbu/rbu7.test.
︙ | ︙ | |||
102 103 104 105 106 107 108 | 2 2 d 3 1 e 3 2 f } } finish_test | < < | 102 103 104 105 106 107 108 | 2 2 d 3 1 e 3 2 f } } finish_test |
Changes to ext/rbu/rbu8.test.
︙ | ︙ | |||
68 69 70 71 72 73 74 | {} 2 2 _iii 3 three-III } integrity_check 1.3.3 finish_test | < | 68 69 70 71 72 73 74 | {} 2 2 _iii 3 three-III } integrity_check 1.3.3 finish_test |
Changes to ext/rbu/rbu9.test.
︙ | ︙ | |||
121 122 123 124 125 126 127 | } integrity_check 2.$tn.4 } finish_test | < | 121 122 123 124 125 126 127 | } integrity_check 2.$tn.4 } finish_test |
Changes to ext/rbu/rbuA.test.
︙ | ︙ | |||
76 77 78 79 80 81 82 | do_test 2.2 { list [catch { rbu close } msg] $msg } {1 {SQLITE_ERROR - cannot update wal mode database}} finish_test | < | 76 77 78 79 80 81 82 | do_test 2.2 { list [catch { rbu close } msg] $msg } {1 {SQLITE_ERROR - cannot update wal mode database}} finish_test |
Changes to ext/rbu/rbuB.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 | } {1 2 3 4 5 6 7 8 9} db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test | < | 55 56 57 58 59 60 61 | } {1 2 3 4 5 6 7 8 9} db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test |
Changes to ext/rbu/rbuC.test.
︙ | ︙ | |||
135 136 137 138 139 140 141 | integrity_check 3.$tn.4 } finish_test | < | 135 136 137 138 139 140 141 | integrity_check 3.$tn.4 } finish_test |
Changes to ext/rbu/rbucollate.test.
︙ | ︙ | |||
56 57 58 59 60 61 62 | } rbu close db eval { SELECT * FROM t1 } } {a one 1 b two 2 c three 3} #forcedelete testrbu.db finish_test | < | 56 57 58 59 60 61 62 | } rbu close db eval { SELECT * FROM t1 } } {a one 1 b two 2 c three 3} #forcedelete testrbu.db finish_test |
Changes to ext/rbu/rbucrash.test.
︙ | ︙ | |||
141 142 143 144 145 146 147 | for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} { for {set is 1} {$is <= ($rbu_num_steps - $nPre)} {incr is} { do_rbu_crash_test 2.pre=$nPre.step=$is $nPre $is } } finish_test | < | 141 142 143 144 145 146 147 | for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} { for {set is 1} {$is <= ($rbu_num_steps - $nPre)} {incr is} { do_rbu_crash_test 2.pre=$nPre.step=$is $nPre $is } } finish_test |
Changes to ext/rbu/rbucrash2.test.
︙ | ︙ | |||
99 100 101 102 103 104 105 | sqlite3rbu rbu test.db test.db2 } rbu close } } finish_test | < | 99 100 101 102 103 104 105 | sqlite3rbu rbu test.db test.db2 } rbu close } } finish_test |
Changes to ext/rbu/rbudiff.test.
︙ | ︙ | |||
296 297 298 299 300 301 302 | db close db2 close } } finish_test | < | 296 297 298 299 300 301 302 | db close db2 close } } finish_test |
Changes to ext/rbu/rbudor.test.
︙ | ︙ | |||
52 53 54 55 56 57 58 | } {SQLITE_DONE} do_execsql_test 1.4 { SELECT * FROM t1 } [list 1 $bigA 2 $bigB] finish_test | < | 52 53 54 55 56 57 58 | } {SQLITE_DONE} do_execsql_test 1.4 { SELECT * FROM t1 } [list 1 $bigA 2 $bigB] finish_test |
Changes to ext/rbu/rbufault.test.
︙ | ︙ | |||
230 231 232 233 234 235 236 | } } } } } finish_test | < | 230 231 232 233 234 235 236 | } } } } } finish_test |
Changes to ext/rbu/rbufault2.test.
︙ | ︙ | |||
51 52 53 54 55 56 57 | {1 {SQLITE_NOMEM - out of memory}} } finish_test | < | 51 52 53 54 55 56 57 | {1 {SQLITE_NOMEM - out of memory}} } finish_test |
Changes to ext/rbu/rbufault3.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 | } -test { eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist] } } finish_test | < | 91 92 93 94 95 96 97 | } -test { eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist] } } finish_test |
Changes to ext/rbu/rbufault4.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | if {$rc!="ok"} { error "Got $rc instead of ok!" } } } finish_test | < | 59 60 61 62 63 64 65 | if {$rc!="ok"} { error "Got $rc instead of ok!" } } } finish_test |
Changes to ext/rbu/rbufts.test.
︙ | ︙ | |||
127 128 129 130 131 132 133 | INSERT INTO data_ft VALUES('7 8 9', 1, 'x'); } } msg] $msg] } {1 {SQLITE_ERROR - SQL logic error]}} finish_test | < | 127 128 129 130 131 132 133 | INSERT INTO data_ft VALUES('7 8 9', 1, 'x'); } } msg] $msg] } {1 {SQLITE_ERROR - SQL logic error]}} finish_test |
Changes to ext/rbu/rbumulti.test.
︙ | ︙ | |||
168 169 170 171 172 173 174 | sqlite3rbu_destroy_vfs myrbu } } finish_test | < | 168 169 170 171 172 173 174 | sqlite3rbu_destroy_vfs myrbu } } finish_test |
Changes to ext/rbu/rbuprogress.test.
︙ | ︙ | |||
412 413 414 415 416 417 418 | do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) } } } finish_test | < | 412 413 414 415 416 417 418 | do_sp_test 5.$tn.$bReopen.$tn2.1 $bReopen test.db rbu.db $R($tn) } } } finish_test |
Changes to ext/rbu/rburesume.test.
︙ | ︙ | |||
247 248 249 250 251 252 253 | PRAGMA integrity_check; } } {60 ok} db2 close } finish_test | < | 247 248 249 250 251 252 253 | PRAGMA integrity_check; } } {60 ok} db2 close } finish_test |
Changes to ext/rbu/rbusave.test.
︙ | ︙ | |||
98 99 100 101 102 103 104 | do_execsql_test 1.5 { SELECT * FROM t1; SELECT * FROM t2; } {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4} finish_test | < | 98 99 100 101 102 103 104 | do_execsql_test 1.5 { SELECT * FROM t1; SELECT * FROM t2; } {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4} finish_test |
Changes to ext/rbu/rbusplit.test.
︙ | ︙ | |||
88 89 90 91 92 93 94 | 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 } } finish_test | < | 88 89 90 91 92 93 94 | 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 } } finish_test |
Changes to ext/rbu/rbutemplimit.test.
︙ | ︙ | |||
122 123 124 125 126 127 128 | setup_databases unset -nocomplain ::A step_rbu_cachesize test.db test.db2 1000 10 1400000 } {1 SQLITE_FULL} do_test 1.6.2 { info commands rbu } {} finish_test | < | 122 123 124 125 126 127 128 | setup_databases unset -nocomplain ::A step_rbu_cachesize test.db test.db2 1000 10 1400000 } {1 SQLITE_FULL} do_test 1.6.2 { info commands rbu } {} finish_test |
Changes to ext/rbu/rbuvacuum.test.
︙ | ︙ | |||
393 394 395 396 397 398 399 | while {[rbu step]=="SQLITE_OK"} {} list [catch { rbu close } msg] $msg } {0 SQLITE_DONE} catch { db close } finish_test | < | 393 394 395 396 397 398 399 | while {[rbu step]=="SQLITE_OK"} {} list [catch { rbu close } msg] $msg } {0 SQLITE_DONE} catch { db close } finish_test |
Changes to ext/rbu/rbuvacuum2.test.
︙ | ︙ | |||
228 229 230 231 232 233 234 | sqlite3rbu_vacuum rbu test.db test.db2 while {[rbu step]!="SQLITE_DONE"} { rbu step } rbu close execsql { PRAGMA integrity_check } } {ok} finish_test | < | 228 229 230 231 232 233 234 | sqlite3rbu_vacuum rbu test.db test.db2 while {[rbu step]!="SQLITE_DONE"} { rbu step } rbu close execsql { PRAGMA integrity_check } } {ok} finish_test |
Changes to ext/repair/test/checkindex01.test.
︙ | ︙ | |||
343 344 345 346 347 348 349 | } do_index_check_test 7.3 t7i3 { {} 1,1 {} 3,3 } do_index_check_test 7.4 t7i4 { {} 1,1 {} 3,3 } | < < | 343 344 345 346 347 348 349 | } do_index_check_test 7.3 t7i3 { {} 1,1 {} 3,3 } do_index_check_test 7.4 t7i4 { {} 1,1 {} 3,3 } |
Changes to ext/rtree/geopoly.c.
︙ | ︙ | |||
1721 1722 1723 1724 1725 1726 1727 | return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; } return 0; } static sqlite3_module geopolyModule = { | | | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; } return 0; } static sqlite3_module geopolyModule = { 3, /* iVersion */ geopolyCreate, /* xCreate - create a table */ geopolyConnect, /* xConnect - connect to an existing table */ geopolyBestIndex, /* xBestIndex - Determine search strategy */ rtreeDisconnect, /* xDisconnect - Disconnect from a table */ rtreeDestroy, /* xDestroy - Drop a table */ rtreeOpen, /* xOpen - open a cursor */ rtreeClose, /* xClose - close a cursor */ |
︙ | ︙ | |||
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 | rtreeEndTransaction, /* xCommit - commit transaction */ rtreeEndTransaction, /* xRollback - rollback transaction */ geopolyFindFunction, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { void (*xFunc)(sqlite3_context*,int,sqlite3_value**); signed char nArg; | > | 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 | rtreeEndTransaction, /* xCommit - commit transaction */ rtreeEndTransaction, /* xRollback - rollback transaction */ geopolyFindFunction, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ rtreeShadowName /* xShadowName */ }; static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { void (*xFunc)(sqlite3_context*,int,sqlite3_value**); signed char nArg; |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
3321 3322 3323 3324 3325 3326 3327 3328 | } sqlite3_free(zSql); } return rc; } static sqlite3_module rtreeModule = { | > > > > > > > > > > > > > > > > | | 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 | } sqlite3_free(zSql); } return rc; } /* ** Return true if zName is the extension on one of the shadow tables used ** by this module. */ static int rtreeShadowName(const char *zName){ static const char *azName[] = { "node", "parent", "rowid" }; unsigned int i; for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; } return 0; } static sqlite3_module rtreeModule = { 3, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ rtreeBestIndex, /* xBestIndex - Determine search strategy */ rtreeDisconnect, /* xDisconnect - Disconnect from a table */ rtreeDestroy, /* xDestroy - Drop a table */ rtreeOpen, /* xOpen - open a cursor */ rtreeClose, /* xClose - close a cursor */ |
︙ | ︙ | |||
3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 | rtreeEndTransaction, /* xCommit - commit transaction */ rtreeEndTransaction, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; static int rtreeSqlInit( Rtree *pRtree, sqlite3 *db, const char *zDb, const char *zPrefix, | > | 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 | rtreeEndTransaction, /* xCommit - commit transaction */ rtreeEndTransaction, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ rtreeShadowName /* xShadowName */ }; static int rtreeSqlInit( Rtree *pRtree, sqlite3 *db, const char *zDb, const char *zPrefix, |
︙ | ︙ |
Changes to ext/rtree/rtree8.test.
︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | # The following block of tests - rtree8-2.* - test a couple of database # corruption cases. In this case things are not corrupted at the b-tree # level, but the contents of the various tables used internally by an # r-tree table are inconsistent. # populate_t1 50 do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5} do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {} for {set i 1} {$i <= 50} {incr i} { do_catchsql_test rtree8-2.1.3.$i { SELECT * FROM t1 WHERE id = $i } {1 {database disk image is malformed}} } do_catchsql_test rtree8-2.1.4 { SELECT * FROM t1 } {1 {database disk image is malformed}} do_catchsql_test rtree8-2.1.5 { DELETE FROM t1 } {1 {database disk image is malformed}} do_execsql_test rtree8-2.1.6 { DROP TABLE t1; CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2); } {} populate_t1 50 do_execsql_test rtree8-2.2.1 { DELETE FROM t1_parent } {} do_catchsql_test rtree8-2.2.2 { DELETE FROM t1 WHERE id=25 } {1 {database disk image is malformed}} do_execsql_test rtree8-2.2.3 { | > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # The following block of tests - rtree8-2.* - test a couple of database # corruption cases. In this case things are not corrupted at the b-tree # level, but the contents of the various tables used internally by an # r-tree table are inconsistent. # populate_t1 50 do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5} sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {} for {set i 1} {$i <= 50} {incr i} { do_catchsql_test rtree8-2.1.3.$i { SELECT * FROM t1 WHERE id = $i } {1 {database disk image is malformed}} } do_catchsql_test rtree8-2.1.4 { SELECT * FROM t1 } {1 {database disk image is malformed}} do_catchsql_test rtree8-2.1.5 { DELETE FROM t1 } {1 {database disk image is malformed}} do_execsql_test rtree8-2.1.6 { DROP TABLE t1; CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2); } {} populate_t1 50 sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtree8-2.2.1 { DELETE FROM t1_parent } {} do_catchsql_test rtree8-2.2.2 { DELETE FROM t1 WHERE id=25 } {1 {database disk image is malformed}} do_execsql_test rtree8-2.2.3 { |
︙ | ︙ |
Changes to ext/rtree/rtreeA.test.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 | execsql BEGIN for {set i 0} {$i < 500} {incr i} { set x2 [expr $i+5] set y2 [expr $i+5] execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) } } execsql COMMIT } proc truncate_node {nodeno nTrunc} { set blob [db one {SELECT data FROM t1_node WHERE nodeno=$nodeno}] if {$nTrunc<0} {set nTrunc "end-$nTrunc"} set blob [string range $blob 0 $nTrunc] db eval { UPDATE t1_node SET data = $blob WHERE nodeno=$nodeno } | > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | execsql BEGIN for {set i 0} {$i < 500} {incr i} { set x2 [expr $i+5] set y2 [expr $i+5] execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) } } execsql COMMIT sqlite3_db_config db DEFENSIVE 0 } proc truncate_node {nodeno nTrunc} { set blob [db one {SELECT data FROM t1_node WHERE nodeno=$nodeno}] if {$nTrunc<0} {set nTrunc "end-$nTrunc"} set blob [string range $blob 0 $nTrunc] db eval { UPDATE t1_node SET data = $blob WHERE nodeno=$nodeno } |
︙ | ︙ | |||
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | #------------------------------------------------------------------------- # Truncated blobs in the _node table. # create_t1 populate_t1 sqlite3 db test.db do_execsql_test rtreeA-7.100 { UPDATE t1_node SET data=x'' WHERE rowid=1; } {} do_catchsql_test rtreeA-7.110 { SELECT * FROM t1 WHERE x1>0 AND x1<100 AND x2>0 AND x2<100; } {1 {undersize RTree blobs in "t1_node"}} do_test rtreeA-7.120 { sqlite3_extended_errcode db } {SQLITE_CORRUPT_VTAB} finish_test | > < | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | #------------------------------------------------------------------------- # Truncated blobs in the _node table. # create_t1 populate_t1 sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtreeA-7.100 { UPDATE t1_node SET data=x'' WHERE rowid=1; } {} do_catchsql_test rtreeA-7.110 { SELECT * FROM t1 WHERE x1>0 AND x1<100 AND x2>0 AND x2<100; } {1 {undersize RTree blobs in "t1_node"}} do_test rtreeA-7.120 { sqlite3_extended_errcode db } {SQLITE_CORRUPT_VTAB} finish_test |
Changes to ext/rtree/rtreecheck.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | CREATE VIRTUAL TABLE r1 USING $module (id, x1, x2, y1, y2); INSERT INTO r1 VALUES(1, 5, 5, 5, 5); -- 3 INSERT INTO r1 VALUES(2, 6, 6, 6, 6); -- 9 INSERT INTO r1 VALUES(3, 7, 7, 7, 7); -- 15 INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21 INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27 " } setup_simple_db do_execsql_test 2.1 { SELECT rtreecheck('r1') } {ok} | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | CREATE VIRTUAL TABLE r1 USING $module (id, x1, x2, y1, y2); INSERT INTO r1 VALUES(1, 5, 5, 5, 5); -- 3 INSERT INTO r1 VALUES(2, 6, 6, 6, 6); -- 9 INSERT INTO r1 VALUES(3, 7, 7, 7, 7); -- 15 INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21 INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27 " sqlite3_db_config db DEFENSIVE 0 } setup_simple_db do_execsql_test 2.1 { SELECT rtreecheck('r1') } {ok} |
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 118 119 120 121 | do_execsql_test 3.1 { CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2); INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5); SELECT rtreecheck('r2') } {ok} do_execsql_test 3.2 { BEGIN; UPDATE r2_node SET data = X'123456'; SELECT rtreecheck('r2')!="ok"; } {1} do_execsql_test 3.3 { | > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | do_execsql_test 3.1 { CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2); INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5); SELECT rtreecheck('r2') } {ok} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { BEGIN; UPDATE r2_node SET data = X'123456'; SELECT rtreecheck('r2')!="ok"; } {1} do_execsql_test 3.3 { |
︙ | ︙ | |||
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | do_execsql_test 5.0 { CREATE VIRTUAL TABLE r3 USING rtree_i32(id, x1, x2, y1, y2); WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 ) INSERT INTO r3 SELECT i, i, i, i, i FROM x; } do_execsql_test 5.1 { BEGIN; UPDATE r3_node SET data = set_int32(data, 3, 5000); UPDATE r3_node SET data = set_int32(data, 4, 5000); SELECT rtreecheck('r3')=='ok' } 0 do_execsql_test 5.2 { ROLLBACK; BEGIN; UPDATE r3_node SET data = set_int32(data, 3, 0); UPDATE r3_node SET data = set_int32(data, 4, 0); SELECT rtreecheck('r3')=='ok' } 0 finish_test | > < | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | do_execsql_test 5.0 { CREATE VIRTUAL TABLE r3 USING rtree_i32(id, x1, x2, y1, y2); WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 ) INSERT INTO r3 SELECT i, i, i, i, i FROM x; } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 5.1 { BEGIN; UPDATE r3_node SET data = set_int32(data, 3, 5000); UPDATE r3_node SET data = set_int32(data, 4, 5000); SELECT rtreecheck('r3')=='ok' } 0 do_execsql_test 5.2 { ROLLBACK; BEGIN; UPDATE r3_node SET data = set_int32(data, 3, 0); UPDATE r3_node SET data = set_int32(data, 4, 0); SELECT rtreecheck('r3')=='ok' } 0 finish_test |
Added ext/session/changesetfuzz.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 | /* ** 2018-11-01 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code to implement the "changesetfuzz" command ** line utility for fuzzing changeset blobs without corrupting them. */ /************************************************************************ ** USAGE: ** ** This program may be invoked in two ways: ** ** changesetfuzz INPUT ** changesetfuzz INPUT SEED N ** ** Argument INPUT must be the name of a file containing a binary changeset. ** In the first form above, this program outputs a human-readable version ** of the same changeset. This is chiefly for debugging. ** ** As well as changesets, this program can also dump and fuzz patchsets. ** The term "changeset" is used for both patchsets and changesets from this ** point on. ** ** In the second form, arguments SEED and N must both be integers. In this ** case, this program writes N binary changesets to disk. Each output ** changeset is a slightly modified - "fuzzed" - version of the input. ** The output changesets are written to files name "INPUT-$n", where $n is ** an integer between 0 and N-1, inclusive. Output changesets are always ** well-formed. Parameter SEED is used to seed the PRNG - any two ** invocations of this program with the same SEED and input changeset create ** the same N output changesets. ** ** The ways in which an input changeset may be fuzzed are as follows: ** ** 1. Any two values within the changeset may be exchanged. ** ** 2. Any TEXT, BLOB, INTEGER or REAL value within the changeset ** may have a single bit of its content flipped. ** ** 3. Any value within a changeset may be replaced by a pseudo-randomly ** generated value. ** ** The above operations never set a PRIMARY KEY column to NULL. Nor do they ** set any value to "undefined", or replace any "undefined" value with ** another. Any such operation risks producing a changeset that is not ** well-formed. ** ** 4. A single change may be duplicated. ** ** 5. A single change may be removed, so long as this does not mean that ** there are zero changes following a table-header within the changeset. ** ** 6. A single change may have its type (INSERT, DELETE, UPDATE) changed. ** If an INSERT is changed to a DELETE (or vice versa), the type is ** simply changed - no other modifications are required. If an INSERT ** or DELETE is changed to an UPDATE, then the single record is duplicated ** (as both the old.* and new.* records of the new UPDATE change). If an ** UPDATE is changed to a DELETE or INSERT, the new.* record is discarded ** and any "undefined" fields replaced with pseudo-randomly generated ** values. ** ** 7. An UPDATE change that modifies N table columns may be modified so ** that it updates N-1 columns, so long as (N>1). ** ** 8. The "indirect" flag may be toggled for any change. ** ** Entire group of changes may also be operated on: ** ** 9. Duplicate an existing group. ** ** 10. Remove an existing group. ** ** 11. The positions of two groups may be exchanged. ** ** There are also schema changes: ** ** 12. A non-PK column may be added to a table. In this case a NULL ** value is appended to all records. ** ** 13. A PK column may be added to a table. In this case a non-NULL ** value is appended to all INSERT, DELETE and UPDATE old.* records. ** An "undefined" is appended to new.* UPDATE records. ** ** 14. A column may be removed from a table, provided that it is not the ** only PRIMARY KEY column in the table. In this case the corresponding ** field is removed from all records. In cases where this leaves an UPDATE ** with no non-PK, non-undefined fields, the entire change is removed. */ #include "sqlite3.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <ctype.h> #define FUZZ_VALUE_SUB 1 /* Replace one value with a copy of another */ #define FUZZ_VALUE_MOD 2 /* Modify content by 1 bit */ #define FUZZ_VALUE_RND 3 /* Replace with pseudo-random value */ #define FUZZ_CHANGE_DUP 4 /* Duplicate an existing change */ #define FUZZ_CHANGE_DEL 5 /* Completely remove one change */ #define FUZZ_CHANGE_TYPE 6 /* Change the type of one change */ #define FUZZ_CHANGE_FIELD 7 /* Change an UPDATE to modify fewer columns */ #define FUZZ_CHANGE_INDIRECT 8 /* Toggle the "indirect" flag of a change */ #define FUZZ_GROUP_DUP 9 /* Duplicate a change group */ #define FUZZ_GROUP_DEL 10 /* Delete an entire change group */ #define FUZZ_GROUP_SWAP 11 /* Exchange the position of two groups */ #define FUZZ_COLUMN_ADD 12 /* Add column to table definition */ #define FUZZ_COLUMN_ADDPK 13 /* Add PK column to table definition */ #define FUZZ_COLUMN_DEL 14 /* Remove column from table definition */ typedef unsigned char u8; typedef sqlite3_uint64 u64; typedef sqlite3_int64 i64; typedef unsigned int u32; /* ** Show a usage message on stderr then quit. */ static void usage(const char *argv0){ fprintf(stderr, "Usage: %s FILENAME ?SEED N?\n", argv0); exit(1); } /* ** Read the content of a disk file into an in-memory buffer */ static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){ FILE *f; int sz; void *pBuf; f = fopen(zFilename, "rb"); if( f==0 ){ fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename); exit(1); } fseek(f, 0, SEEK_END); sz = (int)ftell(f); rewind(f); pBuf = sqlite3_malloc( sz ? sz : 1 ); if( pBuf==0 ){ fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n", sz, zFilename); exit(1); } if( sz>0 ){ if( fread(pBuf, sz, 1, f)!=1 ){ fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename); exit(1); } fclose(f); } *pSz = sz; *ppBuf = pBuf; } /* ** Write the contents of buffer pBuf, size nBuf bytes, into file zFilename ** on disk. zFilename, if it already exists, is clobbered. */ static void fuzzWriteFile(const char *zFilename, void *pBuf, int nBuf){ FILE *f; f = fopen(zFilename, "wb"); if( f==0 ){ fprintf(stderr, "cannot open \"%s\" for writing\n", zFilename); exit(1); } if( fwrite(pBuf, nBuf, 1, f)!=1 ){ fprintf(stderr, "cannot write to \"%s\"\n", zFilename); exit(1); } fclose(f); } static int fuzzCorrupt(){ return SQLITE_CORRUPT; } /************************************************************************* ** The following block is a copy of the implementation of SQLite function ** sqlite3_randomness. This version has two important differences: ** ** 1. It always uses the same seed. So the sequence of random data output ** is the same for every run of the program. ** ** 2. It is not threadsafe. */ static struct sqlite3PrngType { unsigned char i, j; /* State variables */ unsigned char s[256]; /* State variables */ } sqlite3Prng = { 0xAF, 0x28, { 0x71, 0xF5, 0xB4, 0x6E, 0x80, 0xAB, 0x1D, 0xB8, 0xFB, 0xB7, 0x49, 0xBF, 0xFF, 0x72, 0x2D, 0x14, 0x79, 0x09, 0xE3, 0x78, 0x76, 0xB0, 0x2C, 0x0A, 0x8E, 0x23, 0xEE, 0xDF, 0xE0, 0x9A, 0x2F, 0x67, 0xE1, 0xBE, 0x0E, 0xA7, 0x08, 0x97, 0xEB, 0x77, 0x78, 0xBA, 0x9D, 0xCA, 0x49, 0x4C, 0x60, 0x9A, 0xF6, 0xBD, 0xDA, 0x7F, 0xBC, 0x48, 0x58, 0x52, 0xE5, 0xCD, 0x83, 0x72, 0x23, 0x52, 0xFF, 0x6D, 0xEF, 0x0F, 0x82, 0x29, 0xA0, 0x83, 0x3F, 0x7D, 0xA4, 0x88, 0x31, 0xE7, 0x88, 0x92, 0x3B, 0x9B, 0x3B, 0x2C, 0xC2, 0x4C, 0x71, 0xA2, 0xB0, 0xEA, 0x36, 0xD0, 0x00, 0xF1, 0xD3, 0x39, 0x17, 0x5D, 0x2A, 0x7A, 0xE4, 0xAD, 0xE1, 0x64, 0xCE, 0x0F, 0x9C, 0xD9, 0xF5, 0xED, 0xB0, 0x22, 0x5E, 0x62, 0x97, 0x02, 0xA3, 0x8C, 0x67, 0x80, 0xFC, 0x88, 0x14, 0x0B, 0x15, 0x10, 0x0F, 0xC7, 0x40, 0xD4, 0xF1, 0xF9, 0x0E, 0x1A, 0xCE, 0xB9, 0x1E, 0xA1, 0x72, 0x8E, 0xD7, 0x78, 0x39, 0xCD, 0xF4, 0x5D, 0x2A, 0x59, 0x26, 0x34, 0xF2, 0x73, 0x0B, 0xA0, 0x02, 0x51, 0x2C, 0x03, 0xA3, 0xA7, 0x43, 0x13, 0xE8, 0x98, 0x2B, 0xD2, 0x53, 0xF8, 0xEE, 0x91, 0x7D, 0xE7, 0xE3, 0xDA, 0xD5, 0xBB, 0xC0, 0x92, 0x9D, 0x98, 0x01, 0x2C, 0xF9, 0xB9, 0xA0, 0xEB, 0xCF, 0x32, 0xFA, 0x01, 0x49, 0xA5, 0x1D, 0x9A, 0x76, 0x86, 0x3F, 0x40, 0xD4, 0x89, 0x8F, 0x9C, 0xE2, 0xE3, 0x11, 0x31, 0x37, 0xB2, 0x49, 0x28, 0x35, 0xC0, 0x99, 0xB6, 0xD0, 0xBC, 0x66, 0x35, 0xF7, 0x83, 0x5B, 0xD7, 0x37, 0x1A, 0x2B, 0x18, 0xA6, 0xFF, 0x8D, 0x7C, 0x81, 0xA8, 0xFC, 0x9E, 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC, 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90, 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7 } }; /* ** Generate and return single random byte */ static unsigned char fuzzRandomByte(void){ unsigned char t; sqlite3Prng.i++; t = sqlite3Prng.s[sqlite3Prng.i]; sqlite3Prng.j += t; sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; sqlite3Prng.s[sqlite3Prng.j] = t; t += sqlite3Prng.s[sqlite3Prng.i]; return sqlite3Prng.s[t]; } /* ** Return N random bytes. */ static void fuzzRandomBlob(int nBuf, unsigned char *zBuf){ int i; for(i=0; i<nBuf; i++){ zBuf[i] = fuzzRandomByte(); } } /* ** Return a random integer between 0 and nRange (not inclusive). */ static unsigned int fuzzRandomInt(unsigned int nRange){ unsigned int ret; assert( nRange>0 ); fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret); return (ret % nRange); } static u64 fuzzRandomU64(){ u64 ret; fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret); return ret; } static void fuzzRandomSeed(unsigned int iSeed){ int i; for(i=0; i<256; i+=4){ sqlite3Prng.s[i] ^= ((iSeed >> 24) & 0xFF); sqlite3Prng.s[i+1] ^= ((iSeed >> 16) & 0xFF); sqlite3Prng.s[i+2] ^= ((iSeed >> 8) & 0xFF); sqlite3Prng.s[i+3] ^= ((iSeed >> 0) & 0xFF); } } /* ** End of code for generating pseudo-random values. *************************************************************************/ typedef struct FuzzChangeset FuzzChangeset; typedef struct FuzzChangesetGroup FuzzChangesetGroup; typedef struct FuzzChange FuzzChange; /* ** Object containing partially parsed changeset. */ struct FuzzChangeset { int bPatchset; /* True for a patchset */ FuzzChangesetGroup **apGroup; /* Array of groups in changeset */ int nGroup; /* Number of items in list pGroup */ u8 **apVal; /* Array of all values in changeset */ int nVal; /* Number of used slots in apVal[] */ int nChange; /* Number of changes in changeset */ int nUpdate; /* Number of UPDATE changes in changeset */ }; /* ** There is one object of this type for each change-group (table header) ** in the input changeset. */ struct FuzzChangesetGroup { const char *zTab; /* Name of table */ int nCol; /* Number of columns in table */ u8 *aPK; /* PK array for this table */ u8 *aChange; /* Buffer containing array of changes */ int szChange; /* Size of buffer aChange[] in bytes */ int nChange; /* Number of changes in buffer aChange[] */ }; /* ** Description of a fuzz change to be applied to a changeset. */ struct FuzzChange { int eType; /* One of the FUZZ_* constants above */ int iChange; /* Change or UPDATE to modify */ int iGroup; /* Group to modify */ int iDelete; /* Field to remove (FUZZ_COLUMN_DEL) */ u8 *pSub1; /* Replace this value with pSub2 */ u8 *pSub2; /* And this one with pSub1 */ u8 aSub[128]; /* Buffer for substitute value */ int iCurrent; /* Current change number */ }; /* ** Allocate and return nByte bytes of zeroed memory. */ static void *fuzzMalloc(int nByte){ void *pRet = sqlite3_malloc(nByte); if( pRet ){ memset(pRet, 0, nByte); } return pRet; } /* ** Free the buffer indicated by the first argument. This function is used ** to free buffers allocated by fuzzMalloc(). */ static void fuzzFree(void *p){ sqlite3_free(p); } /* ** Argument p points to a buffer containing an SQLite varint that, assuming the ** input is not corrupt, may be between 0 and 0x7FFFFFFF, inclusive. Before ** returning, this function sets (*pnVal) to the value of that varint, and ** returns the number of bytes of space that it takes up. */ static int fuzzGetVarint(u8 *p, int *pnVal){ int i; sqlite3_uint64 nVal = 0; for(i=0; i<9; i++){ nVal = (nVal<<7) + (p[i] & 0x7F); if( (p[i] & 0x80)==0 ){ i++; break; } } *pnVal = (int)nVal; return i; } /* ** Write value nVal into the buffer indicated by argument p as an SQLite ** varint. nVal is guaranteed to be between 0 and (2^21-1), inclusive. ** Return the number of bytes written to buffer p. */ static int fuzzPutVarint(u8 *p, int nVal){ assert( nVal>0 && nVal<2097152 ); if( nVal<128 ){ p[0] = nVal; return 1; } if( nVal<16384 ){ p[0] = ((nVal >> 7) & 0x7F) | 0x80; p[1] = (nVal & 0x7F); return 2; } p[0] = ((nVal >> 14) & 0x7F) | 0x80; p[1] = ((nVal >> 7) & 0x7F) | 0x80; p[2] = (nVal & 0x7F); return 3; } /* ** Read a 64-bit big-endian integer value from buffer aRec[]. Return ** the value read. */ static i64 fuzzGetI64(u8 *aRec){ return (i64)( (((u64)aRec[0]) << 56) + (((u64)aRec[1]) << 48) + (((u64)aRec[2]) << 40) + (((u64)aRec[3]) << 32) + (((u64)aRec[4]) << 24) + (((u64)aRec[5]) << 16) + (((u64)aRec[6]) << 8) + (((u64)aRec[7]) << 0) ); } /* ** Write value iVal to buffer aRec[] as an unsigned 64-bit big-endian integer. */ static void fuzzPutU64(u8 *aRec, u64 iVal){ aRec[0] = (iVal>>56) & 0xFF; aRec[1] = (iVal>>48) & 0xFF; aRec[2] = (iVal>>40) & 0xFF; aRec[3] = (iVal>>32) & 0xFF; aRec[4] = (iVal>>24) & 0xFF; aRec[5] = (iVal>>16) & 0xFF; aRec[6] = (iVal>> 8) & 0xFF; aRec[7] = (iVal) & 0xFF; } /* ** Parse a single table-header from the input. Allocate a new change-group ** object with the results. Return SQLITE_OK if successful, or an error code ** otherwise. */ static int fuzzParseHeader( FuzzChangeset *pParse, /* Changeset parse object */ u8 **ppHdr, /* IN/OUT: Iterator */ u8 *pEnd, /* 1 byte past EOF */ FuzzChangesetGroup **ppGrp /* OUT: New change-group object */ ){ int rc = SQLITE_OK; FuzzChangesetGroup *pGrp; u8 cHdr = (pParse->bPatchset ? 'P' : 'T'); assert( pEnd>(*ppHdr) ); pGrp = (FuzzChangesetGroup*)fuzzMalloc(sizeof(FuzzChangesetGroup)); if( !pGrp ){ rc = SQLITE_NOMEM; }else{ u8 *p = *ppHdr; if( p[0]!=cHdr ){ rc = fuzzCorrupt(); }else{ p++; p += fuzzGetVarint(p, &pGrp->nCol); pGrp->aPK = p; p += pGrp->nCol; pGrp->zTab = (const char*)p; p = &p[strlen(p)+1]; if( p>=pEnd ){ rc = fuzzCorrupt(); } } *ppHdr = p; } if( rc!=SQLITE_OK ){ fuzzFree(pGrp); pGrp = 0; } *ppGrp = pGrp; return rc; } /* ** Argument p points to a buffer containing a single changeset-record value. ** This function attempts to determine the size of the value in bytes. If ** successful, it sets (*pSz) to the size and returns SQLITE_OK. Or, if the ** buffer does not contain a valid value, SQLITE_CORRUPT is returned and ** the final value of (*pSz) is undefined. */ static int fuzzChangeSize(u8 *p, int *pSz){ u8 eType = p[0]; switch( eType ){ case 0x00: /* undefined */ case 0x05: /* null */ *pSz = 1; break; case 0x01: /* integer */ case 0x02: /* real */ *pSz = 9; break; case 0x03: /* text */ case 0x04: { /* blob */ int nTxt; int sz; sz = fuzzGetVarint(&p[1], &nTxt); *pSz = 1 + sz + nTxt; break; } default: return fuzzCorrupt(); } return SQLITE_OK; } /* ** When this function is called, (*ppRec) points to the start of a ** record in a changeset being parsed. This function adds entries ** to the pParse->apVal[] array for all values and advances (*ppRec) ** to one byte past the end of the record. Argument pEnd points to ** one byte past the end of the input changeset. ** ** Argument bPkOnly is true if the record being parsed is part of ** a DELETE record in a patchset. In this case, all non-primary-key ** fields have been omitted from the record. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ static int fuzzParseRecord( u8 **ppRec, /* IN/OUT: Iterator */ u8 *pEnd, /* One byte after end of input data */ FuzzChangeset *pParse, /* Changeset parse context */ int bPkOnly /* True if non-PK fields omitted */ ){ int rc = SQLITE_OK; FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1]; int i; u8 *p = *ppRec; for(i=0; rc==SQLITE_OK && i<pGrp->nCol; i++){ if( bPkOnly==0 || pGrp->aPK[i] ){ int sz; if( p>=pEnd ) break; if( (pParse->nVal & (pParse->nVal-1))==0 ){ int nNew = pParse->nVal ? pParse->nVal*2 : 4; u8 **apNew = (u8**)sqlite3_realloc(pParse->apVal, nNew*sizeof(u8*)); if( apNew==0 ) return SQLITE_NOMEM; pParse->apVal = apNew; } pParse->apVal[pParse->nVal++] = p; rc = fuzzChangeSize(p, &sz); p += sz; } } if( rc==SQLITE_OK && i<pGrp->nCol ){ rc = fuzzCorrupt(); } *ppRec = p; return rc; } /* ** Parse the array of changes starting at (*ppData) and add entries for ** all values to the pParse->apVal[] array. Argument pEnd points to one byte ** past the end of the input changeset. If successful, set (*ppData) to point ** to one byte past the end of the change array and return SQLITE_OK. ** Otherwise, return an SQLite error code. The final value of (*ppData) is ** undefined in this case. */ static int fuzzParseChanges(u8 **ppData, u8 *pEnd, FuzzChangeset *pParse){ u8 cHdr = (pParse->bPatchset ? 'P' : 'T'); FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1]; int rc = SQLITE_OK; u8 *p = *ppData; pGrp->aChange = p; while( rc==SQLITE_OK && p<pEnd && p[0]!=cHdr ){ u8 eOp = p[0]; u8 bIndirect = p[1]; p += 2; if( eOp==SQLITE_UPDATE ){ pParse->nUpdate++; if( pParse->bPatchset==0 ){ rc = fuzzParseRecord(&p, pEnd, pParse, 0); } }else if( eOp!=SQLITE_INSERT && eOp!=SQLITE_DELETE ){ rc = fuzzCorrupt(); } if( rc==SQLITE_OK ){ int bPkOnly = (eOp==SQLITE_DELETE && pParse->bPatchset); rc = fuzzParseRecord(&p, pEnd, pParse, bPkOnly); } pGrp->nChange++; pParse->nChange++; } pGrp->szChange = p - pGrp->aChange; *ppData = p; return rc; } /* ** Parse the changeset stored in buffer pChangeset (nChangeset bytes in ** size). If successful, write the results into (*pParse) and return ** SQLITE_OK. Or, if an error occurs, return an SQLite error code. The ** final state of (*pParse) is undefined in this case. */ static int fuzzParseChangeset( u8 *pChangeset, /* Buffer containing changeset */ int nChangeset, /* Size of buffer in bytes */ FuzzChangeset *pParse /* OUT: Results of parse */ ){ u8 *pEnd = &pChangeset[nChangeset]; u8 *p = pChangeset; int rc = SQLITE_OK; memset(pParse, 0, sizeof(FuzzChangeset)); if( nChangeset>0 ){ pParse->bPatchset = (pChangeset[0]=='P'); } while( rc==SQLITE_OK && p<pEnd ){ FuzzChangesetGroup *pGrp = 0; /* Read a table-header from the changeset */ rc = fuzzParseHeader(pParse, &p, pEnd, &pGrp); assert( (rc==SQLITE_OK)==(pGrp!=0) ); /* If the table-header was successfully parsed, add the new change-group ** to the array and parse the associated changes. */ if( rc==SQLITE_OK ){ FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc( pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1) ); if( apNew==0 ){ rc = SQLITE_NOMEM; }else{ apNew[pParse->nGroup] = pGrp; pParse->apGroup = apNew; pParse->nGroup++; } rc = fuzzParseChanges(&p, pEnd, pParse); } } return rc; } /* ** When this function is called, (*ppRec) points to the first byte of ** a record that is part of change-group pGrp. This function attempts ** to output a human-readable version of the record to stdout and advance ** (*ppRec) to point to the first byte past the end of the record before ** returning. If successful, SQLITE_OK is returned. Otherwise, an SQLite ** error code. ** ** If parameter bPkOnly is non-zero, then all non-primary-key fields have ** been omitted from the record. This occurs for records that are part ** of DELETE changes in patchsets. */ static int fuzzPrintRecord(FuzzChangesetGroup *pGrp, u8 **ppRec, int bPKOnly){ int rc = SQLITE_OK; u8 *p = *ppRec; int i; const char *zPre = " ("; for(i=0; i<pGrp->nCol; i++){ if( bPKOnly==0 || pGrp->aPK[i] ){ u8 eType = p++[0]; switch( eType ){ case 0x00: /* undefined */ printf("%sn/a", zPre); break; case 0x01: { /* integer */ sqlite3_int64 iVal = 0; iVal = fuzzGetI64(p); printf("%s%lld", zPre, iVal); p += 8; break; } case 0x02: { /* real */ sqlite3_int64 iVal = 0; double fVal = 0.0; iVal = fuzzGetI64(p); memcpy(&fVal, &iVal, 8); printf("%s%f", zPre, fVal); p += 8; break; } case 0x03: /* text */ case 0x04: { /* blob */ int nTxt; int sz; int i; p += fuzzGetVarint(p, &nTxt); printf("%s%s", zPre, eType==0x03 ? "'" : "X'"); for(i=0; i<nTxt; i++){ if( eType==0x03 ){ printf("%c", p[i]); }else{ char aHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; printf("%c", aHex[ p[i]>>4 ]); printf("%c", aHex[ p[i] & 0x0F ]); } } printf("'"); p += nTxt; break; } case 0x05: /* null */ printf("%sNULL", zPre); break; } zPre = ", "; } } printf(")"); *ppRec = p; return rc; } /* ** Print a human-readable version of the table-header and all changes in the ** change-group passed as the second argument. */ static void fuzzPrintGroup(FuzzChangeset *pParse, FuzzChangesetGroup *pGrp){ int i; u8 *p; /* The table header */ printf("TABLE: %s nCol=%d aPK=", pGrp->zTab, pGrp->nCol); for(i=0; i<pGrp->nCol; i++){ printf("%d", (int)pGrp->aPK[i]); } printf("\n"); /* The array of changes */ p = pGrp->aChange; for(i=0; i<pGrp->nChange; i++){ u8 eType = p[0]; u8 bIndirect = p[1]; printf("%s (ind=%d):", (eType==SQLITE_INSERT) ? "INSERT" : (eType==SQLITE_DELETE ? "DELETE" : "UPDATE"), bIndirect ); p += 2; if( pParse->bPatchset==0 && eType==SQLITE_UPDATE ){ fuzzPrintRecord(pGrp, &p, 0); } fuzzPrintRecord(pGrp, &p, eType==SQLITE_DELETE && pParse->bPatchset); printf("\n"); } } /* ** Initialize the object passed as the second parameter with details ** of the change that will be attempted (type of change, to which part of the ** changeset it applies etc.). If successful, return SQLITE_OK. Or, if an ** error occurs, return an SQLite error code. ** ** If a negative value is returned, then the selected change would have ** produced a non-well-formed changeset. In this case the caller should ** call this function again. */ static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){ int iSub; memset(pChange, 0, sizeof(FuzzChange)); pChange->eType = fuzzRandomInt(FUZZ_COLUMN_DEL) + 1; assert( pChange->eType==FUZZ_VALUE_SUB || pChange->eType==FUZZ_VALUE_MOD || pChange->eType==FUZZ_VALUE_RND || pChange->eType==FUZZ_CHANGE_DUP || pChange->eType==FUZZ_CHANGE_DEL || pChange->eType==FUZZ_CHANGE_TYPE || pChange->eType==FUZZ_CHANGE_FIELD || pChange->eType==FUZZ_CHANGE_INDIRECT || pChange->eType==FUZZ_GROUP_DUP || pChange->eType==FUZZ_GROUP_DEL || pChange->eType==FUZZ_GROUP_SWAP || pChange->eType==FUZZ_COLUMN_ADD || pChange->eType==FUZZ_COLUMN_ADDPK || pChange->eType==FUZZ_COLUMN_DEL ); pChange->iGroup = fuzzRandomInt(pParse->nGroup); pChange->iChange = fuzzRandomInt(pParse->nChange); if( pChange->eType==FUZZ_CHANGE_FIELD ){ if( pParse->nUpdate==0 ) return -1; pChange->iChange = fuzzRandomInt(pParse->nUpdate); } pChange->iDelete = -1; if( pChange->eType==FUZZ_COLUMN_DEL ){ FuzzChangesetGroup *pGrp = pParse->apGroup[pChange->iGroup]; int i; pChange->iDelete = fuzzRandomInt(pGrp->nCol); for(i=pGrp->nCol-1; i>=0; i--){ if( pGrp->aPK[i] && pChange->iDelete!=i ) break; } if( i<0 ) return -1; } if( pChange->eType==FUZZ_GROUP_SWAP ){ FuzzChangesetGroup *pGrp; int iGrp = pChange->iGroup; if( pParse->nGroup==1 ) return -1; while( iGrp==pChange->iGroup ){ iGrp = fuzzRandomInt(pParse->nGroup); } pGrp = pParse->apGroup[pChange->iGroup]; pParse->apGroup[pChange->iGroup] = pParse->apGroup[iGrp]; pParse->apGroup[iGrp] = pGrp; } if( pChange->eType==FUZZ_VALUE_SUB || pChange->eType==FUZZ_VALUE_MOD || pChange->eType==FUZZ_VALUE_RND ){ iSub = fuzzRandomInt(pParse->nVal); pChange->pSub1 = pParse->apVal[iSub]; if( pChange->eType==FUZZ_VALUE_SUB ){ iSub = fuzzRandomInt(pParse->nVal); pChange->pSub2 = pParse->apVal[iSub]; }else{ pChange->pSub2 = pChange->aSub; } if( pChange->eType==FUZZ_VALUE_RND ){ pChange->aSub[0] = (u8)(fuzzRandomInt(5) + 1); switch( pChange->aSub[0] ){ case 0x01: { /* integer */ u64 iVal = fuzzRandomU64(); fuzzPutU64(&pChange->aSub[1], iVal); break; } case 0x02: { /* real */ u64 iVal1 = fuzzRandomU64(); u64 iVal2 = fuzzRandomU64(); double d = (double)iVal1 / (double)iVal2; memcpy(&iVal1, &d, sizeof(iVal1)); fuzzPutU64(&pChange->aSub[1], iVal1); break; } case 0x03: /* text */ case 0x04: { /* blob */ int nByte = fuzzRandomInt(48); pChange->aSub[1] = nByte; fuzzRandomBlob(nByte, &pChange->aSub[2]); if( pChange->aSub[0]==0x03 ){ int i; for(i=0; i<nByte; i++){ pChange->aSub[2+i] &= 0x7F; } } break; } } } if( pChange->eType==FUZZ_VALUE_MOD ){ int sz; int iMod = -1; fuzzChangeSize(pChange->pSub1, &sz); memcpy(pChange->aSub, pChange->pSub1, sz); switch( pChange->aSub[0] ){ case 0x01: case 0x02: iMod = fuzzRandomInt(8) + 1; break; case 0x03: /* text */ case 0x04: { /* blob */ int nByte; int iFirst = 1 + fuzzGetVarint(&pChange->aSub[1], &nByte); if( nByte>0 ){ iMod = fuzzRandomInt(nByte) + iFirst; } break; } } if( iMod>=0 ){ u8 mask = (1 << fuzzRandomInt(8 - (pChange->aSub[0]==0x03))); pChange->aSub[iMod] ^= mask; } } } return SQLITE_OK; } /* ** Copy a single change from the input to the output changeset, making ** any modifications specified by (*pFuzz). */ static int fuzzCopyChange( FuzzChangeset *pParse, int iGrp, FuzzChange *pFuzz, u8 **pp, u8 **ppOut /* IN/OUT: Input and output pointers */ ){ int bPS = pParse->bPatchset; FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp]; u8 *p = *pp; u8 *pOut = *ppOut; u8 eType = p++[0]; int iRec; int nRec = ((eType==SQLITE_UPDATE && !bPS) ? 2 : 1); int iUndef = -1; int nUpdate = 0; u8 eNew = eType; if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_TYPE ){ switch( eType ){ case SQLITE_INSERT: eNew = SQLITE_DELETE; break; case SQLITE_DELETE: eNew = SQLITE_UPDATE; break; case SQLITE_UPDATE: eNew = SQLITE_INSERT; break; } } if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_FIELD && eType==SQLITE_UPDATE ){ int sz; int i; int nDef = 0; u8 *pCsr = p+1; for(i=0; i<pGrp->nCol; i++){ if( pCsr[0] && pGrp->aPK[i]==0 ) nDef++; fuzzChangeSize(pCsr, &sz); pCsr += sz; } if( nDef<=1 ) return -1; nDef = fuzzRandomInt(nDef); pCsr = p+1; for(i=0; i<pGrp->nCol; i++){ if( pCsr[0] && pGrp->aPK[i]==0 ){ if( nDef==0 ) iUndef = i; nDef--; } fuzzChangeSize(pCsr, &sz); pCsr += sz; } } /* Copy the change type and indirect flag. If the fuzz mode is ** FUZZ_CHANGE_INDIRECT, and the current change is the one selected for ** fuzzing, invert the indirect flag. */ *(pOut++) = eNew; if( pFuzz->eType==FUZZ_CHANGE_INDIRECT && pFuzz->iCurrent==pFuzz->iChange ){ *(pOut++) = !(*(p++)); }else{ *(pOut++) = *(p++); } for(iRec=0; iRec<nRec; iRec++){ int i; /* Copy the next record from the output to the input. */ for(i=0; i<pGrp->nCol; i++){ int sz; u8 *pCopy = p; /* If this is a patchset, and the input is a DELETE, then the only ** fields present are the PK fields. So, if this is not a PK, skip to ** the next column. If the current fuzz is FUZZ_CHANGE_TYPE, then ** write a randomly selected value to the output. */ if( bPS && eType==SQLITE_DELETE && pGrp->aPK[i]==0 ){ if( eType!=eNew ){ assert( eNew==SQLITE_UPDATE ); do { pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)]; }while( pCopy[0]==0x00 ); fuzzChangeSize(pCopy, &sz); memcpy(pOut, pCopy, sz); pOut += sz; } continue; } if( p==pFuzz->pSub1 ){ pCopy = pFuzz->pSub2; }else if( p==pFuzz->pSub2 ){ pCopy = pFuzz->pSub1; }else if( i==iUndef ){ pCopy = "\0"; } if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){ while( pCopy[0]==0x00 ){ pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)]; } }else if( p[0]==0x00 && pCopy[0]!=0x00 ){ return -1; }else{ if( pGrp->aPK[i]>0 && pCopy[0]==0x05 ) return -1; } if( (pFuzz->iGroup!=iGrp || i!=pFuzz->iDelete) && (eNew==eType || eType!=SQLITE_UPDATE || iRec==0) && (eNew==eType || eNew!=SQLITE_DELETE || !bPS || pGrp->aPK[i]) ){ fuzzChangeSize(pCopy, &sz); memcpy(pOut, pCopy, sz); pOut += sz; nUpdate += (pGrp->aPK[i]==0 && pCopy[0]!=0x00); } fuzzChangeSize(p, &sz); p += sz; } if( iGrp==pFuzz->iGroup ){ if( pFuzz->eType==FUZZ_COLUMN_ADD ){ if( !bPS || eType!=SQLITE_DELETE ) *(pOut++) = 0x05; }else if( pFuzz->eType==FUZZ_COLUMN_ADDPK ){ if( iRec==1 ){ *(pOut++) = 0x00; }else{ u8 *pNew; int szNew; do { pNew = pParse->apVal[fuzzRandomInt(pParse->nVal)]; }while( pNew[0]==0x00 || pNew[0]==0x05 ); fuzzChangeSize(pNew, &szNew); memcpy(pOut, pNew, szNew); pOut += szNew; } } } } if( pFuzz->iCurrent==pFuzz->iChange ){ if( pFuzz->eType==FUZZ_CHANGE_DUP ){ int nByte = pOut - (*ppOut); memcpy(pOut, *ppOut, nByte); pOut += nByte; } if( pFuzz->eType==FUZZ_CHANGE_DEL ){ pOut = *ppOut; } if( eNew!=eType && eNew==SQLITE_UPDATE && !bPS ){ int i; u8 *pCsr = (*ppOut) + 2; for(i=0; i<pGrp->nCol; i++){ int sz; u8 *pCopy = pCsr; if( pGrp->aPK[i] ) pCopy = "\0"; fuzzChangeSize(pCopy, &sz); memcpy(pOut, pCopy, sz); pOut += sz; fuzzChangeSize(pCsr, &sz); pCsr += sz; } } } /* If a column is being deleted from this group, and this change was an ** UPDATE, and there are now no non-PK, non-undefined columns in the ** change, remove it altogether. */ if( pFuzz->eType==FUZZ_COLUMN_DEL && pFuzz->iGroup==iGrp && eType==SQLITE_UPDATE && nUpdate==0 ){ pOut = *ppOut; } *pp = p; *ppOut = pOut; pFuzz->iCurrent += (eType==SQLITE_UPDATE || pFuzz->eType!=FUZZ_CHANGE_FIELD); return SQLITE_OK; } /* ** Fuzz the changeset parsed into object pParse and write the results ** to file zOut on disk. Argument pBuf points to a buffer that is guaranteed ** to be large enough to hold the fuzzed changeset. ** ** Return SQLITE_OK if successful, or an SQLite error code if an error occurs. */ static int fuzzDoOneFuzz( const char *zOut, /* Filename to write modified changeset to */ u8 *pBuf, /* Buffer to use for modified changeset */ FuzzChangeset *pParse /* Parse of input changeset */ ){ FuzzChange change; int iGrp; int rc = -1; while( rc<0 ){ u8 *pOut = pBuf; rc = fuzzSelectChange(pParse, &change); for(iGrp=0; rc==SQLITE_OK && iGrp<pParse->nGroup; iGrp++){ FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp]; int nTab = strlen(pGrp->zTab) + 1; int j; int nRep = 1; /* If this is the group to delete for a FUZZ_GROUP_DEL change, jump to ** the next group. Unless this is the only group in the changeset - in ** that case this change cannot be applied. ** ** Or, if this is a FUZZ_GROUP_DUP, set nRep to 2 to output two ** copies of the group. */ if( change.iGroup==iGrp ){ if( change.eType==FUZZ_GROUP_DEL ){ if( pParse->nGroup==1 ) rc = -1; continue; } else if( change.eType==FUZZ_GROUP_DUP ){ nRep = 2; } } for(j=0; j<nRep; j++){ int i; u8 *pSaved; u8 *p = pGrp->aChange; int nCol = pGrp->nCol; int iPKDel = 0; if( iGrp==change.iGroup ){ if( change.eType==FUZZ_COLUMN_ADD || change.eType==FUZZ_COLUMN_ADDPK ){ nCol++; }else if( change.eType==FUZZ_COLUMN_DEL ){ nCol--; iPKDel = pGrp->aPK[change.iDelete]; } } /* Output a table header */ pOut++[0] = pParse->bPatchset ? 'P' : 'T'; pOut += fuzzPutVarint(pOut, nCol); for(i=0; i<pGrp->nCol; i++){ if( iGrp!=change.iGroup || i!=change.iDelete ){ u8 v = pGrp->aPK[i]; if( iPKDel && v>iPKDel ) v--; *(pOut++) = v; } } if( nCol>pGrp->nCol ){ if( change.eType==FUZZ_COLUMN_ADD ){ *(pOut++) = 0x00; }else{ u8 max = 0; for(i=0; i<pGrp->nCol; i++){ if( pGrp->aPK[i]>max ) max = pGrp->aPK[i]; } *(pOut++) = max+1; } } memcpy(pOut, pGrp->zTab, nTab); pOut += nTab; /* Output the change array. */ pSaved = pOut; for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){ rc = fuzzCopyChange(pParse, iGrp, &change, &p, &pOut); } if( pOut==pSaved ) rc = -1; } } if( rc==SQLITE_OK ){ fuzzWriteFile(zOut, pBuf, pOut-pBuf); } } return rc; } int main(int argc, char **argv){ int nRepeat = 0; /* Number of output files */ int iSeed = 0; /* Value of PRNG seed */ const char *zInput; /* Name of input file */ void *pChangeset = 0; /* Input changeset */ int nChangeset = 0; /* Size of input changeset in bytes */ int i; /* Current output file */ FuzzChangeset changeset; /* Partially parsed changeset */ int rc; u8 *pBuf = 0; if( argc!=4 && argc!=2 ) usage(argv[0]); zInput = argv[1]; fuzzReadFile(zInput, &nChangeset, &pChangeset); rc = fuzzParseChangeset(pChangeset, nChangeset, &changeset); if( rc==SQLITE_OK ){ if( argc==2 ){ for(i=0; i<changeset.nGroup; i++){ fuzzPrintGroup(&changeset, changeset.apGroup[i]); } }else{ pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024); if( pBuf==0 ){ rc = SQLITE_NOMEM; }else{ iSeed = atoi(argv[2]); nRepeat = atoi(argv[3]); fuzzRandomSeed((unsigned int)iSeed); for(i=0; rc==SQLITE_OK && i<nRepeat; i++){ char *zOut = sqlite3_mprintf("%s-%d", zInput, i); rc = fuzzDoOneFuzz(zOut, pBuf, &changeset); sqlite3_free(zOut); } fuzzFree(pBuf); } } } if( rc!=SQLITE_OK ){ fprintf(stderr, "error while processing changeset: %d\n", rc); } return rc; } |
Added ext/session/changesetfuzz1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | # 2018 November 08 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix changesetfuzz1 set CF [test_find_binary changesetfuzz] if {$CF==""} { finish_test return } proc writefile {zFile data} { set fd [open $zFile w] fconfigure $fd -translation binary -encoding binary puts -nonewline $fd $data close $fd } do_execsql_test 1.0 { CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, d)); CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); INSERT INTO t1 VALUES ('one', 'two', 'three', 'four'), ('five', 'six', 'seven', 'eight'), ('nine', 'ten', 'eleven', 'twelve'); INSERT INTO t2 VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); } set C [changeset_from_sql { INSERT INTO t2 VALUES(10, 11, 12); DELETE FROM t2 WHERE a=1; UPDATE t1 SET b='forty-five' WHERE a='one'; UPDATE t1 SET a='twenty-nine', b='seventy' WHERE a='five'; }] writefile c1.changeset $C do_test 1.1 { for {set j 0} {$j < 200} {incr j} { forcecopy c1.changeset input.changeset for {set i 0} {$i < 6} {incr i} { exec $CF input.changeset $i 1 exec $CF input.changeset-0 forcecopy input.changeset-0 input.changeset } } } {} set P [patchset_from_sql { INSERT INTO t2 VALUES(13, 14, 15); DELETE FROM t2 WHERE a=4; UPDATE t1 SET b='thirteen' WHERE a='one'; UPDATE t1 SET a='ninety-seven', b='twenty' WHERE a='five'; }] writefile p1.patchset $P do_test 1.2 { for {set j 0} {$j < 200} {incr j} { forcecopy p1.patchset input.patchset for {set i 0} {$i < 6} {incr i} { exec $CF input.patchset $i 1 exec $CF input.patchset-0 forcecopy input.patchset-0 input.patchset } } } {} finish_test |
Changes to ext/session/sessionC.test.
︙ | ︙ | |||
191 192 193 194 195 196 197 | SELECT * FROM t3; } } {1 1 3 3} finish_test | < | 191 192 193 194 195 196 197 | SELECT * FROM t3; } } {1 1 3 3} finish_test |
Changes to ext/session/sessionD.test.
︙ | ︙ | |||
251 252 253 254 255 256 257 | } {0 {}} S delete do_catchsql_test 4.5.2 { SELECT * FROM ixua.i8; } {1 {no such table: ixua.i8}} finish_test | < | 251 252 253 254 255 256 257 | } {0 {}} S delete do_catchsql_test 4.5.2 { SELECT * FROM ixua.i8; } {1 {no such table: ixua.i8}} finish_test |
Changes to ext/session/sessionE.test.
︙ | ︙ | |||
107 108 109 110 111 112 113 | {INSERT t2 0 X. {} {i 7 i 8}} } S delete finish_test | < < | 107 108 109 110 111 112 113 | {INSERT t2 0 X. {} {i 7 i 8}} } S delete finish_test |
Changes to ext/session/sessionF.test.
︙ | ︙ | |||
288 289 290 291 292 293 294 | } do_test 3.$tn { set res } [list {*}$result] } finish_test | < | 288 289 290 291 292 293 294 | } do_test 3.$tn { set res } [list {*}$result] } finish_test |
Changes to ext/session/sessionG.test.
︙ | ︙ | |||
244 245 246 247 248 249 250 | SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; } {0} # db eval { SELECT * FROM t1 } { puts "$a || $b" } finish_test | < | 244 245 246 247 248 249 250 | SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; } {0} # db eval { SELECT * FROM t1 } { puts "$a || $b" } finish_test |
Changes to ext/session/sessionH.test.
︙ | ︙ | |||
32 33 34 35 36 37 38 | INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s; } compare_db db db2 } {} finish_test | < | 32 33 34 35 36 37 38 | INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s; } compare_db db db2 } {} finish_test |
Changes to ext/session/sessionfault2.test.
︙ | ︙ | |||
278 279 280 281 282 283 284 | } -test { catch { R delete } faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } finish_test | < | 278 279 280 281 282 283 284 | } -test { catch { R delete } faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } finish_test |
Changes to ext/session/sessionrebase.test.
︙ | ︙ | |||
470 471 472 473 474 475 476 | R configure $::rebase expr [catch {R rebase $P}]==0 } $rebasable catch { R delete } } finish_test | < | 470 471 472 473 474 475 476 | R configure $::rebase expr [catch {R rebase $P}]==0 } $rebasable catch { R delete } } finish_test |
Changes to ext/session/sessionstat1.test.
︙ | ︙ | |||
304 305 306 307 308 309 310 | return "REPLACE" } sqlite3changeset_apply db2 $C xConflict execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2 } {t3 null 3} finish_test | < | 304 305 306 307 308 309 310 | return "REPLACE" } sqlite3changeset_apply db2 $C xConflict execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2 } {t3 null 3} finish_test |
Changes to ext/session/sessionwor.test.
︙ | ︙ | |||
50 51 52 53 54 55 56 | do_iterator_test 1.3 t1 { DELETE FROM t1; } { {DELETE t1 0 X. {t one t three} {}} } finish_test | < | 50 51 52 53 54 55 56 | do_iterator_test 1.3 t1 { DELETE FROM t1; } { {DELETE t1 0 X. {t one t three} {}} } finish_test |
Changes to main.mk.
︙ | ︙ | |||
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 | showshm$(EXE): $(TOP)/tool/showshm.c $(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \ $(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB) fts3view$(EXE): $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \ $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB) rollback-test$(EXE): $(TOP)/tool/rollback-test.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o rollback-test$(EXE) \ | > > > > | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 | showshm$(EXE): $(TOP)/tool/showshm.c $(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \ $(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB) changesetfuzz$(EXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changesetfuzz$(EXE) \ $(TOP)/ext/session/changesetfuzz.c sqlite3.o $(THREADLIB) fts3view$(EXE): $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \ $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB) rollback-test$(EXE): $(TOP)/tool/rollback-test.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o rollback-test$(EXE) \ |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
102 103 104 105 106 107 108 | savedDbFlags = db->mDbFlags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | savedDbFlags = db->mDbFlags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0); zDb = db->aDb[iDb].zDbSName; db->mDbFlags |= DBFLAG_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); if( !zName ) goto exit_rename_table; |
︙ | ︙ | |||
144 145 146 147 148 149 150 | /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ goto exit_rename_table; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE | | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ goto exit_rename_table; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ goto exit_rename_table; } if( IsVirtual(pTab) ){ pVTab = sqlite3GetVTable(db, -1, pTab); if( pVTab->pVtab->pModule->xRename==0 ){ pVTab = 0; } } #endif /* Begin a transaction for database iDb. |
︙ | ︙ | |||
272 273 274 275 276 277 278 | db = pParse->db; if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); | | | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | db = pParse->db; if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema, 0); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; pTab = sqlite3FindTable(db, zTab, zDb); assert( pTab ); |
︙ | ︙ | |||
425 426 427 428 429 430 431 | goto exit_begin_add_column; } if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ goto exit_begin_add_column; } assert( pTab->addColOffset>0 ); | | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | goto exit_begin_add_column; } if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ goto exit_begin_add_column; } assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. But modify ** the name by adding an "sqlite_altertab_" prefix. By adding this ** prefix, we insure that the name will not collide with an existing ** table because user table are not allowed to have the "sqlite_" ** prefix on their name. |
︙ | ︙ | |||
526 527 528 529 530 531 532 | if( !pTab ) goto exit_rename_column; /* Cannot alter a system table */ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column; if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column; /* Which schema holds the table to be altered */ | | | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | if( !pTab ) goto exit_rename_column; /* Cannot alter a system table */ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column; if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column; /* Which schema holds the table to be altered */ iSchema = sqlite3SchemaToIndex(db, pTab->pSchema, 0); assert( iSchema>=0 ); zDb = db->aDb[iSchema].zDbSName; #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ goto exit_rename_column; |
︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 | NameContext sNC; int rc = SQLITE_OK; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; assert( pNew->pTabSchema ); pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, | | > | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 | NameContext sNC; int rc = SQLITE_OK; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; assert( pNew->pTabSchema ); pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema, 0)].zDbSName ); pParse->eTriggerOp = pNew->op; /* ALWAYS() because if the table of the trigger does not exist, the ** error would have been hit before this point */ if( ALWAYS(pParse->pTriggerTab) ){ int iDb = sqlite3SchemaToIndex(db, pParse->pTriggerTab->pSchema, 0); rc = sqlite3ViewGetColumnNames(pParse, iDb, pParse->pTriggerTab); } /* Resolve symbols in WHEN clause */ if( rc==SQLITE_OK && pNew->pWhen ){ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); } for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ if( pStep->pSelect ){ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); if( pParse->nErr ) rc = pParse->rc; } if( rc==SQLITE_OK && pStep->zTarget ){ Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb); if( pTarget==0 ){ rc = SQLITE_ERROR; }else{ int iDb = sqlite3SchemaToIndex(db, pTarget->pSchema, 0); if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, iDb, pTarget)) ){ SrcList sSrc; memset(&sSrc, 0, sizeof(sSrc)); sSrc.nSrc = 1; sSrc.a[0].zName = pStep->zTarget; sSrc.a[0].pTab = pTarget; sNC.pSrcList = &sSrc; if( pStep->pWhere ){ rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); } if( rc==SQLITE_OK ){ rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); } assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); if( pStep->pUpsert ){ Upsert *pUpsert = pStep->pUpsert; assert( rc==SQLITE_OK ); pUpsert->pUpsertSrc = &sSrc; sNC.uNC.pUpsert = pUpsert; sNC.ncFlags = NC_UUpsert; rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); if( rc==SQLITE_OK ){ ExprList *pUpsertSet = pUpsert->pUpsertSet; rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); } if( rc==SQLITE_OK ){ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); } if( rc==SQLITE_OK ){ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); } sNC.ncFlags = 0; } } } } } return rc; } |
︙ | ︙ | |||
1440 1441 1442 1443 1444 1445 1446 | sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); if( sParse.nErr ) rc = sParse.rc; sqlite3WalkSelect(&sWalker, pTab->pSelect); } }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY | | | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); if( sParse.nErr ) rc = sParse.rc; sqlite3WalkSelect(&sWalker, pTab->pSelect); } }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ FKey *pFKey; for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); } } } |
︙ | ︙ | |||
1571 1572 1573 1574 1575 1576 1577 | } else if( sParse.pNewTrigger ){ if( isLegacy==0 ){ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); } if( rc==SQLITE_OK ){ | | | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | } else if( sParse.pNewTrigger ){ if( isLegacy==0 ){ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); } if( rc==SQLITE_OK ){ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema, 0); int i2 = sqlite3FindDbName(db, zDb); if( i1==i2 ) sqlite3_result_int(context, 1); } } } if( rc!=SQLITE_OK ){ |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 | /* ** Generate code to do an analysis of all indices associated with ** a single table. */ static void analyzeOneTable( Parse *pParse, /* Parser context */ Table *pTab, /* Table whose indices are to be analyzed */ Index *pOnlyIdx, /* If not NULL, only analyze this one index */ int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ int iMem, /* Available memory locations begin here */ int iTab /* Next available cursor */ ){ sqlite3 *db = pParse->db; /* Database handle */ Index *pIdx; /* An index to being analyzed */ int iIdxCur; /* Cursor open on index being analyzed */ int iTabCur; /* Table cursor */ Vdbe *v; /* The virtual machine being built up */ int i; /* Loop counter */ int jZeroRows = -1; /* Jump from here if number of rows is zero */ | > < | 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 | /* ** Generate code to do an analysis of all indices associated with ** a single table. */ static void analyzeOneTable( Parse *pParse, /* Parser context */ int iDb, /* Database that contains table pTab */ Table *pTab, /* Table whose indices are to be analyzed */ Index *pOnlyIdx, /* If not NULL, only analyze this one index */ int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ int iMem, /* Available memory locations begin here */ int iTab /* Next available cursor */ ){ sqlite3 *db = pParse->db; /* Database handle */ Index *pIdx; /* An index to being analyzed */ int iIdxCur; /* Cursor open on index being analyzed */ int iTabCur; /* Table cursor */ Vdbe *v; /* The virtual machine being built up */ int i; /* Loop counter */ int jZeroRows = -1; /* Jump from here if number of rows is zero */ u8 needTableCnt = 1; /* True to count the table */ int regNewRowid = iMem++; /* Rowid for the inserted record */ int regStat4 = iMem++; /* Register to hold Stat4Accum object */ int regChng = iMem++; /* Index of changed index field */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int regRowid = iMem++; /* Rowid argument passed to stat_push() */ #endif |
︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 | return; } if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ /* Do not gather statistics on system tables */ return; } assert( sqlite3BtreeHoldsAllMutexes(db) ); | < | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | return; } if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ /* Do not gather statistics on system tables */ return; } assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( iDb>=0 ); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, db->aDb[iDb].zDbSName ) ){ return; } |
︙ | ︙ | |||
1114 1115 1116 1117 1118 1119 1120 | /* Make sure there are enough memory cells allocated to accommodate ** the regPrev array and a trailing rowid (the rowid slot is required ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); /* Open a read-only cursor on the index being analyzed. */ | | | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | /* Make sure there are enough memory cells allocated to accommodate ** the regPrev array and a trailing rowid (the rowid slot is required ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); /* Open a read-only cursor on the index being analyzed. */ assert( db->aDb[iDb].pSchema==pIdx->pSchema ); sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); /* Invoke the stat_init() function. The arguments are: ** ** (1) the number of columns in the index including the rowid |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | sqlite3 *db = pParse->db; Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; int iTab; | < | | < < | > > | 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 | sqlite3 *db = pParse->db; Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; int iTab; sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab; pParse->nTab += 3; openStatTable(pParse, iDb, iStatCur, 0, 0); iMem = pParse->nMem+1; iTab = pParse->nTab; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, iDb, pTab, 0, iStatCur, iMem, iTab); } loadAnalysis(pParse, iDb); } /* ** Generate code that will do an analysis of a single table in ** a database. If pOnlyIdx is not NULL then it is a single index ** in pTab that should be analyzed. */ static void analyzeTable(Parse *pParse, int iDb, Table *pTab, Index *pOnlyIdx){ int iStatCur; assert( pTab!=0 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab; pParse->nTab += 3; if( pOnlyIdx ){ openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx"); }else{ openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl"); } analyzeOneTable(pParse, iDb, pTab, pOnlyIdx, iStatCur, pParse->nMem+1, pParse->nTab ); loadAnalysis(pParse, iDb); } /* ** Generate code for the ANALYZE command. The parser calls this routine ** when it recognizes an ANALYZE command. ** |
︙ | ︙ | |||
1421 1422 1423 1424 1425 1426 1427 | /* Form 3: Analyze the table or index named as an argument */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ | | | | 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | /* Form 3: Analyze the table or index named as an argument */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ analyzeTable(pParse, iDb, pIdx->pTable, pIdx); }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ analyzeTable(pParse, iDb, pTab, 0); } sqlite3DbFree(db, z); } } } if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3VdbeAddOp0(v, OP_Expire); |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
96 97 98 99 100 101 102 | ** reopen it as a MemDB */ pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; pNew = &db->aDb[db->init.iDb]; if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); pNew->pBt = 0; pNew->pSchema = 0; | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ** reopen it as a MemDB */ pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; pNew = &db->aDb[db->init.iDb]; if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); pNew->pBt = 0; pNew->pSchema = 0; rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); }else{ /* This is a real ATTACH ** ** Check for the following errors: ** ** * Too many attached databases, ** * Transaction currently open |
︙ | ︙ |
Changes to src/auth.c.
︙ | ︙ | |||
149 150 151 152 153 154 155 | int iSrc; /* Index in pTabList->a[] of table being read */ int iDb; /* The index of the database the expression refers to */ int iCol; /* Index of column in table */ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->xAuth==0 ) return; | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | int iSrc; /* Index in pTabList->a[] of table being read */ int iDb; /* The index of the database the expression refers to */ int iCol; /* Index of column in table */ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema, 0); /* TODO! */ if( iDb<0 ){ /* An attempt to read a column out of a subquery or other ** temporary table. */ return; } if( pExpr->op==TK_TRIGGER ){ |
︙ | ︙ |
Changes to src/btmutex.c.
︙ | ︙ | |||
248 249 250 251 252 253 254 | ** ** If pSchema is not NULL, then iDb is computed from pSchema and ** db using sqlite3SchemaToIndex(). */ int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ Btree *p; assert( db!=0 ); | > | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | ** ** If pSchema is not NULL, then iDb is computed from pSchema and ** db using sqlite3SchemaToIndex(). */ int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ Btree *p; assert( db!=0 ); if( pSchema && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ) return 1; if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); if( !sqlite3_mutex_held(db->mutex) ) return 0; if( iDb==1 ) return 1; p = db->aDb[iDb].pBt; assert( p!=0 ); return p->sharable==0 || p->locked==1; } |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
187 188 189 190 191 192 193 | ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); VdbeComment((v, "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); } #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; i<pParse->nVtabLock; i++){ | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); VdbeComment((v, "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); } #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; i<pParse->nVtabLock; i++){ char *vtab = (char *)pParse->apVtabLock[i]; sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); } pParse->nVtabLock = 0; #endif /* Once all the cookies have been verified and transactions opened, ** obtain the required table-locks. This is a no-op unless the |
︙ | ︙ | |||
262 263 264 265 266 267 268 | if( zSql==0 ){ return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); sqlite3RunParser(pParse, zSql, &zErrMsg); | | > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | if( zSql==0 ){ return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); sqlite3RunParser(pParse, zSql, &zErrMsg); if( zErrMsg ){ sqlite3ErrorMsg(pParse, "%z", zErrMsg); } sqlite3DbFree(db, zSql); memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; } #if SQLITE_USER_AUTHENTICATION /* |
︙ | ︙ | |||
391 392 393 394 395 396 397 | */ Table *sqlite3LocateTableItem( Parse *pParse, u32 flags, struct SrcList_item *p ){ const char *zDb; | > > > | > > | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | */ Table *sqlite3LocateTableItem( Parse *pParse, u32 flags, struct SrcList_item *p ){ const char *zDb; if( pParse->iFixDb && pParse->iFixDb!=2 ){ zDb = pParse->db->aDb[pParse->iFixDb-1].zDbSName; assert( p->zDatabase==0 || sqlite3StrICmp(p->zDatabase, zDb)==0 ); if( p->zDatabase==0 ){ p->zDatabase = sqlite3DbStrDup(pParse->db, zDb); } }else if( p->pSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema, 0); zDb = pParse->db->aDb[iDb].zDbSName; }else{ zDb = p->zDatabase; } return sqlite3LocateTable(pParse, flags, p->zName, zDb); } |
︙ | ︙ | |||
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 | assert( pPk->nColumn==j ); assert( pTab->nCol==j ); }else{ pPk->nColumn = pTab->nCol; } recomputeColumnsNotIndexed(pPk); } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure that other action routines have been building ** is added to the internal hash tables, assuming no errors have | > > > > > > > > > > > > > > > > > > > > > > > > > > | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 | assert( pPk->nColumn==j ); assert( pTab->nCol==j ); }else{ pPk->nColumn = pTab->nCol; } recomputeColumnsNotIndexed(pPk); } /* ** Return true if zName is a shadow table name in the current database ** connection. ** ** zName is temporarily modified while this routine is running, but is ** restored to its original value prior to this routine returning. */ static int isShadowTableName(sqlite3 *db, char *zName){ char *zTail; /* Pointer to the last "_" in zName */ Table *pTab; /* Table that zName is a shadow of */ Module *pMod; /* Module for the virtual table */ zTail = strrchr(zName, '_'); if( zTail==0 ) return 0; *zTail = 0; pTab = sqlite3FindTable(db, zName, 0); *zTail = '_'; if( pTab==0 ) return 0; if( !IsVirtual(pTab) ) return 0; pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); if( pMod==0 ) return 0; if( pMod->pModule->iVersion<3 ) return 0; if( pMod->pModule->xShadowName==0 ) return 0; return pMod->pModule->xShadowName(zTail+1); } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure that other action routines have been building ** is added to the internal hash tables, assuming no errors have |
︙ | ︙ | |||
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 | if( pEnd==0 && pSelect==0 ){ return; } assert( !db->mallocFailed ); p = pParse->pNewTable; if( p==0 ) return; /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) ** | > > > > | 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 | if( pEnd==0 && pSelect==0 ){ return; } assert( !db->mallocFailed ); p = pParse->pNewTable; if( p==0 ) return; if( pSelect==0 && isShadowTableName(db, p->zName) ){ p->tabFlags |= TF_Shadow; } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) ** |
︙ | ︙ | |||
1963 1964 1965 1966 1967 1968 1969 | sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); }else{ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; convertToWithoutRowidTable(pParse, p); } } | | | 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 | sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); }else{ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; convertToWithoutRowidTable(pParse, p); } } iDb = sqlite3SchemaToIndex(db, p->pSchema, 0); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. */ if( p->pCheck ){ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); } |
︙ | ︙ | |||
2183 2184 2185 2186 2187 2188 2189 | sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; sqlite3TwoPartName(pParse, pName1, pName2, &pName); | | | 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 | sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema, 0); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. |
︙ | ︙ | |||
2236 2237 2238 2239 2240 2241 2242 | #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ | | | | 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 | #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ int sqlite3ViewGetColumnNames(Parse *pParse, int iDb, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ #ifndef SQLITE_OMIT_VIRTUALTABLE int rc; #endif #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; /* Saved xAuth pointer */ #endif assert( pTable ); #ifndef SQLITE_OMIT_VIRTUALTABLE db->nSchemaLock++; rc = sqlite3VtabCallConnect(pParse, iDb, pTable); db->nSchemaLock--; if( rc ){ return 1; } if( IsVirtual(pTable) ) return 0; #endif |
︙ | ︙ | |||
2500 2501 2502 2503 2504 2505 2506 | if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ | | | 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 | if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0); assert( iDb>=0 && iDb<pParse->db->nDb ); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } } |
︙ | ︙ | |||
2627 2628 2629 2630 2631 2632 2633 | pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; if( pTab==0 ){ if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); goto exit_drop_table; } | | | | | 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 | pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; if( pTab==0 ){ if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); goto exit_drop_table; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); sqlite3SchemaWritable(pParse, iDb); /* If pTab is a virtual table, call ViewGetColumnNames() to ensure ** it is initialized. */ if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ goto exit_drop_table; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code; const char *zTab = SCHEMA_TABLE(iDb); const char *zDb = db->aDb[iDb].zDbSName; const char *zArg2 = 0; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; } if( isView ){ if( !OMIT_TEMPDB && iDb==1 ){ code = SQLITE_DROP_TEMP_VIEW; }else{ code = SQLITE_DROP_VIEW; } #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( IsVirtual(pTab) ){ code = SQLITE_DROP_VTABLE; zArg2 = sqlite3GetVTable(db, -1, pTab)->pMod->zName; #endif }else{ if( !OMIT_TEMPDB && iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; }else{ code = SQLITE_DROP_TABLE; } |
︙ | ︙ | |||
2876 2877 2878 2879 2880 2881 2882 | ** ** if memRootPage is not negative, it means that the index is newly ** created. The register specified by memRootPage contains the ** root page number of the index. If memRootPage is negative, then ** the index already exists and must be cleared before being refilled and ** the root page number of the index is taken from pIndex->tnum. */ | | > > > > > < | 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 | ** ** if memRootPage is not negative, it means that the index is newly ** created. The register specified by memRootPage contains the ** root page number of the index. If memRootPage is negative, then ** the index already exists and must be cleared before being refilled and ** the root page number of the index is taken from pIndex->tnum. */ static void sqlite3RefillIndex( Parse *pParse, int iDb, Index *pIndex, int memRootPage ){ Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab++; /* Btree cursor used for pTab */ int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ int iSorter; /* Cursor opened by OpenSorter (if in use) */ int addr1; /* Address of top of loop */ int addr2; /* Address to jump to for next iteration */ int tnum; /* Root page of index */ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ KeyInfo *pKey; /* KeyInfo for index */ int regRecord; /* Register holding assembled index record */ sqlite3 *db = pParse->db; /* The database connection */ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, db->aDb[iDb].zDbSName ) ){ return; } #endif |
︙ | ︙ | |||
3023 3024 3025 3026 3027 3028 3029 | u8 idxType /* The index type */ ){ Table *pTab = 0; /* Table to be indexed */ Index *pIndex = 0; /* The index to be created */ char *zName = 0; /* Name of the index */ int nName; /* Number of characters in zName */ int i, j; | < | 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 | u8 idxType /* The index type */ ){ Table *pTab = 0; /* Table to be indexed */ Index *pIndex = 0; /* The index to be created */ char *zName = 0; /* Name of the index */ int nName; /* Number of characters in zName */ int i, j; int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ sqlite3 *db = pParse->db; Db *pDb; /* The specific table containing the indexed database */ int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ int nExtra = 0; /* Space allocated for zExtra[] */ |
︙ | ︙ | |||
3072 3073 3074 3075 3076 3077 3078 | pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } #endif | < | < < < < > | | 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 | pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } #endif if( iDb!=1 ) pTblName->a[0].zDatabase = db->aDb[iDb].zDbSName; pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); pTblName->a[0].zDatabase = 0; assert( db->mallocFailed==0 || pTab==0 ); if( pTab==0 ) goto exit_create_index; if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){ sqlite3ErrorMsg(pParse, "cannot create a TEMP index on non-TEMP table \"%s\"", pTab->zName); goto exit_create_index; } if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); }else{ assert( pName==0 ); assert( pStart==0 ); pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 |
︙ | ︙ | |||
3516 3517 3518 3519 3520 3521 3522 | ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ | | | | 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 | ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ sqlite3RefillIndex(pParse, iDb, pIndex, iMem); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(pParse, iDb, sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); } sqlite3VdbeJumpHere(v, pIndex->tnum); } } /* When adding an index to the list of indices for a table, make ** sure all indices labeled OE_Replace come after all those labeled ** OE_Ignore. This is necessary for the correct constraint check ** processing (in sqlite3GenerateConstraintChecks()) as part of ** UPDATE and INSERT statements. */ if( db->init.busy || pTblName==0 ){ if( onError!=OE_Replace || pTab->pIndex==0 || pTab->pIndex->onError==OE_Replace){ pIndex->pNext = pTab->pIndex; pTab->pIndex = pIndex; }else{ |
︙ | ︙ | |||
3642 3643 3644 3645 3646 3647 3648 | goto exit_drop_index; } if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } | | | 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 | goto exit_drop_index; } if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } iDb = sqlite3SchemaToIndex(db, pIndex->pSchema, 0); sqlite3SchemaWritable(pParse, iDb); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); |
︙ | ︙ | |||
4376 4377 4378 4379 4380 4381 4382 | #endif /* ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX | | > > > > > < | | 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 | #endif /* ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX static void reindexTable( Parse *pParse, int iDb, Table *pTab, char const *zColl ){ Index *pIndex; /* An index associated with pTab */ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ if( zColl==0 || collationMatch(zColl, pIndex) ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, iDb, pIndex, -1); } } } #endif /* ** Recompute all indices of all tables in all databases where the |
︙ | ︙ | |||
4407 4408 4409 4410 4411 4412 4413 | Table *pTab; /* A table in the database */ assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); | | | 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 | Table *pTab; /* A table in the database */ assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); reindexTable(pParse, iDb, pTab, zColl); } } } #endif /* ** Generate code for the REINDEX command. |
︙ | ︙ | |||
4466 4467 4468 4469 4470 4471 4472 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ | | | | 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, iDb, pTab, 0); sqlite3DbFree(db, z); return; } pIndex = sqlite3FindIndex(db, z, zDb); sqlite3DbFree(db, z); if( pIndex ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, iDb, pIndex, -1); return; } sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif /* |
︙ | ︙ |
Changes to src/callback.c.
︙ | ︙ | |||
551 552 553 554 555 556 557 | ** schema in the list, then the new schema is added to it. */ void sqlite3SchemaReuse(sqlite3 *db, int iDb){ Schema *pSchema = db->aDb[iDb].pSchema; Schema *p; assert( pSchema && iDb!=1 ); | | | | | | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 | ** schema in the list, then the new schema is added to it. */ void sqlite3SchemaReuse(sqlite3 *db, int iDb){ Schema *pSchema = db->aDb[iDb].pSchema; Schema *p; assert( pSchema && iDb!=1 ); sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) ); for(p=sharedSchemaList; p; p=p->pNext){ if( p->cksum==pSchema->cksum && p->schema_cookie==pSchema->schema_cookie ){ break; } } if( !p ){ /* No matching schema was found. */ pSchema->pNext = sharedSchemaList; sharedSchemaList = pSchema; }else{ /* Found a matching schema. Increase its ref count. */ p->nRef++; } sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) ); /* If a matching schema was found in the shared schema list, free the ** schema object just parsed, and add a pointer to the matching schema ** to the db handle. */ if( p ){ sqlite3SchemaClear(pSchema); sqlite3DbFree(0, pSchema); |
︙ | ︙ |
Changes to src/dbpage.c.
︙ | ︙ | |||
115 116 117 118 119 120 121 | ** unavailable */ for(i=0; i<pIdxInfo->nConstraint; i++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( !p->usable ){ | | < | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ** unavailable */ for(i=0; i<pIdxInfo->nConstraint; i++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( !p->usable ){ /* No solution. */ return SQLITE_CONSTRAINT; } iPlan = 2; pIdxInfo->aConstraintUsage[i].argvIndex = 1; pIdxInfo->aConstraintUsage[i].omit = 1; break; } |
︙ | ︙ | |||
403 404 405 406 407 408 409 410 411 412 413 414 415 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); } #elif defined(SQLITE_ENABLE_DBPAGE_VTAB) int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ | > | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); } #elif defined(SQLITE_ENABLE_DBPAGE_VTAB) int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ |
Changes to src/dbstat.c.
︙ | ︙ | |||
190 191 192 193 194 195 196 | ** operate on a different database schema, so check for it. ** ** idxNum is normally 0, but will be 1 if a schema=? constraint exists. */ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; | < < > | < | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | ** operate on a different database schema, so check for it. ** ** idxNum is normally 0, but will be 1 if a schema=? constraint exists. */ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; /* Look for a valid schema=? constraint. If found, change the idxNum to ** 1 and request the value of that constraint be sent to xFilter. And ** lower the cost estimate to encourage the constrained version to be ** used. */ for(i=0; i<pIdxInfo->nConstraint; i++){ if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT; if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; pIdxInfo->idxNum = 1; pIdxInfo->estimatedCost = 1.0; pIdxInfo->aConstraintUsage[i].argvIndex = 1; pIdxInfo->aConstraintUsage[i].omit = 1; break; } |
︙ | ︙ | |||
393 394 395 396 397 398 399 400 401 402 403 404 405 406 | if( nLocal<0 ) goto statPageIsCorrupt; pCell->nLocal = nLocal; assert( nPayload>=(u32)nLocal ); assert( nLocal<=(nUsable-35) ); if( nPayload>(u32)nLocal ){ int j; int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT; pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); for(j=1; j<nOvfl; j++){ int rc; | > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | if( nLocal<0 ) goto statPageIsCorrupt; pCell->nLocal = nLocal; assert( nPayload>=(u32)nLocal ); assert( nLocal<=(nUsable-35) ); if( nPayload>(u32)nLocal ){ int j; int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); if( iOff+nLocal>nUsable ) goto statPageIsCorrupt; pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT; pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); for(j=1; j<nOvfl; j++){ int rc; |
︙ | ︙ | |||
716 717 718 719 720 721 722 723 724 725 726 727 728 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } #elif defined(SQLITE_ENABLE_DBSTAT_VTAB) int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ | > | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } #elif defined(SQLITE_ENABLE_DBSTAT_VTAB) int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ |
Changes to src/delete.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | pTab->nTabRef++; } if( sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; } return pTab; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < | < < > < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | pTab->nTabRef++; } if( sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; } return pTab; } /* Return true if table pTab is read-only. ** ** A table is read-only if any of the following are true: ** ** 1) It is a virtual table and no implementation of the xUpdate method ** has been provided ** ** 2) It is a system table (i.e. sqlite_master), this call is not ** part of a nested parse and writable_schema pragma has not ** been specified ** ** 3) The table is a shadow table, the database connection is in ** defensive mode, and the current sqlite3_prepare() ** is for a top-level SQL statement. */ static int tabIsReadOnly(Parse *pParse, Table *pTab){ sqlite3 *db; if( IsVirtual(pTab) ){ return sqlite3GetVTable(pParse->db, -1, pTab)->pMod->pModule->xUpdate==0; } if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; db = pParse->db; if( (pTab->tabFlags & TF_Readonly)!=0 ){ return sqlite3WritableSchema(db)==0 && pParse->nested==0; } assert( pTab->tabFlags & TF_Shadow ); return (db->flags & SQLITE_Defensive)!=0 && db->nVdbeExec==0 && db->pVtabCtx==0; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } #ifndef SQLITE_OMIT_VIEW if( !viewOk && pTab->pSelect ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } #endif return 0; } #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) /* ** Evaluate a view and store its result in an ephemeral table. The ** pWhere argument is an optional WHERE clause that restricts the ** set of rows in the view that are to be added to the ephemeral table. */ void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ int iDb, /* Database in which view resides */ Table *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ ExprList *pOrderBy, /* Optional ORDER BY clause */ Expr *pLimit, /* Optional LIMIT clause */ int iCur /* Cursor number for ephemeral table */ ){ SelectDest dest; Select *pSel; SrcList *pFrom; sqlite3 *db = pParse->db; pWhere = sqlite3ExprDup(db, pWhere, 0); pFrom = sqlite3SrcListAppend(db, 0, 0, 0); if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); assert( pFrom->a[0].pOn==0 ); |
︙ | ︙ | |||
298 299 300 301 302 303 304 305 306 307 | pWhere = sqlite3LimitWhere( pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE" ); pOrderBy = 0; pLimit = 0; } #endif /* If pTab is really a view, make sure it has been initialized. */ | > > > | < < < | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | pWhere = sqlite3LimitWhere( pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE" ); pOrderBy = 0; pLimit = 0; } #endif iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase); assert( iDb<db->nDb ); /* If pTab is really a view, make sure it has been initialized. */ if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ goto delete_from_cleanup; } if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto delete_from_cleanup; } rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, db->aDb[iDb].zDbSName); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } assert(!isView || pTrigger); |
︙ | ︙ | |||
346 347 348 349 350 351 352 | sqlite3BeginWriteOperation(pParse, bComplex, iDb); /* If we are trying to delete from a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ | | < < | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | sqlite3BeginWriteOperation(pParse, bComplex, iDb); /* If we are trying to delete from a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ sqlite3MaterializeView(pParse, iDb, pTab, pWhere, pOrderBy, pLimit,iTabCur); iDataCur = iIdxCur = iTabCur; pOrderBy = 0; pLimit = 0; } #endif /* Resolve the column names in the WHERE clause. |
︙ | ︙ | |||
512 513 514 515 516 517 518 | */ if( !isView ){ int iAddrOnce = 0; if( eOnePass==ONEPASS_MULTI ){ iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); | | | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | */ if( !isView ){ int iAddrOnce = 0; if( eOnePass==ONEPASS_MULTI ){ iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } testcase( IsVirtual(pTab) ); sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, OPFLAG_FORDELETE, iTabCur, aToOpen, &iDataCur, &iIdxCur); assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); } /* Set up a loop over the rowids/primary-keys that were found in the ** where-clause loop above. |
︙ | ︙ | |||
546 547 548 549 550 551 552 | VdbeCoverage(v); assert( nKey==1 ); } /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ | | | | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | VdbeCoverage(v); assert( nKey==1 ); } /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab); sqlite3VtabMakeWritable(pParse, iDb, pTab); assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); if( eOnePass==ONEPASS_SINGLE ){ sqlite3VdbeAddOp1(v, OP_Close, iTabCur); if( sqlite3IsToplevel(pParse) ){ pParse->isMultiWrite = 0; } } sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, OE_Abort); }else #endif { int count = (pParse->nested==0); /* True to count changes */ sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur, iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); } /* End of the loop over all rowids/primary-keys. */ if( eOnePass!=ONEPASS_OFF ){ sqlite3VdbeResolveLabel(v, addrBypass); sqlite3WhereEnd(pWInfo); |
︙ | ︙ | |||
661 662 663 664 665 666 667 668 669 670 671 672 673 674 | ** then it identifies an index cursor (from within array of cursors ** starting at iIdxCur) that already points to the index entry to be deleted. ** Except, this optimization is disabled if there are BEFORE triggers since ** the trigger body might have moved the cursor. */ void sqlite3GenerateRowDelete( Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the row to be deleted */ Trigger *pTrigger, /* List of triggers to (potentially) fire */ int iDataCur, /* Cursor from which column data is extracted */ int iIdxCur, /* First index cursor */ int iPk, /* First memory cell containing the PRIMARY KEY */ i16 nPk, /* Number of PRIMARY KEY memory cells */ u8 count, /* If non-zero, increment the row change counter */ | > | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | ** then it identifies an index cursor (from within array of cursors ** starting at iIdxCur) that already points to the index entry to be deleted. ** Except, this optimization is disabled if there are BEFORE triggers since ** the trigger body might have moved the cursor. */ void sqlite3GenerateRowDelete( Parse *pParse, /* Parsing context */ int iDb, /* Database containing pTab */ Table *pTab, /* Table containing the row to be deleted */ Trigger *pTrigger, /* List of triggers to (potentially) fire */ int iDataCur, /* Cursor from which column data is extracted */ int iIdxCur, /* First index cursor */ int iPk, /* First memory cell containing the PRIMARY KEY */ i16 nPk, /* Number of PRIMARY KEY memory cells */ u8 count, /* If non-zero, increment the row change counter */ |
︙ | ︙ | |||
703 704 705 706 707 708 709 | u32 mask; /* Mask of OLD.* columns in use */ int iCol; /* Iterator used while populating OLD.* */ int addrStart; /* Start of BEFORE trigger programs */ /* TODO: Could use temporary registers here. Also could attempt to ** avoid copying the contents of the rowid register. */ mask = sqlite3TriggerColmask( | | | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | u32 mask; /* Mask of OLD.* columns in use */ int iCol; /* Iterator used while populating OLD.* */ int addrStart; /* Start of BEFORE trigger programs */ /* TODO: Could use temporary registers here. Also could attempt to ** avoid copying the contents of the rowid register. */ mask = sqlite3TriggerColmask( pParse, iDb, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf ); mask |= sqlite3FkOldmask(pParse, pTab); iOld = pParse->nMem+1; pParse->nMem += (1 + pTab->nCol); /* Populate the OLD.* pseudo-table register array. These values will be ** used by any BEFORE and AFTER triggers that exist. */ sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld); for(iCol=0; iCol<pTab->nCol; iCol++){ testcase( mask!=0xffffffff && iCol==31 ); testcase( mask!=0xffffffff && iCol==32 ); if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1); } } /* Invoke BEFORE DELETE trigger programs. */ addrStart = sqlite3VdbeCurrentAddr(v); sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel ); /* If any BEFORE triggers were coded, then seek the cursor to the ** row to be deleted again. It may be that the BEFORE triggers moved ** the cursor or already deleted the row that the cursor was ** pointing to. |
︙ | ︙ | |||
745 746 747 748 749 750 751 | testcase( iIdxNoSeek>=0 ); iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ | | | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | testcase( iIdxNoSeek>=0 ); iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ sqlite3FkCheck(pParse, iDb, pTab, iOld, 0, 0, 0); } /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). ** ** If variable 'count' is non-zero, then this OP_Delete instruction should |
︙ | ︙ | |||
778 779 780 781 782 783 784 | if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just deleted. */ | | | | 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just deleted. */ sqlite3FkActions(pParse, iDb, pTab, 0, iOld, 0, 0); /* Invoke AFTER DELETE trigger programs. */ sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel ); /* Jump here if the row had already been deleted before any BEFORE ** trigger programs were invoked. Or if a trigger program throws a ** RAISE(IGNORE) exception. */ sqlite3VdbeResolveLabel(v, iLabel); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2365 2366 2367 2368 2369 2370 2371 | assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; /* Code an OP_Transaction and OP_TableLock for <table>. */ | | | 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; /* Code an OP_Transaction and OP_TableLock for <table>. */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema, p->pSrc->a[0].zDatabase); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); assert(v); /* sqlite3GetVdbe() has always been previously called */ if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ /* The "x IN (SELECT rowid FROM table)" case */ int iAddr = sqlite3VdbeAddOp0(v, OP_Once); |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | ** For an UPDATE operation, this function is called twice. Once before ** the original record is deleted from the table using the calling convention ** described for DELETE. Then again after the original record is deleted ** but before the new record is inserted using the INSERT convention. */ void sqlite3FkCheck( Parse *pParse, /* Parse context */ Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ int regNew, /* New row data is stored here */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ sqlite3 *db = pParse->db; /* Database handle */ FKey *pFKey; /* Used to iterate through FKs */ | > < < < | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | ** For an UPDATE operation, this function is called twice. Once before ** the original record is deleted from the table using the calling convention ** described for DELETE. Then again after the original record is deleted ** but before the new record is inserted using the INSERT convention. */ void sqlite3FkCheck( Parse *pParse, /* Parse context */ int iDb, /* Database containing pTab */ Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ int regNew, /* New row data is stored here */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ sqlite3 *db = pParse->db; /* Database handle */ FKey *pFKey; /* Used to iterate through FKs */ const char *zDb; /* Name of database containing pTab */ int isIgnoreErrors = pParse->disableTriggers; /* Exactly one of regOld and regNew should be non-zero. */ assert( (regOld==0)!=(regNew==0) ); /* If foreign-keys are disabled, this function is a no-op. */ if( (db->flags&SQLITE_ForeignKeys)==0 ) return; zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ Table *pTo; /* Parent table of foreign key pFKey */ Index *pIdx = 0; /* Index on key columns in pTo */ |
︙ | ︙ | |||
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 | /* ** This function is called when deleting or updating a row to implement ** any required CASCADE, SET NULL or SET DEFAULT actions. */ void sqlite3FkActions( Parse *pParse, /* Parse context */ Table *pTab, /* Table being updated or deleted from */ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ int regOld, /* Address of array containing old row */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ /* If foreign-key support is enabled, iterate through all FKs that ** refer to table pTab. If there is an action associated with the FK ** for this operation (either update or delete), invoke the associated ** trigger sub-program. */ if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *pFKey; /* Iterator variable */ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges); if( pAct ){ | > | | 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 | /* ** This function is called when deleting or updating a row to implement ** any required CASCADE, SET NULL or SET DEFAULT actions. */ void sqlite3FkActions( Parse *pParse, /* Parse context */ int iDb, /* Database in which pTab resides */ Table *pTab, /* Table being updated or deleted from */ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ int regOld, /* Address of array containing old row */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ /* If foreign-key support is enabled, iterate through all FKs that ** refer to table pTab. If there is an action associated with the FK ** for this operation (either update or delete), invoke the associated ** trigger sub-program. */ if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *pFKey; /* Iterator variable */ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges); if( pAct ){ sqlite3CodeRowTriggerDirect(pParse, iDb, pAct,pTab,regOld,OE_Abort,0); } } } } } #endif /* ifndef SQLITE_OMIT_TRIGGER */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
164 165 166 167 168 169 170 | ** run without using a temporary table for the results of the SELECT. */ static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); #ifndef SQLITE_OMIT_VIRTUALTABLE | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | ** run without using a temporary table for the results of the SELECT. */ static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); #ifndef SQLITE_OMIT_VIRTUALTABLE VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, iDb, pTab) : 0; #endif for(i=1; i<iEnd; i++){ VdbeOp *pOp = sqlite3VdbeGetOp(v, i); assert( pOp!=0 ); if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){ Index *pIndex; |
︙ | ︙ | |||
564 565 566 567 568 569 570 | /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ){ goto insert_cleanup; } | | | 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ){ goto insert_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase); assert( iDb<db->nDb ); if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, db->aDb[iDb].zDbSName) ){ goto insert_cleanup; } withoutRowid = !HasRowid(pTab); |
︙ | ︙ | |||
592 593 594 595 596 597 598 | # define isView 0 #endif assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); /* If pTab is really a view, make sure it has been initialized. ** ViewGetColumnNames() is a no-op if pTab is not a view. */ | | | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | # define isView 0 #endif assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); /* If pTab is really a view, make sure it has been initialized. ** ViewGetColumnNames() is a no-op if pTab is not a view. */ if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ goto insert_cleanup; } /* Cannot insert into a read-only table. */ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto insert_cleanup; |
︙ | ︙ | |||
807 808 809 810 811 812 813 | regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; | | | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){ assert( pIdx ); |
︙ | ︙ | |||
923 924 925 926 927 928 929 | ** table column affinities. */ if( !isView ){ sqlite3TableAffinity(v, pTab, regCols+1); } /* Fire BEFORE or INSTEAD OF triggers */ | | | 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 | ** table column affinities. */ if( !isView ){ sqlite3TableAffinity(v, pTab, regCols+1); } /* Fire BEFORE or INSTEAD OF triggers */ sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, pTab, regCols-pTab->nCol-1, onError, endOfLoop); sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); } /* Compute the content of the next row to insert into a range of ** registers beginning at regIns. |
︙ | ︙ | |||
1023 1024 1025 1026 1027 1028 1029 | } /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ | | | | | > | | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | } /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab); sqlite3VtabMakeWritable(pParse, iDb, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); }else #endif { int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert ); sqlite3FkCheck(pParse, iDb, pTab, 0, regIns, 0, 0); /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE ** constraints or (b) there are no triggers and this table is not a ** parent table in a foreign key constraint. It is safe to set the ** flag in the second case as if any REPLACE constraint is hit, an ** OP_Delete or OP_IdxDelete instruction will be executed on each ** cursor that is disturbed. And these instructions both clear the |
︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 | */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ | | | 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 | */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, pTab, regData-2-pTab->nCol, onError, endOfLoop); } /* The bottom of the main insertion loop, if the data source ** is a SELECT statement. */ sqlite3VdbeResolveLabel(v, endOfLoop); |
︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | ** Which action to take is determined by the overrideError parameter. ** Or if overrideError==OE_Default, then the pParse->onError parameter ** is used. Or if pParse->onError==OE_Default then the onError value ** for the constraint is used. */ void sqlite3GenerateConstraintChecks( Parse *pParse, /* The parser context */ Table *pTab, /* The table being inserted or updated */ int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */ int iDataCur, /* Canonical data cursor (main table or PK index) */ int iIdxCur, /* First index cursor */ int regNewData, /* First register in a range holding values to insert */ int regOldData, /* Previous content. 0 for INSERTs */ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ | > | 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 | ** Which action to take is determined by the overrideError parameter. ** Or if overrideError==OE_Default, then the pParse->onError parameter ** is used. Or if pParse->onError==OE_Default then the onError value ** for the constraint is used. */ void sqlite3GenerateConstraintChecks( Parse *pParse, /* The parser context */ int iDb, /* Databse that contains pTab */ Table *pTab, /* The table being inserted or updated */ int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */ int iDataCur, /* Canonical data cursor (main table or PK index) */ int iIdxCur, /* First index cursor */ int regNewData, /* First register in a range holding values to insert */ int regOldData, /* Previous content. 0 for INSERTs */ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ |
︙ | ︙ | |||
1553 1554 1555 1556 1557 1558 1559 | */ Trigger *pTrigger = 0; if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); | | | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 | */ Trigger *pTrigger = 0; if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1); }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK assert( HasRowid(pTab) ); /* This OP_Delete opcode fires the pre-update-hook only. It does ** not modify the b-tree. It is more efficient to let the coming ** OP_Insert replace the existing entry than it is to delete the ** existing entry and then insert a new one. */ |
︙ | ︙ | |||
1802 1803 1804 1805 1806 1807 1808 | assert( onError==OE_Replace ); if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); } | | | 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 | assert( onError==OE_Replace ); if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); } sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); seenReplace = 1; break; } } if( pUpIdx==pIdx ){ |
︙ | ︙ | |||
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | ** pTab->pIndex list. ** ** If pTab is a virtual table, then this routine is a no-op and the ** *piDataCur and *piIdxCur values are left uninitialized. */ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ int iBase, /* Use this for the table cursor, if there is one */ u8 *aToOpen, /* If not NULL: boolean for each table and index */ int *piDataCur, /* Write the database source cursor number here */ int *piIdxCur /* Write the first index cursor number here */ ){ int i; | > < < | 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 | ** pTab->pIndex list. ** ** If pTab is a virtual table, then this routine is a no-op and the ** *piDataCur and *piIdxCur values are left uninitialized. */ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ int iDb, /* Database to open pTab in */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ int iBase, /* Use this for the table cursor, if there is one */ u8 *aToOpen, /* If not NULL: boolean for each table and index */ int *piDataCur, /* Write the database source cursor number here */ int *piIdxCur /* Write the first index cursor number here */ ){ int i; int iDataCur; Index *pIdx; Vdbe *v; assert( op==OP_OpenRead || op==OP_OpenWrite ); assert( op==OP_OpenWrite || p5==0 ); if( IsVirtual(pTab) ){ /* This routine is a no-op for virtual tables. Leave the output ** variables *piDataCur and *piIdxCur uninitialized so that valgrind ** can detect if they are used by mistake in the caller. */ return 0; } v = sqlite3GetVdbe(pParse); assert( v!=0 ); if( iBase<0 ) iBase = pParse->nTab; iDataCur = iBase++; if( piDataCur ) *piDataCur = iDataCur; if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); |
︙ | ︙ | |||
2280 2281 2282 2283 2284 2285 2286 | /* If we get this far, it means that the xfer optimization is at ** least a possibility, though it might only work if the destination ** table (tab1) is initially empty. */ #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif | | | 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 | /* If we get this far, it means that the xfer optimization is at ** least a possibility, though it might only work if the destination ** table (tab1) is initially empty. */ #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema, pItem->zDatabase); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; regAutoinc = autoIncBegin(pParse, iDbDest, pDest); regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 | | SQLITE_CellSizeCk #endif #if defined(SQLITE_ENABLE_FTS3_TOKENIZER) | SQLITE_Fts3Tokenizer #endif #if defined(SQLITE_ENABLE_QPSG) | SQLITE_EnableQPSG #endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3HashInit(&db->aModule); #endif | > > > | 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 | | SQLITE_CellSizeCk #endif #if defined(SQLITE_ENABLE_FTS3_TOKENIZER) | SQLITE_Fts3Tokenizer #endif #if defined(SQLITE_ENABLE_QPSG) | SQLITE_EnableQPSG #endif #if defined(SQLITE_DEFAULT_DEFENSIVE) | SQLITE_Defensive #endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3HashInit(&db->aModule); #endif |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 | */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 7; | > | | | 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ int i, k; int nHidden = 0; int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema, zDb); Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 7; sqlite3CodeVerifySchema(pParse, iTabDb); sqlite3ViewGetColumnNames(pParse, iTabDb, pTab); for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ int isHidden = IsHiddenColumn(pCol); if( isHidden && pPragma->iArg==0 ){ nHidden++; continue; } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ |
︙ | ︙ | |||
1548 1549 1550 1551 1552 1553 1554 | Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); | | | 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 | Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); sqlite3OpenTableAndIndices(pParse, i, pTab, OP_OpenRead, 0, 1, 0, &iDataCur, &iIdxCur); /* reg[7] counts the number of entries in the table. ** reg[8+i] counts the number of entries in the i-th index */ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ |
︙ | ︙ | |||
2473 2474 2475 2476 2477 2478 2479 | 0, /* xSync - sync transaction */ 0, /* xCommit - commit transaction */ 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ | | > | 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 | 0, /* xSync - sync transaction */ 0, /* xCommit - commit transaction */ 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 /* xShadowName */ }; /* ** Check to see if zTabName is really the name of a pragma. If it is, ** then register an eponymous virtual table for that pragma and return ** a pointer to the Module object for the new virtual table. */ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
504 505 506 507 508 509 510 | /* ** Convert a schema pointer into the iDb index that indicates ** which database file in db->aDb[] the schema refers to. ** ** If the same database is attached more than once, the first ** attached database is returned. */ | | | > > > > > > > > > > < > > | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | /* ** Convert a schema pointer into the iDb index that indicates ** which database file in db->aDb[] the schema refers to. ** ** If the same database is attached more than once, the first ** attached database is returned. */ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema, const char *zDb){ int i; assert( sqlite3_mutex_held(db->mutex) ); if( zDb ){ int i; for(i=0; i<db->nDb; i++){ if( i==1 ) continue; if( sqlite3StrICmp(zDb, db->aDb[i].zDbSName)==0 ) return i; } assert( sqlite3StrICmp(zDb, "temp")==0 ); } /* If pSchema is NULL, then return -1000000. This happens when code in ** expr.c is trying to resolve a reference to a transient table (i.e. one ** created by a sub-select). In this case the return value of this ** function should never be used. ** ** We return -1000000 instead of the more usual -1 simply because using ** -1000000 as the incorrect index into db->aDb[] is much ** more likely to cause a segfault than -1 (of course there are assert() ** statements too, but it never hurts to play the odds). */ if( pSchema ){ for(i=0; 1; i++){ assert( i<db->nDb ); if( db->aDb[i].pSchema==pSchema ){ break; } } assert( i>=0 && i<db->nDb ); }else{ i = -1000000; } return i; } /* ** Free all memory allocations in the pParse object */ |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 | struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; | > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ int iDb = -1; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; |
︙ | ︙ | |||
219 220 221 222 223 224 225 226 227 228 229 230 231 232 | ** database name. */ zDb = 0; }else{ for(i=0; i<db->nDb; i++){ assert( db->aDb[i].zDbSName ); if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } } } } /* Start at the inner-most context and move outward until a match is found */ | > | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | ** database name. */ zDb = 0; }else{ for(i=0; i<db->nDb; i++){ assert( db->aDb[i].zDbSName ); if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; iDb = i; break; } } } } /* Start at the inner-most context and move outward until a match is found */ |
︙ | ︙ | |||
250 251 252 253 254 255 256 | pMatch = pItem; pExpr->iColumn = j; hit = 1; } } if( hit || zTab==0 ) continue; } | | > | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | pMatch = pItem; pExpr->iColumn = j; hit = 1; } } if( hit || zTab==0 ) continue; } if( zDb && (pTab->pSchema || pSchema) ){ int ii = sqlite3SchemaToIndex(db, pTab->pSchema, pItem->zDatabase); if( ii!=iDb ) continue; } if( zTab ){ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; assert( zTabName!=0 ); if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1441 1442 1443 1444 1445 1446 1447 | sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } #ifdef SQLITE_ENABLE_SORTER_REFERENCES /* Open any cursors needed for sorter-reference expressions */ for(i=0; i<pSort->nDefer; i++){ Table *pTab = pSort->aDefer[i].pTab; | | | 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } #ifdef SQLITE_ENABLE_SORTER_REFERENCES /* Open any cursors needed for sorter-reference expressions */ for(i=0; i<pSort->nDefer; i++){ Table *pTab = pSort->aDefer[i].pTab; int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0); /* TODO */ sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); } #endif iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ |
︙ | ︙ | |||
1709 1710 1711 1712 1713 1714 1715 | zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zName; zType = sqlite3ColumnType(&pTab->aCol[iCol],0); } zOrigTab = pTab->zName; if( pNC->pParse && pTab->pSchema ){ | > | | 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 | zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zName; zType = sqlite3ColumnType(&pTab->aCol[iCol],0); } zOrigTab = pTab->zName; if( pNC->pParse && pTab->pSchema ){ /* TODO: Fix the following for REUSE schemas */ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema, 0); zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; } #else assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; }else{ |
︙ | ︙ | |||
4882 4883 4884 4885 4886 4887 4888 4889 | } pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( IsVirtual(pTab) || pTab->pSelect ){ i16 nCol; | > > > | > > > > | 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 | } pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( IsVirtual(pTab) || pTab->pSelect ){ int iSave = pParse->iFixDb; i16 nCol; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pFrom->zDatabase); pParse->iFixDb = 1 + iDb; if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ pParse->iFixDb = iSave; return WRC_Abort; } assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); nCol = pTab->nCol; pTab->nCol = -1; sqlite3WalkSelect(pWalker, pFrom->pSelect); pParse->iFixDb = iSave; pTab->nCol = nCol; } #endif } /* Locate the index named by the INDEXED BY clause, if any. */ if( sqlite3IndexedByLookup(pParse, pFrom) ){ |
︙ | ︙ | |||
4980 4981 4982 4983 4984 4985 4986 | } if( db->mallocFailed ) break; if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } | | | 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 | } if( db->mallocFailed ) break; if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pFrom->zDatabase); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; j<pTab->nCol; j++){ char *zName = pTab->aCol[j].zName; char *zColname; /* The computed column name */ char *zToFree; /* Malloced string that needs to be freed */ Token sColname; /* Computed column name as a token */ |
︙ | ︙ | |||
6471 6472 6473 6474 6475 6476 6477 | ** ** This statement is so common that it is optimized specially. The ** OP_Count instruction is executed either on the intkey table that ** contains the data for table <tbl> or on one of its indexes. It ** is better to execute the op on an index, as indexes are almost ** always spread across less pages than their corresponding tables. */ | | > > | 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 | ** ** This statement is so common that it is optimized specially. The ** OP_Count instruction is executed either on the intkey table that ** contains the data for table <tbl> or on one of its indexes. It ** is better to execute the op on an index, as indexes are almost ** always spread across less pages than their corresponding tables. */ const int iDb = sqlite3SchemaToIndex( pParse->db, pTab->pSchema, pTabList->a[0].zDatabase ); const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ Index *pIdx; /* Iterator variable */ KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ Index *pBest = 0; /* Best index found so far */ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 | */ #define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ #define SHELL_OPEN_NORMAL 1 /* Normal database file */ #define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ #define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ #define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ #define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ | | | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | */ #define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ #define SHELL_OPEN_NORMAL 1 /* Normal database file */ #define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ #define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ #define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ #define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ #define SHELL_OPEN_REUSESCHEMA 6 /* Open for schema reuse */ /* ** These are the allowed shellFlgs values */ #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */ #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ |
︙ | ︙ | |||
8070 8071 8072 8073 8074 8075 8076 | /* ** We need a default sqlite3_complete() implementation to use in case ** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes ** any arbitrary text is a complete SQL statement. This is not very ** user-friendly, but it does seem to work. */ #ifdef SQLITE_OMIT_COMPLETE | | | 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 | /* ** We need a default sqlite3_complete() implementation to use in case ** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes ** any arbitrary text is a complete SQL statement. This is not very ** user-friendly, but it does seem to work. */ #ifdef SQLITE_OMIT_COMPLETE #define sqlite3_complete(x) 1 #endif /* ** Return true if zSql is a complete SQL statement. Return false if it ** ends in the middle of a string literal or C-style comment. */ static int line_is_complete(char *zSql, int nSql){ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 | ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_db_config()] to make sure that ** the call worked. ^The [sqlite3_db_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** ** <dl> ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd> ^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. ** ^The first argument (the third parameter to [sqlite3_db_config()] is a ** pointer to a memory buffer to use for lookaside memory. ** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb ** may be NULL in which case SQLite will allocate the | > | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 | ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_db_config()] to make sure that ** the call worked. ^The [sqlite3_db_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** ** <dl> ** [[SQLITE_DBCONFIG_LOOKASIDE]] ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd> ^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. ** ^The first argument (the third parameter to [sqlite3_db_config()] is a ** pointer to a memory buffer to use for lookaside memory. ** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb ** may be NULL in which case SQLite will allocate the |
︙ | ︙ | |||
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 | ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by ** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dd> ^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. ** The first argument is an integer which is 0 to disable FK enforcement, ** positive to enable FK enforcement or negative to leave FK enforcement ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether FK enforcement is off or on ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back. </dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or ** positive to enable fts3_tokenizer() or negative to leave the setting ** unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. ** There should be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to state of either the ** C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** | > > > > | > | | | | | | | < < | | | > < < < < < < < < < < | 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 | ** connection is not currently using lookaside memory, or in other words ** when the "current value" returned by ** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. ** Any attempt to change the lookaside memory configuration when lookaside ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd> ** ** [[SQLITE_DBCONFIG_ENABLE_FKEY]] ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dd> ^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. ** The first argument is an integer which is 0 to disable FK enforcement, ** positive to enable FK enforcement or negative to leave FK enforcement ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether FK enforcement is off or on ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back. </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or ** positive to enable fts3_tokenizer() or negative to leave the setting ** unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. ** There should be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to state of either the ** C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** ** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** <dd> ^This option is used to change the name of the "main" database ** schema. ^The sole argument is a pointer to a constant UTF8 string ** which will become the new schema name in place of "main". ^SQLite ** does not make a copy of the new main schema name string, so the application ** must ensure that the argument passed into this DBCONFIG option is unchanged ** until after the database connection closes. ** </dd> ** ** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dd> Usually, when a database in wal mode is closed or detached from a ** database handle, SQLite checks if this will mean that there are now no ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to ** override this behaviour. The first parameter passed to this operation ** is an integer - positive to disable checkpoints-on-close, or zero (the ** default) to enable them, and negative to leave the setting unchanged. ** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** a single SQL query statement will always use the same algorithm regardless ** of values of [bound parameters].)^ The QPSG disables some query optimizations ** that look at the values of bound parameters, which can make some queries ** slower. But the QPSG has the advantage of more predictable behavior. With ** the QPSG active, SQLite will always use the same query plan in the field as ** was used during testing in the lab. ** The first argument to this setting is an integer which is 0 to disable ** the QPSG, positive to enable QPSG, or negative to leave the setting ** unchanged. The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether the QPSG is disabled or enabled ** following this call. ** </dd> ** ** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this ** behavior. The first parameter passed to this operation is an integer - ** positive to enable output for trigger programs, or zero to disable it, ** or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which is written ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ** it is not disabled, 1 if it is. ** </dd> ** ** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** [VACUUM] in order to reset a database back to an empty database ** with no schema and no content. The following process works even for ** a badly corrupted database file: ** <ol> ** <li> If the database connection is newly opened, make sure it has read the ** database schema by preparing then discarding some query against the ** database, or calling sqlite3_table_column_metadata(), ignoring any ** errors. This step is only necessary if the application desires to keep ** the database in WAL mode after the reset if it was in WAL mode before ** the reset. ** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); ** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); ** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ** </ol> ** Because resetting a database is destructive and irreversible, the ** process requires the use of this obscure API and multiple steps to help ** ensure that it does not happen by accident. ** ** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the ** "defensive" flag for a database connection. When the defensive ** flag is enabled, language features that allow ordinary SQL to ** deliberately corrupt the database file are disabled. The disabled ** features include but are not limited to the following: ** <ul> ** <li> The [PRAGMA writable_schema=ON] statement. ** <li> Writes to the [sqlite_dbpage] virtual table. ** <li> Direct writes to [shadow tables]. ** </ul> ** </dd> ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
︙ | ︙ | |||
6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 | void **ppArg); int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info ** ** The sqlite3_index_info structure and its substructures is used as part | > > > | 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 | void **ppArg); int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ int (*xShadowName)(const char*); }; /* ** CAPI3REF: Virtual Table Indexing Information ** KEYWORDS: sqlite3_index_info ** ** The sqlite3_index_info structure and its substructures is used as part |
︙ | ︙ | |||
8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 | ** CAPI3REF: Virtual Table Configuration Options ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** ** <dl> ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire | > | 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 | ** CAPI3REF: Virtual Table Configuration Options ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** ** <dl> ** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | ** parameters that may or may not be used depending on compilation options. ** For example those parameters only used in assert() statements. In these ** cases the parameters are named as per the usual conventions. */ #define UNUSED_PARAMETER(x) (void)(x) #define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; | > > > > > | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 | ** parameters that may or may not be used depending on compilation options. ** For example those parameters only used in assert() statements. In these ** cases the parameters are named as per the usual conventions. */ #define UNUSED_PARAMETER(x) (void)(x) #define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) /* ** The static mutex with which to protect reusable schemas. */ #define SQLITE_MUTEX_SCHEMA_REUSE SQLITE_MUTEX_STATIC_APP1 /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; |
︙ | ︙ | |||
1932 1933 1934 1935 1936 1937 1938 | ** list without holding the corresponding sqlite3.mutex mutex. ** ** The memory for objects of this type is always allocated by ** sqlite3DbMalloc(), using the connection handle stored in VTable.db as ** the first argument. */ struct VTable { | | > | 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 | ** list without holding the corresponding sqlite3.mutex mutex. ** ** The memory for objects of this type is always allocated by ** sqlite3DbMalloc(), using the connection handle stored in VTable.db as ** the first argument. */ struct VTable { sqlite3 *db; /* Database that owns this virtual table */ Btree *pBt; /* Btree backend associated with this table */ Module *pMod; /* Pointer to module implementation */ sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ int iSavepoint; /* Depth of the SAVEPOINT stack */ VTable *pNext; /* Next in linked list (see above) */ }; |
︙ | ︙ | |||
2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 | #define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ #define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ #define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ #define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ #define TF_StatsUsed 0x0100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE | > | 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 | #define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ #define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ #define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ #define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ #define TF_StatsUsed 0x0100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ #define TF_Shadow 0x0400 /* True for a shadow table */ /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 | ** accessed (or set to 0 for triggers fired as a result of INSERT ** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to ** a mask of new.* columns used by the program. */ struct TriggerPrg { Trigger *pTrigger; /* Trigger this program was coded from */ TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ SubProgram *pProgram; /* Program implementing pTrigger/orconf */ int orconf; /* Default ON CONFLICT policy */ u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ }; /* ** The yDbMask datatype for the bitmask of all attached databases. | > | 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 | ** accessed (or set to 0 for triggers fired as a result of INSERT ** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to ** a mask of new.* columns used by the program. */ struct TriggerPrg { Trigger *pTrigger; /* Trigger this program was coded from */ TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */ int iFixDb; /* Value of Parse.iFixDb when this was coded */ SubProgram *pProgram; /* Program implementing pTrigger/orconf */ int orconf; /* Default ON CONFLICT policy */ u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ }; /* ** The yDbMask datatype for the bitmask of all attached databases. |
︙ | ︙ | |||
3126 3127 3128 3129 3130 3131 3132 | const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Index *pNewIndex; /* An index being constructed by CREATE INDEX */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ | | > | 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 | const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Index *pNewIndex; /* An index being constructed by CREATE INDEX */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ VTable **apVtabLock; /* Pointer to virtual tables needing locking */ #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ With *pWithToFree; /* Free this WITH object at the end of the parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif int iFixDb; }; #define PARSE_MODE_NORMAL 0 #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME_COLUMN 2 #define PARSE_MODE_RENAME_TABLE 3 |
︙ | ︙ | |||
3886 3887 3888 3889 3890 3891 3892 | void sqlite3RowSetInsert(RowSet*, i64); int sqlite3RowSetTest(RowSet*, int iBatch, i64); int sqlite3RowSetNext(RowSet*, i64*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) | | | | 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 | void sqlite3RowSetInsert(RowSet*, i64); int sqlite3RowSetTest(RowSet*, int iBatch, i64); int sqlite3RowSetNext(RowSet*, i64*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) int sqlite3ViewGetColumnNames(Parse*,int,Table*); #else # define sqlite3ViewGetColumnNames(A,B,C) 0 #endif #if SQLITE_MAX_ATTACHED>30 int sqlite3DbMaskAllZero(yDbMask); #endif void sqlite3DropTable(Parse*, SrcList*, int, int); void sqlite3CodeDropTable(Parse*, Table*, int, int); |
︙ | ︙ | |||
4020 4021 4022 4023 4024 4025 4026 | int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); #ifdef SQLITE_ENABLE_NORMALIZE int sqlite3IsRowidN(const char*, int); #endif void sqlite3GenerateRowDelete( | | | | | 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 | int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); #ifdef SQLITE_ENABLE_NORMALIZE int sqlite3IsRowidN(const char*, int); #endif void sqlite3GenerateRowDelete( Parse*,int,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); void sqlite3GenerateConstraintChecks(Parse*,int,Table*,int*,int,int,int,int, u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM void sqlite3SetMakeRecordP5(Vdbe*,Table*); #else # define sqlite3SetMakeRecordP5(A,B) #endif void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); int sqlite3OpenTableAndIndices(Parse*, int, Table*, int, u8, int,u8*,int*,int*); void sqlite3BeginWriteOperation(Parse*, int, int); void sqlite3MultiWrite(Parse*); void sqlite3MayAbort(Parse*); void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8); void sqlite3UniqueConstraint(Parse*, int, Index*); void sqlite3RowidConstraint(Parse*, int, Table*); Expr *sqlite3ExprDup(sqlite3*,Expr*,int); |
︙ | ︙ | |||
4058 4059 4060 4061 4062 4063 4064 | void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*); void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) | | | | | | | | | | 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 | void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*); void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int); #endif #ifndef SQLITE_OMIT_TRIGGER void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, Expr*,int, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*, int); void sqlite3DropTriggerPtr(Parse*, Trigger*); Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); Trigger *sqlite3TriggerList(Parse *, Table *); void sqlite3CodeRowTrigger(Parse*, int, Trigger *, int, ExprList*, int, Table *, int, int, int); void sqlite3CodeRowTriggerDirect(Parse*, int, Trigger*, Table*, int, int,int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, const char*,const char*); TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, Select*,u8,Upsert*, const char*,const char*); TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8, const char*,const char*); TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, const char*,const char*); void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); u32 sqlite3TriggerColmask(Parse*,int,Trigger*,ExprList*,int,int,Table*,int); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) # define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J) # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F,G) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G,H) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); |
︙ | ︙ | |||
4289 4290 4291 4292 4293 4294 4295 | void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3SchemaClear(void *); void sqlite3SchemaUnuse(sqlite3*, int); void sqlite3SchemaReuse(sqlite3*, int); void sqlite3SchemaWritable(Parse*, int); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); | | | 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 | void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3SchemaClear(void *); void sqlite3SchemaUnuse(sqlite3*, int); void sqlite3SchemaReuse(sqlite3*, int); void sqlite3SchemaWritable(Parse*, int); Schema *sqlite3SchemaGet(sqlite3 *, Btree *); int sqlite3SchemaToIndex(sqlite3 *db, Schema *, const char*); KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); #ifdef SQLITE_DEBUG |
︙ | ︙ | |||
4377 4378 4379 4380 4381 4382 4383 | # define sqlite3VtabRollback(X) # define sqlite3VtabCommit(X) # define sqlite3VtabInSync(db) 0 # define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK | | | | | | 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 | # define sqlite3VtabRollback(X) # define sqlite3VtabCommit(X) # define sqlite3VtabInSync(db) 0 # define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK # define sqlite3GetVTable(X,Y,Z) ((VTable*)0) #else void sqlite3VtabClear(sqlite3 *db, Table*); void sqlite3VtabDisconnect(sqlite3 *db, Table *p); int sqlite3VtabSync(sqlite3 *db, Vdbe*); int sqlite3VtabRollback(sqlite3 *db); int sqlite3VtabCommit(sqlite3 *db); void sqlite3VtabLock(VTable *); void sqlite3VtabUnlock(VTable *); void sqlite3VtabUnlockList(sqlite3*); int sqlite3VtabSavepoint(sqlite3 *, int, int); void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); VTable *sqlite3GetVTable(sqlite3*, int, Table*); Module *sqlite3VtabCreateModule( sqlite3*, const char*, const sqlite3_module*, void*, void(*)(void*) ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif int sqlite3VtabEponymousTableInit(Parse*,Module*); void sqlite3VtabEponymousTableClear(sqlite3*,Module*); void sqlite3VtabMakeWritable(Parse*,int,Table*); void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); void sqlite3VtabFinishParse(Parse*, Token*); void sqlite3VtabArgInit(Parse*); void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); int sqlite3VtabCallConnect(Parse*, int, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParserReset(Parse*); |
︙ | ︙ | |||
4456 4457 4458 4459 4460 4461 4462 | ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) | | | | | | 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 | ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3FkCheck(Parse*, int, Table*, int, int, int*, int); void sqlite3FkDropTable(Parse*, SrcList *, Table*); void sqlite3FkActions(Parse*, int, Table*, ExprList*, int, int*, int); int sqlite3FkRequired(Parse*, Table*, int*, int); u32 sqlite3FkOldmask(Parse*, Table*); FKey *sqlite3FkReferences(Table *); #else #define sqlite3FkActions(a,b,c,d,e,f,g) #define sqlite3FkCheck(a,b,c,d,e,f,g) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #define sqlite3FkReferences(a) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY void sqlite3FkDelete(sqlite3 *, Table*); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
211 212 213 214 215 216 217 | sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION if( !IN_RENAME_OBJECT ){ | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION if( !IN_RENAME_OBJECT ){ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0); int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[iTabDb].zDbSName; const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } |
︙ | ︙ | |||
287 288 289 290 291 292 293 | DbFixer sFix; /* Fixer object */ int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | DbFixer sFix; /* Fixer object */ int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema, 0); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } sqlite3TokenInit(&nameToken, pTrig->zName); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
︙ | ︙ | |||
606 607 608 609 610 611 612 | */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; int iDb; | | | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; int iDb; iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); sqlite3SchemaWritable(pParse, iDb); pTable = tableOfTrigger(pTrigger); assert( pTable ); assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION { |
︙ | ︙ | |||
725 726 727 728 729 730 731 | ** wants. */ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ sqlite3 *db = pParse->db; | < < < < < < < < | 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | ** wants. */ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ sqlite3 *db = pParse->db; SrcList *pSrc; /* SrcList to be returned */ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); } return pSrc; } /* ** Generate VDBE code for the statements inside the body of a single ** trigger. |
︙ | ︙ | |||
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 | pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); if( !pProgram ) return 0; sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram); pPrg->pTrigger = pTrigger; pPrg->orconf = orconf; pPrg->aColmask[0] = 0xffffffff; pPrg->aColmask[1] = 0xffffffff; /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); if( !pSubParse ) return 0; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pSubParse; pSubParse->db = db; pSubParse->pTriggerTab = pTab; pSubParse->pToplevel = pTop; pSubParse->zAuthContext = pTrigger->zName; pSubParse->eTriggerOp = pTrigger->op; pSubParse->nQueryLoop = pParse->nQueryLoop; v = sqlite3GetVdbe(pSubParse); if( v ){ | > > | | | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); if( !pProgram ) return 0; sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram); pPrg->pTrigger = pTrigger; pPrg->orconf = orconf; pPrg->aColmask[0] = 0xffffffff; pPrg->aColmask[1] = 0xffffffff; pPrg->iFixDb = pParse->iFixDb; /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); if( !pSubParse ) return 0; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pSubParse; pSubParse->db = db; pSubParse->pTriggerTab = pTab; pSubParse->pToplevel = pTop; pSubParse->zAuthContext = pTrigger->zName; pSubParse->eTriggerOp = pTrigger->op; pSubParse->nQueryLoop = pParse->nQueryLoop; pSubParse->iFixDb = pParse->iFixDb; v = sqlite3GetVdbe(pSubParse); if( v ){ VdbeComment((v, "Start: %s.%s (%d) (%s %s%s%s ON %s)", pTrigger->zName, onErrorText(orconf), pParse->iFixDb-1, (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), (pTrigger->op==TK_INSERT ? "INSERT" : ""), (pTrigger->op==TK_DELETE ? "DELETE" : ""), pTab->zName )); #ifndef SQLITE_OMIT_TRACE |
︙ | ︙ | |||
963 964 965 966 967 968 969 970 971 972 973 974 975 976 | transferParseError(pParse, pSubParse); if( db->mallocFailed==0 && pParse->nErr==0 ){ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } pProgram->nMem = pSubParse->nMem; pProgram->nCsr = pSubParse->nTab; pProgram->token = (void *)pTrigger; pPrg->aColmask[0] = pSubParse->oldmask; pPrg->aColmask[1] = pSubParse->newmask; sqlite3VdbeDelete(v); } assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); | > | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 | transferParseError(pParse, pSubParse); if( db->mallocFailed==0 && pParse->nErr==0 ){ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } pProgram->nMem = pSubParse->nMem; pProgram->nCsr = pSubParse->nTab; pProgram->token = (void *)pTrigger; pProgram->itoken = pParse->iFixDb; pPrg->aColmask[0] = pSubParse->oldmask; pPrg->aColmask[1] = pSubParse->newmask; sqlite3VdbeDelete(v); } assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
︙ | ︙ | |||
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | ** Return a pointer to a TriggerPrg object containing the sub-program for ** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such ** TriggerPrg object exists, a new object is allocated and populated before ** being returned. */ static TriggerPrg *getRowTrigger( Parse *pParse, /* Current parse context */ Trigger *pTrigger, /* Trigger to code */ Table *pTab, /* The table trigger pTrigger is attached to */ int orconf /* ON CONFLICT algorithm. */ ){ Parse *pRoot = sqlite3ParseToplevel(pParse); TriggerPrg *pPrg; assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); /* It may be that this trigger has already been coded (or is in the ** process of being coded). If this is the case, then an entry with ** a matching TriggerPrg.pTrigger field will be present somewhere ** in the Parse.pTriggerPrg list. Search for such an entry. */ | > > > | | | > | > > > > | | | > | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | ** Return a pointer to a TriggerPrg object containing the sub-program for ** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such ** TriggerPrg object exists, a new object is allocated and populated before ** being returned. */ static TriggerPrg *getRowTrigger( Parse *pParse, /* Current parse context */ int iDb, /* Database containing pTab */ Trigger *pTrigger, /* Trigger to code */ Table *pTab, /* The table trigger pTrigger is attached to */ int orconf /* ON CONFLICT algorithm. */ ){ Parse *pRoot = sqlite3ParseToplevel(pParse); TriggerPrg *pPrg; int iFixDb = pParse->iFixDb; pParse->iFixDb = (pTrigger->pSchema==pRoot->db->aDb[1].pSchema)?0:(iDb+1); assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); /* It may be that this trigger has already been coded (or is in the ** process of being coded). If this is the case, then an entry with ** a matching TriggerPrg.pTrigger field will be present somewhere ** in the Parse.pTriggerPrg list. Search for such an entry. */ for(pPrg=pRoot->pTriggerPrg; pPrg; pPrg=pPrg->pNext){ if( pPrg->pTrigger==pTrigger && pPrg->orconf==orconf && pParse->iFixDb==pPrg->iFixDb ) break; } /* If an existing TriggerPrg could not be located, create a new one. */ if( !pPrg ){ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); } pParse->iFixDb = iFixDb; return pPrg; } /* ** Generate code for the trigger program associated with trigger p on ** table pTab. The reg, orconf and ignoreJump parameters passed to this ** function are the same as those described in the header function for ** sqlite3CodeRowTrigger() */ void sqlite3CodeRowTriggerDirect( Parse *pParse, /* Parse context */ int iDb, /* Database containing pTrigger */ Trigger *p, /* Trigger to code */ Table *pTab, /* The table to code triggers from */ int reg, /* Reg array containing OLD.* and NEW.* values */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf); assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program ** is a pointer to the sub-vdbe containing the trigger program. */ if( pPrg ){ int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, (const char *)pPrg->pProgram, P4_SUBPROGRAM); VdbeComment((v, "Call: %s.%s (%d)", (p->zName?p->zName:"fkey"), onErrorText(orconf), iDb )); /* Set the P5 operand of the OP_Program instruction to non-zero if ** recursive invocation of this trigger program is disallowed. Recursive ** invocation is disallowed if (a) the sub-program is really a trigger, ** not a foreign key action, and (b) the flag to enable recursive triggers ** is clear. */ sqlite3VdbeChangeP5(v, (u8)bRecursive); |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | ** Parameter orconf is the default conflict resolution algorithm for the ** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump ** is the instruction that control should jump to if a trigger program ** raises an IGNORE exception. */ void sqlite3CodeRowTrigger( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int reg, /* The first in an array of registers (see above) */ int orconf, /* ON CONFLICT policy */ | > | 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | ** Parameter orconf is the default conflict resolution algorithm for the ** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump ** is the instruction that control should jump to if a trigger program ** raises an IGNORE exception. */ void sqlite3CodeRowTrigger( Parse *pParse, /* Parse context */ int iDb, Trigger *pTrigger, /* List of triggers on table pTab */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int reg, /* The first in an array of registers (see above) */ int orconf, /* ON CONFLICT policy */ |
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 | || p->pSchema==pParse->db->aDb[1].pSchema ); /* Determine whether we should code this trigger */ if( p->op==op && p->tr_tm==tr_tm && checkColumnOverlap(p->pColumns, pChanges) ){ | | | 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 | || p->pSchema==pParse->db->aDb[1].pSchema ); /* Determine whether we should code this trigger */ if( p->op==op && p->tr_tm==tr_tm && checkColumnOverlap(p->pColumns, pChanges) ){ sqlite3CodeRowTriggerDirect(pParse, iDb, p, pTab, reg, orconf,ignoreJump); } } } /* ** Triggers may access values stored in the old.* or new.* pseudo-table. ** This function returns a 32-bit bitmask indicating which columns of the |
︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | ** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only ** included in the returned mask if the TRIGGER_BEFORE bit is set in the ** tr_tm parameter. Similarly, values accessed by AFTER triggers are only ** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. */ u32 sqlite3TriggerColmask( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int orconf /* Default ON CONFLICT policy for trigger steps */ ){ const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; assert( isNew==1 || isNew==0 ); for(p=pTrigger; p; p=p->pNext){ if( p->op==op && (tr_tm&p->tr_tm) && checkColumnOverlap(p->pColumns,pChanges) ){ TriggerPrg *pPrg; | > | | 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | ** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only ** included in the returned mask if the TRIGGER_BEFORE bit is set in the ** tr_tm parameter. Similarly, values accessed by AFTER triggers are only ** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. */ u32 sqlite3TriggerColmask( Parse *pParse, /* Parse context */ int iDb, Trigger *pTrigger, /* List of triggers on table pTab */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int orconf /* Default ON CONFLICT policy for trigger steps */ ){ const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; assert( isNew==1 || isNew==0 ); for(p=pTrigger; p; p=p->pNext){ if( p->op==op && (tr_tm&p->tr_tm) && checkColumnOverlap(p->pColumns,pChanges) ){ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf); if( pPrg ){ mask |= pPrg->aColmask[isNew]; } } } return mask; } #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
Changes to src/update.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ ExprList *pChanges, /* The columns to change in the UPDATE statement */ Expr *pRowidExpr, /* Expression used to recompute the rowid */ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ Expr *pWhere, /* WHERE clause of the UPDATE statement */ int onError /* ON CONFLICT strategy */ | > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ int iDb, SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ ExprList *pChanges, /* The columns to change in the UPDATE statement */ Expr *pRowidExpr, /* Expression used to recompute the rowid */ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ Expr *pWhere, /* WHERE clause of the UPDATE statement */ int onError /* ON CONFLICT strategy */ |
︙ | ︙ | |||
207 208 209 210 211 212 213 | } assert( pTabList->nSrc==1 ); /* Locate the table which we want to update. */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | } assert( pTabList->nSrc==1 ); /* Locate the table which we want to update. */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase); /* Figure out if we have any triggers and if the table being ** updated is a view. */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); isView = pTab->pSelect!=0; |
︙ | ︙ | |||
236 237 238 239 240 241 242 | pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" ); pOrderBy = 0; pLimit = 0; } #endif | | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" ); pOrderBy = 0; pLimit = 0; } #endif if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){ goto update_cleanup; } if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto update_cleanup; } /* Allocate a cursors for the main database table and for all indices. |
︙ | ︙ | |||
412 413 414 415 416 417 418 | } /* If we are trying to update a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ | | | | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | } /* If we are trying to update a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ sqlite3MaterializeView(pParse, iDb, pTab, pWhere, pOrderBy, pLimit, iDataCur ); pOrderBy = 0; pLimit = 0; } #endif /* Resolve the column names in all the expressions in the ** WHERE clause. */ if( sqlite3ResolveExprNames(&sNC, pWhere) ){ goto update_cleanup; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Virtual tables must be handled separately */ if( IsVirtual(pTab) ){ updateVirtualTable(pParse, iDb, pTabList, pTab, pChanges, pRowidExpr, aXRef, pWhere, onError); goto update_cleanup; } #endif /* Jump to labelBreak to abandon further processing of this UPDATE */ labelContinue = labelBreak = sqlite3VdbeMakeLabel(v); |
︙ | ︙ | |||
559 560 561 562 563 564 565 | if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; } if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } | | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; } if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, 0, 0); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); } /* Top of the update loop */ if( eOnePass!=ONEPASS_OFF ){ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ |
︙ | ︙ | |||
606 607 608 609 610 611 612 | sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } /* Compute the old pre-UPDATE content of the row being changed, if that ** information is needed */ if( chngPk || hasFK || pTrigger ){ u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); | | | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } /* Compute the old pre-UPDATE content of the row being changed, if that ** information is needed */ if( chngPk || hasFK || pTrigger ){ u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); oldmask |= sqlite3TriggerColmask(pParse, iDb, pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError ); for(i=0; i<pTab->nCol; i++){ if( oldmask==0xffffffff || (i<32 && (oldmask & MASKBIT32(i))!=0) || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ |
︙ | ︙ | |||
639 640 641 642 643 644 645 | ** this UPDATE statement and (b) not accessed by new.* references. The ** values for registers not modified by the UPDATE must be reloaded from ** the database after the BEFORE triggers are fired anyway (as the trigger ** may have modified them). So not loading those that are not going to ** be used eliminates some redundant opcodes. */ newmask = sqlite3TriggerColmask( | | | 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 | ** this UPDATE statement and (b) not accessed by new.* references. The ** values for registers not modified by the UPDATE must be reloaded from ** the database after the BEFORE triggers are fired anyway (as the trigger ** may have modified them). So not loading those that are not going to ** be used eliminates some redundant opcodes. */ newmask = sqlite3TriggerColmask( pParse, iDb, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); }else{ j = aXRef[i]; if( j>=0 ){ |
︙ | ︙ | |||
668 669 670 671 672 673 674 | } /* Fire any BEFORE UPDATE triggers. This happens before constraints are ** verified. One could argue that this is wrong. */ if( tmask&TRIGGER_BEFORE ){ sqlite3TableAffinity(v, pTab, regNew); | | | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 | } /* Fire any BEFORE UPDATE triggers. This happens before constraints are ** verified. One could argue that this is wrong. */ if( tmask&TRIGGER_BEFORE ){ sqlite3TableAffinity(v, pTab, regNew); sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); /* The row-trigger may have deleted the row being updated. In this ** case, jump to the next row. No updates or AFTER triggers are ** required. This behavior - what happens when the row being updated ** is deleted or renamed by a BEFORE trigger - is left undefined in the ** documentation. |
︙ | ︙ | |||
706 707 708 709 710 711 712 | } if( !isView ){ int addr1 = 0; /* Address of jump instruction */ /* Do constraint checks. */ assert( regOldRowid>0 ); | | | | | | 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | } if( !isView ){ int addr1 = 0; /* Address of jump instruction */ /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, iDb, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ if( bReplace || chngKey ){ if( pPk ){ addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); }else{ |
︙ | ︙ | |||
758 759 760 761 762 763 764 | } #endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } if( hasFK ){ | | | | | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 | } #endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } if( hasFK ){ sqlite3FkCheck(pParse, iDb, pTab, 0, regNewRowid, aXRef, chngKey); } /* Insert the new index entries and the new record. */ sqlite3CompleteInsertion( pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), 0, 0 ); /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just updated. */ if( hasFK ){ sqlite3FkActions(pParse, iDb, pTab, pChanges, regOldRowid, aXRef,chngKey); } } /* Increment the row counter */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ if( eOnePass==ONEPASS_SINGLE ){ /* Nothing to do at end-of-loop for a single-pass */ |
︙ | ︙ | |||
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | ** ** The "onepass" strategy does not use an ephemeral table. Instead, it ** stores the same values (A, B and C above) in a register array and ** makes a single invocation of VUpdate. */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ ExprList *pChanges, /* The columns to change in the UPDATE statement */ Expr *pRowid, /* Expression used to recompute the rowid */ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ Expr *pWhere, /* WHERE clause of the UPDATE statement */ int onError /* ON CONFLICT strategy */ ){ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* Database connection */ | > | | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | ** ** The "onepass" strategy does not use an ephemeral table. Instead, it ** stores the same values (A, B and C above) in a register array and ** makes a single invocation of VUpdate. */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ int iDb, SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ ExprList *pChanges, /* The columns to change in the UPDATE statement */ Expr *pRowid, /* Expression used to recompute the rowid */ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ Expr *pWhere, /* WHERE clause of the UPDATE statement */ int onError /* ON CONFLICT strategy */ ){ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* Database connection */ const char *pVTab = (const char*)sqlite3GetVTable(db, iDb, pTab); WhereInfo *pWInfo; int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ int regArg; /* First register in VUpdate arg array */ int regRec; /* Register in which to assemble record */ int regRowid; /* Register for ephem table rowid */ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ |
︙ | ︙ | |||
968 969 970 971 972 973 974 | /* Extract arguments from the current row of the ephemeral table and ** invoke the VUpdate method. */ for(i=0; i<nArg; i++){ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i); } } | | | 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 | /* Extract arguments from the current row of the ephemeral table and ** invoke the VUpdate method. */ for(i=0; i<nArg; i++){ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i); } } sqlite3VtabMakeWritable(pParse, iDb, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); /* End of the ephemeral table scan. Or, if using the onepass strategy, ** jump to here if the scan visited zero rows. */ if( eOnePass==ONEPASS_OFF ){ |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
163 164 165 166 167 168 169 | saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; | | > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName; pMain = db->aDb[iDb].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 | int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ Mem *pMem; /* Used to iterate through memory cells */ Mem *pEnd; /* Last memory cell in new array */ VdbeFrame *pFrame; /* New vdbe frame to execute in */ SubProgram *pProgram; /* Sub-program to execute */ void *t; /* Token identifying trigger */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; assert( pProgram->nOp>0 ); /* If the p5 flag is clear, then recursive invocation of triggers is ** disabled for backwards compatibility (p5 is set if this sub-program ** is really a trigger, not a foreign key action, and the flag set ** and cleared by the "PRAGMA recursive_triggers" command is clear). ** ** It is recursive invocation of triggers, at the SQL level, that is ** disabled. In some cases a single trigger may generate more than one ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a ** single trigger all have the same value for the SubProgram.token ** variable. */ if( pOp->p5 ){ t = pProgram->token; | > > | > > | 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 | int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ Mem *pMem; /* Used to iterate through memory cells */ Mem *pEnd; /* Last memory cell in new array */ VdbeFrame *pFrame; /* New vdbe frame to execute in */ SubProgram *pProgram; /* Sub-program to execute */ void *t; /* Token identifying trigger */ int i; /* Second part of token identifying trigger */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; assert( pProgram->nOp>0 ); /* If the p5 flag is clear, then recursive invocation of triggers is ** disabled for backwards compatibility (p5 is set if this sub-program ** is really a trigger, not a foreign key action, and the flag set ** and cleared by the "PRAGMA recursive_triggers" command is clear). ** ** It is recursive invocation of triggers, at the SQL level, that is ** disabled. In some cases a single trigger may generate more than one ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a ** single trigger all have the same value for the SubProgram.token ** variable. */ if( pOp->p5 ){ t = pProgram->token; i = pProgram->itoken; for(pFrame=p->pFrame; pFrame && (pFrame->token!=t || pFrame->itoken!=i); pFrame=pFrame->pParent); if( pFrame ) break; } if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ rc = SQLITE_ERROR; sqlite3VdbeError(p, "too many levels of trigger recursion"); goto abort_due_to_error; |
︙ | ︙ | |||
6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 | pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pFrame->anExec = p->anExec; #endif #ifdef SQLITE_DEBUG pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; #endif | > | 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 | pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; pFrame->itoken = pProgram->itoken; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS pFrame->anExec = p->anExec; #endif #ifdef SQLITE_DEBUG pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; #endif |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | struct SubProgram { VdbeOp *aOp; /* Array of opcodes for sub-program */ int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ u8 *aOnce; /* Array of OP_Once flags */ void *token; /* id that may be used to recursive triggers */ SubProgram *pNext; /* Next sub-program already visited */ }; /* ** A smaller version of VdbeOp used for the VdbeAddOpList() function because ** it takes up less space. */ | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | struct SubProgram { VdbeOp *aOp; /* Array of opcodes for sub-program */ int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ u8 *aOnce; /* Array of OP_Once flags */ void *token; /* id that may be used to recursive triggers */ int itoken; /* Second part of id to identify rec. trig. */ SubProgram *pNext; /* Next sub-program already visited */ }; /* ** A smaller version of VdbeOp used for the VdbeAddOpList() function because ** it takes up less space. */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 | VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ u8 *aOnce; /* Bitmask used by OP_Once */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #if SQLITE_DEBUG u32 iFrameMagic; /* magic number for sanity checking */ #endif int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ | > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ u8 *aOnce; /* Bitmask used by OP_Once */ void *token; /* Copy of SubProgram.token */ int itoken; /* Copy of SubProgram.itoken */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #if SQLITE_DEBUG u32 iFrameMagic; /* magic number for sanity checking */ #endif int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ |
︙ | ︙ | |||
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeList(Vdbe*); int sqlite3VdbeHalt(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemTooBig(Mem*); int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); void sqlite3VdbeMemMove(Mem*, Mem*); int sqlite3VdbeMemNulTerminate(Mem*); | > > | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); int sqlite3VdbeExec(Vdbe*); #ifndef SQLITE_OMIT_EXPLAIN int sqlite3VdbeList(Vdbe*); #endif int sqlite3VdbeHalt(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemTooBig(Mem*); int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); void sqlite3VdbeMemMove(Mem*, Mem*); int sqlite3VdbeMemNulTerminate(Mem*); |
︙ | ︙ | |||
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); #ifndef SQLITE_OMIT_WINDOWFUNC int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); #endif const char *sqlite3OpcodeName(int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); #ifdef SQLITE_DEBUG int sqlite3VdbeFrameIsValid(VdbeFrame*); #endif void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ | > > | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); #ifndef SQLITE_OMIT_WINDOWFUNC int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); #endif #ifndef SQLITE_OMIT_EXPLAIN const char *sqlite3OpcodeName(int); #endif int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); #ifdef SQLITE_DEBUG int sqlite3VdbeFrameIsValid(VdbeFrame*); #endif void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
179 180 181 182 183 184 185 | sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db,pTab->pSchema,zDb)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iCol<pTab->nCol; iCol++) { if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ break; } } |
︙ | ︙ | |||
266 267 268 269 270 271 272 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema, zDb); VdbeOp *aOp; sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); sqlite3VdbeChangeP5(v, 1); assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
137 138 139 140 141 142 143 | /* ** pTab is a pointer to a Table structure representing a virtual-table. ** Return a pointer to the VTable object used by connection db to access ** this virtual-table, if one has been created, or NULL otherwise. */ | | > > > > | > | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | /* ** pTab is a pointer to a Table structure representing a virtual-table. ** Return a pointer to the VTable object used by connection db to access ** this virtual-table, if one has been created, or NULL otherwise. */ VTable *sqlite3GetVTable(sqlite3 *db, int iDb, Table *pTab){ VTable *pVtab; assert( IsVirtual(pTab) ); if( iDb>=0 ){ Btree *pBt = db->aDb[iDb].pBt; for(pVtab=pTab->pVTable; pVtab && pVtab->pBt!=pBt; pVtab=pVtab->pNext); }else{ for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); } return pVtab; } /* ** Decrement the ref-count on a virtual table object. When the ref-count ** reaches zero, call the xDisconnect() method to delete the object. */ |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 | ** list in p->pVTab. It also decrements the VTable ref count. This is ** used when closing database connection db to free all of its VTable ** objects without disturbing the rest of the Schema object (which may ** be being used by other shared-cache connections). */ void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ VTable **ppVTab; assert( IsVirtual(p) ); assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); | > | | > | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | ** list in p->pVTab. It also decrements the VTable ref count. This is ** used when closing database connection db to free all of its VTable ** objects without disturbing the rest of the Schema object (which may ** be being used by other shared-cache connections). */ void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ VTable **ppVTab; VTable **ppNext; assert( IsVirtual(p) ); assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); for(ppVTab=&p->pVTable; *ppVTab; ){ if( (*ppVTab)->db==db ){ VTable *pVTab = *ppVTab; *ppVTab = pVTab->pNext; sqlite3VtabUnlock(pVTab); }else{ ppVTab = &(*ppVTab)->pNext; } } } /* ** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. |
︙ | ︙ | |||
352 353 354 355 356 357 358 | #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the ** sqlite_master table, has already been made by sqlite3StartTable(). ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ | | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the ** sqlite_master table, has already been made by sqlite3StartTable(). ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema, 0); /* TODO */ assert( iDb>=0 ); /* The database the table is being created in */ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } |
︙ | ︙ | |||
414 415 416 417 418 419 420 | ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. ** ** The VM register number pParse->regRowid holds the rowid of an ** entry in the sqlite_master table tht was created for this vtab ** by sqlite3StartTable(). */ | | | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. ** ** The VM register number pParse->regRowid holds the rowid of an ** entry in the sqlite_master table tht was created for this vtab ** by sqlite3StartTable(). */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0); sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#%d", db->aDb[iDb].zDbSName, MASTER_NAME, pTab->zName, pTab->zName, |
︙ | ︙ | |||
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | /* ** Invoke a virtual table constructor (either xCreate or xConnect). The ** pointer to the function to invoke is passed as the fourth parameter ** to this procedure. */ static int vtabCallConstructor( sqlite3 *db, Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; char *zModuleName; | > < | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | /* ** Invoke a virtual table constructor (either xCreate or xConnect). The ** pointer to the function to invoke is passed as the fourth parameter ** to this procedure. */ static int vtabCallConstructor( sqlite3 *db, int iDb, /* Database containing pTab */ Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; char *zModuleName; VtabCtx *pCtx; /* Check that the virtual-table is not already being initialized */ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ if( pCtx->pTab==pTab ){ *pzErr = sqlite3MPrintf(db, "vtable constructor called recursively: %s", pTab->zName |
︙ | ︙ | |||
527 528 529 530 531 532 533 534 535 | pVTable = sqlite3MallocZero(sizeof(VTable)); if( !pVTable ){ sqlite3OomFault(db); sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pMod = pMod; | > < | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | pVTable = sqlite3MallocZero(sizeof(VTable)); if( !pVTable ){ sqlite3OomFault(db); sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pBt = db->aDb[iDb].pBt; pVTable->pMod = pMod; pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; |
︙ | ︙ | |||
618 619 620 621 622 623 624 | /* ** This function is invoked by the parser to call the xConnect() method ** of the virtual table pTab. If an error occurs, an error code is returned ** and an error left in pParse. ** ** This call is a no-op if table pTab is not a virtual table. */ | | | | | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 | /* ** This function is invoked by the parser to call the xConnect() method ** of the virtual table pTab. If an error occurs, an error code is returned ** and an error left in pParse. ** ** This call is a no-op if table pTab is not a virtual table. */ int sqlite3VtabCallConnect(Parse *pParse, int iDb, Table *pTab){ sqlite3 *db = pParse->db; const char *zMod; Module *pMod; int rc; assert( pTab ); if( !IsVirtual(pTab) || sqlite3GetVTable(db, iDb, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; sqlite3ErrorMsg(pParse, "no such module: %s", zModule); rc = SQLITE_ERROR; }else{ char *zErr = 0; rc = vtabCallConstructor(db, iDb, pTab, pMod,pMod->pModule->xConnect,&zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); pParse->rc = rc; } sqlite3DbFree(db, zErr); } |
︙ | ︙ | |||
710 711 712 713 714 715 716 | ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; }else{ | | | | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; }else{ rc = vtabCallConstructor(db, iDb, pTab, pMod, pMod->pModule->xCreate,pzErr); } /* Justification of ALWAYS(): The xConstructor method is required to ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, iDb, pTab)) ){ rc = growVTrans(db); if( rc==SQLITE_OK ){ addToVTrans(db, sqlite3GetVTable(db, iDb, pTab)); } } return rc; } /* |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; | | | 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, -1, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction==0 ) return pDef; /* Call the xFindFunction method on the virtual table implementation ** to see if the implementation wants to overload this function. |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | /* ** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] ** array so that an OP_VBegin will get generated for it. Add pTab to the ** array if it is missing. If pTab is already in the array, this routine ** is a no-op. */ | | > | | | | 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | /* ** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] ** array so that an OP_VBegin will get generated for it. Add pTab to the ** array if it is missing. If pTab is already in the array, this routine ** is a no-op. */ void sqlite3VtabMakeWritable(Parse *pParse, int iDb, Table *pTab){ Parse *pToplevel = sqlite3ParseToplevel(pParse); VTable *pVTab = sqlite3GetVTable(pParse->db, iDb, pTab); int i, n; VTable **apVtabLock; assert( IsVirtual(pTab) ); for(i=0; i<pToplevel->nVtabLock; i++){ if( pVTab==pToplevel->apVtabLock[i] ) return; } n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); if( apVtabLock ){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pVTab; }else{ sqlite3OomFault(pToplevel->db); } } /* ** Check to see if virtual table module pMod can be have an eponymous |
︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 | pTab->nTabRef = 1; pTab->pSchema = db->aDb[0].pSchema; assert( pTab->nModuleArg==0 ); pTab->iPKey = -1; addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); addModuleArgument(db, pTab, 0); addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); | | | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 | pTab->nTabRef = 1; pTab->pSchema = db->aDb[0].pSchema; assert( pTab->nModuleArg==0 ); pTab->iPKey = -1; addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); addModuleArgument(db, pTab, 0); addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); rc = vtabCallConstructor(db, 0, pTab, pMod, pModule->xConnect, &zErr); if( rc ){ sqlite3ErrorMsg(pParse, "%s", zErr); sqlite3DbFree(db, zErr); sqlite3VtabEponymousTableClear(db, pMod); return 0; } return 1; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 | /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** | | | > | > | > > > > > > | | < < < < < < < < < < < < | | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 | /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** ** If an error occurs, pParse is populated with an error message and an ** appropriate error code is returned. A return of SQLITE_CONSTRAINT from ** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that ** the current configuration of "unusable" flags in sqlite3_index_info can ** not result in a valid plan. ** ** Whether or not an error is returned, it is the responsibility of the ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates ** that this is required. */ static int vtabBestIndex( Parse *pParse, struct SrcList_item *pSrc, sqlite3_index_info *p ){ Table *pTab = pSrc->pTab; int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, pSrc->zDatabase); sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, iDb, pTab)->pVtab; int rc; TRACE_IDX_INPUTS(p); rc = pVtab->pModule->xBestIndex(pVtab, p); TRACE_IDX_OUTPUTS(p); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: |
︙ | ︙ | |||
3138 3139 3140 3141 3142 3143 3144 | pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; /* Invoke the virtual table xBestIndex() method */ | | | > > > > > > > > > > | 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 | pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc, pIdxInfo); if( rc ){ if( rc==SQLITE_CONSTRAINT ){ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means ** that the particular combination of parameters provided is unusable. ** Make no entries in the loop table. */ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); return SQLITE_OK; } return rc; } mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0; pNew->u.vtab.omitMask = 0; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<nConstraint; i++, pIdxCons++){ |
︙ | ︙ | |||
4938 4939 4940 4941 4942 4943 4944 | for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){ Table *pTab; /* Table to open */ int iDb; /* Index of database containing table/index */ struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; | | | | 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 | for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){ Table *pTab; /* Table to open */ int iDb; /* Index of database containing table/index */ struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabItem->zDatabase); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else if( IsVirtual(pTab) ){ /* noop */ }else #endif if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
405 406 407 408 409 410 411 | */ pCol = pList->a[0].pExpr; if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; | | | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | */ pCol = pList->a[0].pExpr; if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; pVtab = sqlite3GetVTable(db, -1, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction!=0 ){ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ *peOp2 = i; |
︙ | ︙ |
Changes to test/alter2.test.
︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # to the supplied value. This is 2 if the added column has a default that is # NULL, or 3 otherwise. # proc alter_table {tbl sql {file_format 2}} { sqlite3 dbat test.db set s [string map {' ''} $sql] set t [string map {' ''} $tbl] dbat eval [subst { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table'; PRAGMA writable_schema = 0; }] dbat close set_file_format 2 | > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | # to the supplied value. This is 2 if the added column has a default that is # NULL, or 3 otherwise. # proc alter_table {tbl sql {file_format 2}} { sqlite3 dbat test.db set s [string map {' ''} $sql] set t [string map {' ''} $tbl] sqlite3_db_config dbat DEFENSIVE 0 dbat eval [subst { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table'; PRAGMA writable_schema = 0; }] dbat close set_file_format 2 |
︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 98 99 100 | catchsql {SELECT substr('abcdefg',1,3)} } {1 {bad function}} #----------------------------------------------------------------------- # Some basic tests to make sure short rows are handled. # do_test alter2-1.1 { execsql { CREATE TABLE abc(a, b); INSERT INTO abc VALUES(1, 2); INSERT INTO abc VALUES(3, 4); INSERT INTO abc VALUES(5, 6); } | > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | catchsql {SELECT substr('abcdefg',1,3)} } {1 {bad function}} #----------------------------------------------------------------------- # Some basic tests to make sure short rows are handled. # sqlite3_db_config db DEFENSIVE 0 do_test alter2-1.1 { execsql { CREATE TABLE abc(a, b); INSERT INTO abc VALUES(1, 2); INSERT INTO abc VALUES(3, 4); INSERT INTO abc VALUES(5, 6); } |
︙ | ︙ |
Changes to test/altercol.test.
︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 | do_execsql_test 13.1.3 { DROP TRIGGER tr1; CREATE INDEX x1i ON x1(i); SELECT sql FROM sqlite_master WHERE name='x1i'; } {{CREATE INDEX x1i ON x1(i)}} do_execsql_test 13.1.4 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; } {} do_catchsql_test 13.1.5 { ALTER TABLE x1 RENAME COLUMN t TO ttt; | > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | do_execsql_test 13.1.3 { DROP TRIGGER tr1; CREATE INDEX x1i ON x1(i); SELECT sql FROM sqlite_master WHERE name='x1i'; } {{CREATE INDEX x1i ON x1(i)}} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 13.1.4 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; } {} do_catchsql_test 13.1.5 { ALTER TABLE x1 RENAME COLUMN t TO ttt; |
︙ | ︙ |
Changes to test/alterlegacy.test.
︙ | ︙ | |||
463 464 465 466 467 468 469 | } do_execsql_test 14.6 { ALTER TABLE t1 RENAME TO tt1; } finish_test | < | 463 464 465 466 467 468 469 | } do_execsql_test 14.6 { ALTER TABLE t1 RENAME TO tt1; } finish_test |
Changes to test/altertab.test.
︙ | ︙ | |||
501 502 503 504 505 506 507 | do_execsql_test 15.5 { SELECT sql FROM sqlite_master WHERE name = 'y'; } {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}} finish_test | < | 501 502 503 504 505 506 507 | do_execsql_test 15.5 { SELECT sql FROM sqlite_master WHERE name = 'y'; } {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}} finish_test |
Changes to test/altertab2.test.
︙ | ︙ | |||
37 38 39 40 41 42 43 | do_execsql_test 1.2 { INSERT INTO rr VALUES('in', 'tcl'); SELECT * FROM ffff; } {hello world in tcl} } | > > > | > > > > > > > > > | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | do_execsql_test 1.2 { INSERT INTO rr VALUES('in', 'tcl'); SELECT * FROM ffff; } {hello world in tcl} } #------------------------------------------------------------------------- # Check that table names that appear in REFERENCES clauses are updated # when a table is renamed unless: # # a) "PRAGMA legacy_alter_table" is true, and # b) "PRAGMA foreign_keys" is false. # do_execsql_test 2.0 { CREATE TABLE p1(a PRIMARY KEY, b); CREATE TABLE c1(x REFERENCES p1); CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES p1); CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES p1(a)); } do_execsql_test 2.1 { ALTER TABLE p1 RENAME TO p2; SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; } { {CREATE TABLE c1(x REFERENCES "p2")} {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p2")} {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p2"(a))} } do_execsql_test 2.2 { PRAGMA legacy_alter_table = 1; ALTER TABLE p2 RENAME TO p3; SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; } { {CREATE TABLE c1(x REFERENCES "p2")} {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p2")} {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p2"(a))} } do_execsql_test 2.3 { ALTER TABLE p3 RENAME TO p2; PRAGMA foreign_keys = 1; ALTER TABLE p2 RENAME TO p3; SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; } { {CREATE TABLE c1(x REFERENCES "p3")} {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p3")} {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))} } finish_test |
Changes to test/analyze.test.
︙ | ︙ | |||
346 347 348 349 350 351 352 353 354 355 356 357 358 359 | } {t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-5.99 { execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='sqlite_stat1'; } db close catch { sqlite3 db test.db } catchsql { | > | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | } {t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-5.99 { sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='sqlite_stat1'; } db close catch { sqlite3 db test.db } catchsql { |
︙ | ︙ |
Changes to test/attach.test.
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 | END; } db2 } {1 {trigger r5 cannot reference objects in database temp}} } ;# endif subquery ifcapable json1 { do_test attach-5.10 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(x); CREATE TABLE t2(a,b); CREATE TRIGGER x1 AFTER INSERT ON t1 BEGIN INSERT INTO t2(a,b) SELECT key, value FROM json_each(NEW.x); | > | 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | END; } db2 } {1 {trigger r5 cannot reference objects in database temp}} } ;# endif subquery ifcapable json1 { do_test attach-5.10 { db close catch {db2 close} forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(x); CREATE TABLE t2(a,b); CREATE TRIGGER x1 AFTER INSERT ON t1 BEGIN INSERT INTO t2(a,b) SELECT key, value FROM json_each(NEW.x); |
︙ | ︙ |
Changes to test/autoinc.test.
︙ | ︙ | |||
693 694 695 696 697 698 699 700 701 702 703 704 705 706 | # Does not crash if the sqlite_sequence table schema is missing # or corrupt. # do_test autoinc-12.1 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'fake_','sqlite_'), name='sqlite_sequence', tbl_name='sqlite_sequence' | > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | # Does not crash if the sqlite_sequence table schema is missing # or corrupt. # do_test autoinc-12.1 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'fake_','sqlite_'), name='sqlite_sequence', tbl_name='sqlite_sequence' |
︙ | ︙ | |||
714 715 716 717 718 719 720 721 722 723 724 725 726 727 | }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.2 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'sqlite_','x_'), name='x_sequence', | > | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 | }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.2 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'sqlite_','x_'), name='x_sequence', |
︙ | ︙ | |||
740 741 742 743 744 745 746 747 748 749 750 751 752 753 | } else { set err {malformed database schema (sqlite_sequence) - near "VIRTUAL": syntax error} } do_test autoinc-12.3 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage' WHERE name='sqlite_sequence'; | > | 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | } else { set err {malformed database schema (sqlite_sequence) - near "VIRTUAL": syntax error} } do_test autoinc-12.3 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage' WHERE name='sqlite_sequence'; |
︙ | ︙ | |||
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 | INSERT INTO t1(b) VALUES('one'); CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; } set root1 [db one {SELECT rootpage FROM sqlite_master WHERE name='sqlite_sequence'}] set root2 [db one {SELECT rootpage FROM sqlite_master WHERE name='fake'}] db eval { PRAGMA writable_schema=on; UPDATE sqlite_master SET rootpage=$root2 WHERE name='sqlite_sequence'; UPDATE sqlite_master SET rootpage=$root1 WHERE name='fake'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} breakpoint do_test autoinc-12.5 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x)' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.6 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)' WHERE name='sqlite_sequence'; | > > > | 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 | INSERT INTO t1(b) VALUES('one'); CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; } set root1 [db one {SELECT rootpage FROM sqlite_master WHERE name='sqlite_sequence'}] set root2 [db one {SELECT rootpage FROM sqlite_master WHERE name='fake'}] sqlite3_db_config db DEFENSIVE 0 db eval { PRAGMA writable_schema=on; UPDATE sqlite_master SET rootpage=$root2 WHERE name='sqlite_sequence'; UPDATE sqlite_master SET rootpage=$root1 WHERE name='fake'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} breakpoint do_test autoinc-12.5 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x)' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.6 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)' WHERE name='sqlite_sequence'; |
︙ | ︙ | |||
827 828 829 830 831 832 833 834 835 836 837 838 839 840 | }} msg] lappend res $msg } {0 ok} do_test autoinc-12.7 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)' WHERE name='sqlite_sequence'; | > | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | }} msg] lappend res $msg } {0 ok} do_test autoinc-12.7 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)' WHERE name='sqlite_sequence'; |
︙ | ︙ |
Changes to test/bestindex4.test.
︙ | ︙ | |||
151 152 153 154 155 156 157 | } do_execsql_test 2.0 { CREATE VIRTUAL TABLE x1 USING tcl(vtab_command); CREATE TABLE t1 (x INT PRIMARY KEY); } {} | | | > | | | | > | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | } do_execsql_test 2.0 { CREATE VIRTUAL TABLE x1 USING tcl(vtab_command); CREATE TABLE t1 (x INT PRIMARY KEY); } {} do_eqp_test 2.1 { SELECT * FROM t1, x1 WHERE x1.d=t1.x; } { QUERY PLAN |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0: `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?) } do_eqp_test 2.2 { SELECT * FROM t1, x1(t1.x) } { QUERY PLAN |--SCAN TABLE t1 `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555: } finish_test |
Changes to test/bestindex5.test.
︙ | ︙ | |||
243 244 245 246 247 248 249 | do_execsql_test 3.3 { SELECT rowid, * FROM t4 WHERE x!=245; } {} do_execsql_test 3.4 { SELECT rowid, * FROM t4 WHERE x!='245'; } {} do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {} finish_test | < | 243 244 245 246 247 248 249 | do_execsql_test 3.3 { SELECT rowid, * FROM t4 WHERE x!=245; } {} do_execsql_test 3.4 { SELECT rowid, * FROM t4 WHERE x!='245'; } {} do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {} finish_test |
Changes to test/capi3.test.
︙ | ︙ | |||
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 | execsql { CREATE TABLE t1(a); } db close } {} do_test capi3-8.2 { sqlite3 db test.db execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); } db close } {} do_test capi3-8.3 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; | > > | 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | execsql { CREATE TABLE t1(a); } db close } {} do_test capi3-8.2 { sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); } db close } {} do_test capi3-8.3 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; |
︙ | ︙ |
Changes to test/capi3c.test.
︙ | ︙ | |||
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 | execsql { CREATE TABLE t1(a); } db close } {} do_test capi3c-8.2 { sqlite3 db test.db execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); } db close } {} do_test capi3c-8.3 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3c-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; | > > | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | execsql { CREATE TABLE t1(a); } db close } {} do_test capi3c-8.2 { sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); } db close } {} do_test capi3c-8.3 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3c-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; |
︙ | ︙ |
Changes to test/corrupt.test.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | sqlite3 db test.db list } {} do_test corrupt-3.2 { set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}] set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}] set cookie [expr [execsql {PRAGMA schema_version}] + 1] execsql " PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $t1_r WHERE name = 't1'; UPDATE sqlite_master SET rootpage = $t1i1_r WHERE name = 't1i1'; PRAGMA writable_schema = 0; PRAGMA schema_version = $cookie; " | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | sqlite3 db test.db list } {} do_test corrupt-3.2 { set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}] set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}] set cookie [expr [execsql {PRAGMA schema_version}] + 1] sqlite3_db_config db DEFENSIVE 0 execsql " PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $t1_r WHERE name = 't1'; UPDATE sqlite_master SET rootpage = $t1i1_r WHERE name = 't1i1'; PRAGMA writable_schema = 0; PRAGMA schema_version = $cookie; " |
︙ | ︙ |
Changes to test/corrupt2.test.
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 | do_test corrupt2-2.1 { forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db sqlite3 db2 corrupt.db execsql " $::presql CREATE INDEX a1 ON abc(a); CREATE INDEX a2 ON abc(b); PRAGMA writable_schema = 1; UPDATE sqlite_master SET name = 'a3', sql = 'CREATE INDEX a3' || substr(sql, 16, 10000) | > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | do_test corrupt2-2.1 { forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db sqlite3 db2 corrupt.db sqlite3_db_config db2 DEFENSIVE 0 execsql " $::presql CREATE INDEX a1 ON abc(a); CREATE INDEX a2 ON abc(b); PRAGMA writable_schema = 1; UPDATE sqlite_master SET name = 'a3', sql = 'CREATE INDEX a3' || substr(sql, 16, 10000) |
︙ | ︙ | |||
261 262 263 264 265 266 267 268 269 270 271 272 273 274 | array set A $args catch {db close} forcedelete corrupt.db forcedelete corrupt.db-journal sqlite3 db corrupt.db db eval $::presql eval $A(-tclprep) db eval $A(-sqlprep) db close eval $A(-corrupt) | > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | array set A $args catch {db close} forcedelete corrupt.db forcedelete corrupt.db-journal sqlite3 db corrupt.db sqlite3_db_config db DEFENSIVE 0 db eval $::presql eval $A(-tclprep) db eval $A(-sqlprep) db close eval $A(-corrupt) |
︙ | ︙ |
Changes to test/corrupt5.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | finish_test return } # Create a database with a freelist containing at least two pages. # do_test corrupt5-1.1 { execsql { CREATE TABLE t1(a,b,c); CREATE INDEX i1 ON t1(a,b); PRAGMA writable_schema=ON; UPDATE sqlite_master SET name=NULL, sql=NULL WHERE name='i1'; } db close | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | finish_test return } # Create a database with a freelist containing at least two pages. # do_test corrupt5-1.1 { sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a,b,c); CREATE INDEX i1 ON t1(a,b); PRAGMA writable_schema=ON; UPDATE sqlite_master SET name=NULL, sql=NULL WHERE name='i1'; } db close |
︙ | ︙ |
Changes to test/corruptI.test.
︙ | ︙ | |||
218 219 220 221 222 223 224 225 226 227 228 229 230 231 | PRAGMA auto_vacuum=0; CREATE TABLE t1(x PRIMARY KEY, y); INSERT INTO t1 VALUES('a', 'A'); INSERT INTO t1 VALUES('b', 'A'); INSERT INTO t1 VALUES('c', 'A'); SELECT name FROM sqlite_master; } {t1 sqlite_autoindex_t1_1} do_execsql_test 7.1 { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1'; } do_test 7.2 { db close sqlite3 db test.db | > | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | PRAGMA auto_vacuum=0; CREATE TABLE t1(x PRIMARY KEY, y); INSERT INTO t1 VALUES('a', 'A'); INSERT INTO t1 VALUES('b', 'A'); INSERT INTO t1 VALUES('c', 'A'); SELECT name FROM sqlite_master; } {t1 sqlite_autoindex_t1_1} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 7.1 { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1'; } do_test 7.2 { db close sqlite3 db test.db |
︙ | ︙ |
Changes to test/corruptK.test.
︙ | ︙ | |||
139 140 141 142 143 144 145 | PRAGMA page_size=1024; CREATE TABLE t1(a, b, c); CREATE TABLE t2(a, b, c); CREATE TABLE t3(a, b, c); CREATE TABLE t4(a, b, c); CREATE TABLE t5(a, b, c); } | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | PRAGMA page_size=1024; CREATE TABLE t1(a, b, c); CREATE TABLE t2(a, b, c); CREATE TABLE t3(a, b, c); CREATE TABLE t4(a, b, c); CREATE TABLE t5(a, b, c); } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { UPDATE sqlite_dbpage SET data = hex2blob(' 000: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. 010: 04 00 01 01 20 40 20 20 00 00 3e d9 00 00 00 06 .... @ ..>..... 020: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................ 030: 0f 00 00 00 00 00 00 00 00 00 00 01 00 00 83 00 ................ 040: 00 00 00 00 00 00 00 00 00 00 00 00 00 38 00 00 .............8.. |
︙ | ︙ |
Changes to test/countofview.test.
︙ | ︙ | |||
37 38 39 40 41 42 43 | do_execsql_test 1.3 { select count(*) from ( select c from t2 union all select f from t3 ) } {3} finish_test | < | 37 38 39 40 41 42 43 | do_execsql_test 1.3 { select count(*) from ( select c from t2 union all select f from t3 ) } {3} finish_test |
Changes to test/csv01.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | } {9 10 11 12} do_execsql_test 1.1 { SELECT * FROM t1 WHERE c1='10'; } {9 10 11 12} do_execsql_test 1.2 { SELECT rowid FROM t1; } {1 2 3 4} do_execsql_test 2.0 { DROP TABLE t1; CREATE VIRTUAL TABLE temp.t2 USING csv( data= '1,2,3,4 5,6,7,8 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | } {9 10 11 12} do_execsql_test 1.1 { SELECT * FROM t1 WHERE c1='10'; } {9 10 11 12} do_execsql_test 1.2 { SELECT rowid FROM t1; } {1 2 3 4} do_execsql_test 1.3 { DROP TABLE temp.t1; CREATE VIRTUAL TABLE temp.t1 USING csv( data= 'a,b,"mix-bloom-eel","soft opinion" 1,2,3,4 5,6,7,8 9,10,11,12 13,14,15,16 ', header=1 ); SELECT * FROM t1 WHERE "soft opinion"=12; } {9 10 11 12} do_execsql_test 1.4 { SELECT name FROM pragma_table_xinfo('t1'); } {a b mix-bloom-eel {soft opinion}} do_execsql_test 1.5 { DROP TABLE temp.t1; CREATE VIRTUAL TABLE temp.t1 USING csv( data= 'a,b,"mix-bloom-eel","soft opinion" 1,2,3,4 5,6,7,8 9,10,11,12 13,14,15,16 ', header=false ); SELECT * FROM t1 WHERE c1='b'; } {a b mix-bloom-eel {soft opinion}} do_execsql_test 1.6 { SELECT name FROM pragma_table_xinfo('t1'); } {c0 c1 c2 c3} do_execsql_test 1.7 { DROP TABLE temp.t1; CREATE VIRTUAL TABLE temp.t1 USING csv( data= 'a,b,"mix-bloom-eel","soft opinion" 1,2,3,4 5,6,7,8 9,10,11,12 13,14,15,16 ', header, schema='CREATE TABLE x(x0,x1,x2,x3,x4)', columns=5 ); SELECT * FROM t1 WHERE x1='6'; } {5 6 7 8 {}} do_execsql_test 1.8 { SELECT name FROM pragma_table_xinfo('t1'); } {x0 x1 x2 x3 x4} do_execsql_test 2.0 { DROP TABLE t1; CREATE VIRTUAL TABLE temp.t2 USING csv( data= '1,2,3,4 5,6,7,8 |
︙ | ︙ | |||
103 104 105 106 107 108 109 | 9,10,11,12 13,14,15,16', columns=4, schema= 'CREATE TABLE t3(a,b,c,d,PRIMARY KEY(a,b)) WITHOUT ROWID', testflags=1 ); | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | 9,10,11,12 13,14,15,16', columns=4, schema= 'CREATE TABLE t3(a,b,c,d,PRIMARY KEY(a,b)) WITHOUT ROWID', testflags=1 ); } {1 {bad schema: 'CREATE TABLE t3(a,b,c,d,PRIMARY KEY(a,b)) WITHOUT ROWID' - not an error}} # WITHOUT ROWID tables with a single-column PRIMARY KEY may be writable. do_catchsql_test 4.1 { DROP TABLE IF EXISTS t4; CREATE VIRTUAL TABLE temp.t4 USING csv_wr( data= '1,2,3,4 |
︙ | ︙ | |||
134 135 136 137 138 139 140 | 9,10,11,12 13,14,15,16', columns=4, schema= 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID', testflags=1 ); | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | 9,10,11,12 13,14,15,16', columns=4, schema= 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID', testflags=1 ); } {1 {bad schema: 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID' - PRIMARY KEY missing on table t3}} # 2018-04-24 # Memory leak reported on the sqlite-users mailing list by Ralf Junker. # do_catchsql_test 4.3 { CREATE VIRTUAL TABLE IF NOT EXISTS temp.t1 USING csv(filename='FileDoesNotExist.csv'); |
︙ | ︙ |
Changes to test/dbpage.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | set testprefix dbpage ifcapable !vtab||!compound { finish_test return } do_test 100 { execsql { PRAGMA auto_vacuum=0; PRAGMA page_size=4096; PRAGMA journal_mode=WAL; } execsql { | > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | set testprefix dbpage ifcapable !vtab||!compound { finish_test return } sqlite3_db_config db DEFENSIVE 0 do_test 100 { execsql { PRAGMA auto_vacuum=0; PRAGMA page_size=4096; PRAGMA journal_mode=WAL; } execsql { |
︙ | ︙ |
Changes to test/default.test.
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # Do now allow bound parameters in new DEFAULT values. # Silently convert bound parameters to NULL in DEFAULT causes # in the sqlite_master table, for backwards compatibility. # db close forcedelete test.db sqlite3 db test.db do_execsql_test default-4.0 { CREATE TABLE t1(a TEXT, b TEXT DEFAULT(99)); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE t1(a TEXT, b TEXT DEFAULT(:xyz))'; } {} db close sqlite3 db test.db | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # Do now allow bound parameters in new DEFAULT values. # Silently convert bound parameters to NULL in DEFAULT causes # in the sqlite_master table, for backwards compatibility. # db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 do_execsql_test default-4.0 { CREATE TABLE t1(a TEXT, b TEXT DEFAULT(99)); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE t1(a TEXT, b TEXT DEFAULT(:xyz))'; } {} db close sqlite3 db test.db |
︙ | ︙ |
Changes to test/e_fkey.test.
︙ | ︙ | |||
2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 | SELECT sql FROM sqlite_master WHERE name = 'c'; ROLLBACK; } } {{CREATE TABLE c(b REFERENCES "parent"(a))}} do_test e_fkey-61.2.2 { execsql { PRAGMA foreign_keys = OFF; ALTER TABLE p RENAME TO parent; SELECT sql FROM sqlite_master WHERE name = 'c'; } } {{CREATE TABLE c(b REFERENCES p(a))}} do_test e_fkey-61.2.3 { execsql { PRAGMA foreign_keys = ON } } {} do_test e_fkey-61.3.1 { drop_all_tables execsql { CREATE TABLE p(a UNIQUE); CREATE TABLE c(b REFERENCES p(a) ON DELETE SET NULL); | > > | 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 | SELECT sql FROM sqlite_master WHERE name = 'c'; ROLLBACK; } } {{CREATE TABLE c(b REFERENCES "parent"(a))}} do_test e_fkey-61.2.2 { execsql { PRAGMA foreign_keys = OFF; PRAGMA legacy_alter_table = ON; ALTER TABLE p RENAME TO parent; SELECT sql FROM sqlite_master WHERE name = 'c'; } } {{CREATE TABLE c(b REFERENCES p(a))}} do_test e_fkey-61.2.3 { execsql { PRAGMA foreign_keys = ON } execsql { PRAGMA legacy_alter_table = OFF } } {} do_test e_fkey-61.3.1 { drop_all_tables execsql { CREATE TABLE p(a UNIQUE); CREATE TABLE c(b REFERENCES p(a) ON DELETE SET NULL); |
︙ | ︙ |
Changes to test/e_fts3.test.
︙ | ︙ | |||
673 674 675 676 677 678 679 680 681 682 683 684 685 686 | # set DO_MALLOC_TEST 0 ddl_test 10.1.1 { CREATE VIRTUAL TABLE ta USING fts3 } write_test 10.1.2 ta_content { INSERT INTO ta VALUES('During a summer vacation in 1790') } write_test 10.1.3 ta_content { INSERT INTO ta VALUES('Wordsworth went on a walking tour') } write_test 10.1.4 ta_content { DELETE FROM ta_content WHERE rowid = 2 } read_test 10.1.5 { SELECT * FROM ta WHERE ta MATCH 'summer' } {{During a summer vacation in 1790}} error_test 10.1.6 { SELECT * FROM ta WHERE ta MATCH 'walking' } {database disk image is malformed} | > | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | # set DO_MALLOC_TEST 0 ddl_test 10.1.1 { CREATE VIRTUAL TABLE ta USING fts3 } write_test 10.1.2 ta_content { INSERT INTO ta VALUES('During a summer vacation in 1790') } write_test 10.1.3 ta_content { INSERT INTO ta VALUES('Wordsworth went on a walking tour') } sqlite3_db_config db DEFENSIVE 0 write_test 10.1.4 ta_content { DELETE FROM ta_content WHERE rowid = 2 } read_test 10.1.5 { SELECT * FROM ta WHERE ta MATCH 'summer' } {{During a summer vacation in 1790}} error_test 10.1.6 { SELECT * FROM ta WHERE ta MATCH 'walking' } {database disk image is malformed} |
︙ | ︙ |
Changes to test/e_reindex.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # EVIDENCE-OF: R-52173-44778 The REINDEX command is used to delete and # recreate indices from scratch. # # Test this by corrupting some database indexes, running REINDEX, and # observing that the corruption is gone. # do_execsql_test e_reindex-1.1 { INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); CREATE TABLE saved(a,b,c,d,e); INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index'; PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE type = 'index'; } {} db close sqlite3 db test.db do_execsql_test e_reindex-1.2 { DELETE FROM t1 WHERE a = 3; INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); PRAGMA writable_schema = 1; INSERT INTO sqlite_master SELECT * FROM saved; DROP TABLE saved; | > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | # EVIDENCE-OF: R-52173-44778 The REINDEX command is used to delete and # recreate indices from scratch. # # Test this by corrupting some database indexes, running REINDEX, and # observing that the corruption is gone. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test e_reindex-1.1 { INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); CREATE TABLE saved(a,b,c,d,e); INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index'; PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE type = 'index'; } {} db close sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 do_execsql_test e_reindex-1.2 { DELETE FROM t1 WHERE a = 3; INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); PRAGMA writable_schema = 1; INSERT INTO sqlite_master SELECT * FROM saved; DROP TABLE saved; |
︙ | ︙ |
Changes to test/fts3auto.test.
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 | return [expr $nRow*$pgsz] } # fts3_zero_long_segments TABLE ?LIMIT? # proc fts3_zero_long_segments {tbl limit} { execsql " UPDATE ${tbl}_segments SET block = zeroblob(length(block)) WHERE length(block)>$limit " return [db changes] } | > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | return [expr $nRow*$pgsz] } # fts3_zero_long_segments TABLE ?LIMIT? # proc fts3_zero_long_segments {tbl limit} { sqlite3_db_config db DEFENSIVE 0 execsql " UPDATE ${tbl}_segments SET block = zeroblob(length(block)) WHERE length(block)>$limit " return [db changes] } |
︙ | ︙ |
Changes to test/fts3corrupt.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | set ::testprefix fts3corrupt # Test that a doclist with a length field that indicates that the doclist # extends past the end of the node on which it resides is correctly identified # as database corruption. # do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts3; INSERT INTO t1 VALUES('hello'); } {} do_test fts3corrupt-1.1 { set blob [db one {SELECT root from t1_segdir}] set blob [binary format a7ca* $blob 24 [string range $blob 8 end]] | > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | set ::testprefix fts3corrupt # Test that a doclist with a length field that indicates that the doclist # extends past the end of the node on which it resides is correctly identified # as database corruption. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts3; INSERT INTO t1 VALUES('hello'); } {} do_test fts3corrupt-1.1 { set blob [db one {SELECT root from t1_segdir}] set blob [binary format a7ca* $blob 24 [string range $blob 8 end]] |
︙ | ︙ |
Changes to test/fts3corrupt2.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | "ayjafsraz addjj agsj asejtziqws acatvhegu aoxdjqblsvv aekdmmbs aaobe" "abjjvzubkwt alczv ati awz auyxgcxeb aymjoym anqoukprtyt atwfhpmbooh" "ajfqz aethlgir aclcx aowlyvetby aproqm afjlqtkv anebfy akzrcpfrrvw" "aoledfotm aiwlfm aeejlaej anz abgbvk aktfn aayoh anpywgdvgz" "acvmldguld asdvz aqb aeomsyzyu aggylhprbdz asrfkwz auipybpsn agsnszzfb" } do_test fts3corrupt2-1.0 { execsql BEGIN execsql { CREATE VIRTUAL TABLE t2 USING FTS3(a, b); } execsql { INSERT INTO t2(t2) VALUES('nodesize=32') } foreach d $data { execsql { INSERT INTO t2 VALUES($d, $d) } } | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | "ayjafsraz addjj agsj asejtziqws acatvhegu aoxdjqblsvv aekdmmbs aaobe" "abjjvzubkwt alczv ati awz auyxgcxeb aymjoym anqoukprtyt atwfhpmbooh" "ajfqz aethlgir aclcx aowlyvetby aproqm afjlqtkv anebfy akzrcpfrrvw" "aoledfotm aiwlfm aeejlaej anz abgbvk aktfn aayoh anpywgdvgz" "acvmldguld asdvz aqb aeomsyzyu aggylhprbdz asrfkwz auipybpsn agsnszzfb" } sqlite3_db_config db DEFENSIVE 0 do_test fts3corrupt2-1.0 { execsql BEGIN execsql { CREATE VIRTUAL TABLE t2 USING FTS3(a, b); } execsql { INSERT INTO t2(t2) VALUES('nodesize=32') } foreach d $data { execsql { INSERT INTO t2 VALUES($d, $d) } } |
︙ | ︙ |
Changes to test/fts3corrupt3.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | INSERT INTO t1 VALUES('one'); INSERT INTO t1 VALUES('one'); COMMIT; } do_execsql_test 1.1 { SELECT quote(root) from t1_segdir; } {X'00036F6E6509010200010200010200'} do_execsql_test 1.2 { UPDATE t1_segdir SET root = X'00036F6E650EFFFFFFFFFFFFFFFFFFFFFFFF0200'; } do_catchsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'one' } {0 -1} | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | INSERT INTO t1 VALUES('one'); INSERT INTO t1 VALUES('one'); COMMIT; } do_execsql_test 1.1 { SELECT quote(root) from t1_segdir; } {X'00036F6E6509010200010200010200'} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2 { UPDATE t1_segdir SET root = X'00036F6E650EFFFFFFFFFFFFFFFFFFFFFFFF0200'; } do_catchsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'one' } {0 -1} |
︙ | ︙ |
Changes to test/fts3corrupt4.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | proc blob {a} { binary decode hex $a } db func blob blob do_execsql_test 1.1 { SELECT quote(root) FROM ft_segdir; } {X'0005616261636B03010200030266740302020003046E646F6E03030200'} do_execsql_test 1.2 { UPDATE ft_segdir SET root = blob( '0005616261636B03010200 FFFFFFFF0702 66740302020003046E646F6E03030200' ); } do_catchsql_test 1.3 { | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | proc blob {a} { binary decode hex $a } db func blob blob do_execsql_test 1.1 { SELECT quote(root) FROM ft_segdir; } {X'0005616261636B03010200030266740302020003046E646F6E03030200'} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2 { UPDATE ft_segdir SET root = blob( '0005616261636B03010200 FFFFFFFF0702 66740302020003046E646F6E03030200' ); } do_catchsql_test 1.3 { |
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 | } {12 3} do_execsql_test 2.2 { SELECT quote(block) FROM ft_segments WHERE blockid=2 } {X'00056162633130031F0200'} db func blob blob do_execsql_test 2.3.1 { UPDATE ft_segments SET block = blob('00056162633130031F0200 FFFFFFFF07FF55 66740302020003046E646F6E03030200') WHERE blockid=2; } {} do_catchsql_test 2.3.2 { INSERT INTO ft(ft) VALUES('merge=1,4'); | > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | } {12 3} do_execsql_test 2.2 { SELECT quote(block) FROM ft_segments WHERE blockid=2 } {X'00056162633130031F0200'} db func blob blob sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.3.1 { UPDATE ft_segments SET block = blob('00056162633130031F0200 FFFFFFFF07FF55 66740302020003046E646F6E03030200') WHERE blockid=2; } {} do_catchsql_test 2.3.2 { INSERT INTO ft(ft) VALUES('merge=1,4'); |
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | } {1 5} do_execsql_test 3.1 { SELECT quote(root) FROM ft_segdir } {X'0101056162633132040136030132030136'} db func blob blob do_execsql_test 3.2 { UPDATE ft_segdir SET root = blob('0101056162633132FFFFFFFF070236030132030136'); } do_catchsql_test 3.1 { SELECT * FROM ft WHERE ft MATCH 'abc20' } {1 {database disk image is malformed}} finish_test | > < < | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | } {1 5} do_execsql_test 3.1 { SELECT quote(root) FROM ft_segdir } {X'0101056162633132040136030132030136'} db func blob blob sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { UPDATE ft_segdir SET root = blob('0101056162633132FFFFFFFF070236030132030136'); } do_catchsql_test 3.1 { SELECT * FROM ft WHERE ft MATCH 'abc20' } {1 {database disk image is malformed}} finish_test |
Changes to test/fts3cov.test.
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | execsql { INSERT INTO t1(t1) VALUES('optimize'); SELECT substr(hex(root), 1, 2) FROM t1_segdir; } } {03} # Test the "missing entry" case: do_test fts3cov-2.2 { set root [db one {SELECT root FROM t1_segdir}] read_fts3varint [string range $root 1 end] left_child execsql { DELETE FROM t1_segments WHERE blockid = $left_child } } {} do_error_test fts3cov-2.3 { SELECT * FROM t1 WHERE t1 MATCH 'c*' | > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | execsql { INSERT INTO t1(t1) VALUES('optimize'); SELECT substr(hex(root), 1, 2) FROM t1_segdir; } } {03} # Test the "missing entry" case: sqlite3_db_config db DEFENSIVE 0 do_test fts3cov-2.2 { set root [db one {SELECT root FROM t1_segdir}] read_fts3varint [string range $root 1 end] left_child execsql { DELETE FROM t1_segments WHERE blockid = $left_child } } {} do_error_test fts3cov-2.3 { SELECT * FROM t1 WHERE t1 MATCH 'c*' |
︙ | ︙ | |||
401 402 403 404 405 406 407 408 409 410 411 412 413 414 | } do_execsql_test 15.1 { SELECT rowid FROM t15 WHERE t15 MATCH '"abc* def2"' } {1 2} # Test a corruption case. # do_execsql_test 16.1 { CREATE VIRTUAL TABLE t16 USING fts4; INSERT INTO t16 VALUES('theoretical work to examine the relationship'); INSERT INTO t16 VALUES('solution of our problems on the invisible'); DELETE FROM t16_content WHERE rowid = 2; } do_catchsql_test 16.2 { | > | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | } do_execsql_test 15.1 { SELECT rowid FROM t15 WHERE t15 MATCH '"abc* def2"' } {1 2} # Test a corruption case. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test 16.1 { CREATE VIRTUAL TABLE t16 USING fts4; INSERT INTO t16 VALUES('theoretical work to examine the relationship'); INSERT INTO t16 VALUES('solution of our problems on the invisible'); DELETE FROM t16_content WHERE rowid = 2; } do_catchsql_test 16.2 { |
︙ | ︙ |
Changes to test/fts3d.test.
︙ | ︙ | |||
292 293 294 295 296 297 298 299 300 301 302 303 304 305 | execsql { SELECT OPTIMIZE(t1) FROM t1 LIMIT 1; SELECT level, idx FROM t1_segdir ORDER BY level, idx; } } {{Index already optimal} 1 0} # Even if we move things around, still does nothing. do_test fts3d-5.1 { execsql { UPDATE t1_segdir SET level = 2 WHERE level = 1 AND idx = 0; SELECT OPTIMIZE(t1) FROM t1 LIMIT 1; SELECT level, idx FROM t1_segdir ORDER BY level, idx; } } {{Index already optimal} 2 0} | > | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | execsql { SELECT OPTIMIZE(t1) FROM t1 LIMIT 1; SELECT level, idx FROM t1_segdir ORDER BY level, idx; } } {{Index already optimal} 1 0} # Even if we move things around, still does nothing. sqlite3_db_config db DEFENSIVE 0 do_test fts3d-5.1 { execsql { UPDATE t1_segdir SET level = 2 WHERE level = 1 AND idx = 0; SELECT OPTIMIZE(t1) FROM t1 LIMIT 1; SELECT level, idx FROM t1_segdir ORDER BY level, idx; } } {{Index already optimal} 2 0} |
︙ | ︙ |
Changes to test/fts3defer.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 4 {SELECT snippet(t1) FROM t1 WHERE t1 MATCH '"a longer phrase"'} {"an instance of <b>a</b> <b>longer</b> <b>phrase</b>"} 5 {SELECT rowid FROM t1 WHERE t1 MATCH 'a dog'} {1} } do_select_tests 1.2 $tests do_execsql_test 1.3 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } {1} | > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 4 {SELECT snippet(t1) FROM t1 WHERE t1 MATCH '"a longer phrase"'} {"an instance of <b>a</b> <b>longer</b> <b>phrase</b>"} 5 {SELECT rowid FROM t1 WHERE t1 MATCH 'a dog'} {1} } do_select_tests 1.2 $tests sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.3 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } {1} |
︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } } 3 { set dmt_modes {0 1 2} execsql { CREATE VIRTUAL TABLE t1 USING FTS4 } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 execsql $zero_long_doclists } 4 { set dmt_modes 0 execsql { CREATE VIRTUAL TABLE t1 USING FTS4 } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 execsql "INSERT INTO t1(t1) VALUES('optimize')" execsql $zero_long_doclists } 5 { set dmt_modes 0 execsql { CREATE VIRTUAL TABLE t1 USING FTS4(matchinfo=fts3) } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 execsql $zero_long_doclists } } { execsql { DROP TABLE IF EXISTS t1 } eval $setup set ::testprefix fts3defer-2.$tn | > > > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } } 3 { set dmt_modes {0 1 2} execsql { CREATE VIRTUAL TABLE t1 USING FTS4 } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } 4 { set dmt_modes 0 execsql { CREATE VIRTUAL TABLE t1 USING FTS4 } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 execsql "INSERT INTO t1(t1) VALUES('optimize')" sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } 5 { set dmt_modes 0 execsql { CREATE VIRTUAL TABLE t1 USING FTS4(matchinfo=fts3) } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } } { execsql { DROP TABLE IF EXISTS t1 } eval $setup set ::testprefix fts3defer-2.$tn |
︙ | ︙ |
Changes to test/fts3defer2.test.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1(t1) VALUES('optimize'); } do_execsql_test 1.1.4 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } {2} do_execsql_test 1.2.0 { SELECT content FROM t1 WHERE t1 MATCH 'f (e a)'; | > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(''); INSERT INTO t1(t1) VALUES('optimize'); } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.1.4 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } {2} do_execsql_test 1.2.0 { SELECT content FROM t1 WHERE t1 MATCH 'f (e a)'; |
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | foreach {tn sql} { 1 {} 2 { INSERT INTO t2(t2) VALUES('optimize') } 3 { UPDATE t2_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } { execsql $sql do_execsql_test 2.2.$tn.1 { SELECT mit(matchinfo(t2, 'pcxnal')) FROM t2 WHERE t2 MATCH 'a b'; } [list \ [list 2 1 1 54 54 1 3 3 54 372 8] \ [list 2 1 1 54 54 1 3 3 54 372 7] \ | > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | foreach {tn sql} { 1 {} 2 { INSERT INTO t2(t2) VALUES('optimize') } 3 { UPDATE t2_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } { sqlite3_db_config db DEFENSIVE 0 execsql $sql do_execsql_test 2.2.$tn.1 { SELECT mit(matchinfo(t2, 'pcxnal')) FROM t2 WHERE t2 MATCH 'a b'; } [list \ [list 2 1 1 54 54 1 3 3 54 372 8] \ [list 2 1 1 54 54 1 3 3 54 372 7] \ |
︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | foreach {tn sql} { 1 {} 2 { INSERT INTO t3(t3) VALUES('optimize') } 3 { UPDATE t3_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } { execsql $sql do_execsql_test 2.4.$tn { SELECT docid, mit(matchinfo(t3, 'pcxnal')) FROM t3 WHERE t3 MATCH '"a b c"'; } {1 {1 1 1 4 4 11 912 6} 3 {1 1 1 4 4 11 912 6}} } finish_test | > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | foreach {tn sql} { 1 {} 2 { INSERT INTO t3(t3) VALUES('optimize') } 3 { UPDATE t3_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } { sqlite3_db_config db DEFENSIVE 0 execsql $sql do_execsql_test 2.4.$tn { SELECT docid, mit(matchinfo(t3, 'pcxnal')) FROM t3 WHERE t3 MATCH '"a b c"'; } {1 {1 1 1 4 4 11 912 6} 3 {1 1 1 4 4 11 912 6}} } finish_test |
Changes to test/fts3matchinfo.test.
︙ | ︙ | |||
274 275 276 277 278 279 280 281 282 283 284 285 286 287 | do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} } do_matchinfo_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} } do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') } ifcapable fts4_deferred { do_execsql_test 4.4.0.2 { UPDATE t5_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } | > | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} } do_matchinfo_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} } do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') } ifcapable fts4_deferred { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.4.0.2 { UPDATE t5_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; } } |
︙ | ︙ | |||
335 336 337 338 339 340 341 342 343 344 345 346 347 348 | CREATE VIRTUAL TABLE t9 USING fts4; INSERT INTO t9 VALUES( 'this record is used to try to dectect corruption' ); SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; } {{0 0 20 2 0 0 27 2}} do_catchsql_test 6.2 { UPDATE t9_content SET c0content = 'this record is used to'; SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; } {1 {database disk image is malformed}} #------------------------------------------------------------------------- # Test the outcome of matchinfo() when used within a query that does not | > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | CREATE VIRTUAL TABLE t9 USING fts4; INSERT INTO t9 VALUES( 'this record is used to try to dectect corruption' ); SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; } {{0 0 20 2 0 0 27 2}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 6.2 { UPDATE t9_content SET c0content = 'this record is used to'; SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; } {1 {database disk image is malformed}} #------------------------------------------------------------------------- # Test the outcome of matchinfo() when used within a query that does not |
︙ | ︙ | |||
388 389 390 391 392 393 394 395 396 397 398 399 400 401 | execsql { INSERT INTO t11(t11) VALUES('optimize') } } {} do_execsql_test 8.3 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {{204 1 3 3 0} {204 1 3 3 0} {204 1 3 3 0}} # Corruption related tests. do_execsql_test 8.4.1.1 { UPDATE t11_stat SET value = X'0000'; } do_catchsql_test 8.5.1.2 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} do_execsql_test 8.4.2.1 { UPDATE t11_stat SET value = X'00'; } do_catchsql_test 8.5.2.2 { | > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | execsql { INSERT INTO t11(t11) VALUES('optimize') } } {} do_execsql_test 8.3 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {{204 1 3 3 0} {204 1 3 3 0} {204 1 3 3 0}} # Corruption related tests. sqlite3_db_config db DEFENSIVE 0 do_execsql_test 8.4.1.1 { UPDATE t11_stat SET value = X'0000'; } do_catchsql_test 8.5.1.2 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} do_execsql_test 8.4.2.1 { UPDATE t11_stat SET value = X'00'; } do_catchsql_test 8.5.2.2 { |
︙ | ︙ |
Changes to test/fts3misc.test.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 165 166 167 168 169 | } do_execsql_test 4.1 { SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' } {8000} do_execsql_test 4.2 { SELECT quote(value) from t4_stat where id=0 } {X'C03EC0B204C0A608'} do_execsql_test 4.3 { UPDATE t4_stat SET value = X'C03EC0B204C0A60800' WHERE id=0; } do_catchsql_test 4.4 { SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' } {1 {database disk image is malformed}} do_execsql_test 4.5 { | > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | } do_execsql_test 4.1 { SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' } {8000} do_execsql_test 4.2 { SELECT quote(value) from t4_stat where id=0 } {X'C03EC0B204C0A608'} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.3 { UPDATE t4_stat SET value = X'C03EC0B204C0A60800' WHERE id=0; } do_catchsql_test 4.4 { SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' } {1 {database disk image is malformed}} do_execsql_test 4.5 { |
︙ | ︙ |
Changes to test/fts3query.test.
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 | illegal first argument to %s } { 1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo 2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'" offsets 3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'" snippet 4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'" optimize } do_execsql_test 5.4.0 { UPDATE t2_content SET c0content = X'1234' } do_select_tests 5.4 -errorformat { illegal first argument to %s } { 1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo 2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'" offsets 3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'" snippet | > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | illegal first argument to %s } { 1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo 2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'" offsets 3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'" snippet 4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'" optimize } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 5.4.0 { UPDATE t2_content SET c0content = X'1234' } do_select_tests 5.4 -errorformat { illegal first argument to %s } { 1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo 2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'" offsets 3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'" snippet |
︙ | ︙ |
Changes to test/fts3snippet.test.
︙ | ︙ | |||
180 181 182 183 184 185 186 187 188 189 190 191 192 193 | do_offsets_test $T.2.1 {twohundred} [list 1 0 $off 10] set off [string first "onehundred " $numbers] do_offsets_test $T.2.2 {onehundred} \ [list 0 0 $off 10 1 0 $off 10] [list 0 0 $off 10] # Test a corruption case: execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers } do_error_test $T.2.3 { SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred' } {database disk image is malformed} ########################################################################## # Test the snippet function. | > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | do_offsets_test $T.2.1 {twohundred} [list 1 0 $off 10] set off [string first "onehundred " $numbers] do_offsets_test $T.2.2 {onehundred} \ [list 0 0 $off 10 1 0 $off 10] [list 0 0 $off 10] # Test a corruption case: sqlite3_db_config db DEFENSIVE 0 execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers } do_error_test $T.2.3 { SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred' } {database disk image is malformed} ########################################################################## # Test the snippet function. |
︙ | ︙ |
Changes to test/fts4check.test.
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | } 3 { DELETE FROM t1_segdir WHERE level=0 AND idx=( SELECT max(idx) FROM t1_segdir WHERE level=0 ); } } { do_execsql_test 1.2.1.$tn "BEGIN; $disruption" do_catchsql_test 1.2.2.$tn { INSERT INTO t1 (t1) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 1.2.3.$tn "ROLLBACK" } | > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | } 3 { DELETE FROM t1_segdir WHERE level=0 AND idx=( SELECT max(idx) FROM t1_segdir WHERE level=0 ); } } { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2.1.$tn "BEGIN; $disruption" do_catchsql_test 1.2.2.$tn { INSERT INTO t1 (t1) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 1.2.3.$tn "ROLLBACK" } |
︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | } 3 { DELETE FROM t2_segdir WHERE level=0 AND idx=( SELECT max(idx) FROM t2_segdir WHERE level=1024 ); } } { do_execsql_test 2.2.1.$tn "BEGIN; $disruption" do_catchsql_test 2.2.2.$tn { INSERT INTO t2 (t2) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 2.2.3.$tn "ROLLBACK" } | > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | } 3 { DELETE FROM t2_segdir WHERE level=0 AND idx=( SELECT max(idx) FROM t2_segdir WHERE level=1024 ); } } { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.2.1.$tn "BEGIN; $disruption" do_catchsql_test 2.2.2.$tn { INSERT INTO t2 (t2) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 2.2.3.$tn "ROLLBACK" } |
︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | } 2 { UPDATE t3_content SET langid=langid+1 WHERE rowid = ( SELECT max(rowid) FROM t3_content ) } } { do_execsql_test 3.2.1.$tn "BEGIN; $disruption" do_catchsql_test 3.2.2.$tn { INSERT INTO t3 (t3) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 3.2.3.$tn "ROLLBACK" } #-------------------------------------------------------------------------- # Test case 4.* # # Test that the integrity-check works if there are "notindexed" columns. # do_execsql_test 4.0 { CREATE VIRTUAL TABLE t4 USING fts4(a, b, c, notindexed=b); INSERT INTO t4 VALUES('text one', 'text two', 'text three'); INSERT INTO t4(t4) VALUES('integrity-check'); } do_execsql_test 4.1 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE VIRTUAL TABLE t4 USING fts4(a, b, c)' WHERE name = 't4'; } | > > | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | } 2 { UPDATE t3_content SET langid=langid+1 WHERE rowid = ( SELECT max(rowid) FROM t3_content ) } } { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2.1.$tn "BEGIN; $disruption" do_catchsql_test 3.2.2.$tn { INSERT INTO t3 (t3) VALUES('integrity-check') } {1 {database disk image is malformed}} do_execsql_test 3.2.3.$tn "ROLLBACK" } #-------------------------------------------------------------------------- # Test case 4.* # # Test that the integrity-check works if there are "notindexed" columns. # do_execsql_test 4.0 { CREATE VIRTUAL TABLE t4 USING fts4(a, b, c, notindexed=b); INSERT INTO t4 VALUES('text one', 'text two', 'text three'); INSERT INTO t4(t4) VALUES('integrity-check'); } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.1 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE VIRTUAL TABLE t4 USING fts4(a, b, c)' WHERE name = 't4'; } |
︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | INSERT INTO t5 VALUES('and the stockmen tell the story of his ride'); } do_execsql_test 5.1 { INSERT INTO t5(t5) VALUES('integrity-check'); } {} do_catchsql_test 5.2 { INSERT INTO t5_content VALUES(5, 'his hardy mountain pony'); INSERT INTO t5(t5) VALUES('integrity-check'); } {1 {database disk image is malformed}} do_execsql_test 5.3 ROLLBACK do_execsql_test 5.4 { CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3"); INSERT INTO t5(t5) VALUES('integrity-check'); } {} finish_test | > | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | INSERT INTO t5 VALUES('and the stockmen tell the story of his ride'); } do_execsql_test 5.1 { INSERT INTO t5(t5) VALUES('integrity-check'); } {} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 5.2 { INSERT INTO t5_content VALUES(5, 'his hardy mountain pony'); INSERT INTO t5(t5) VALUES('integrity-check'); } {1 {database disk image is malformed}} do_execsql_test 5.3 ROLLBACK do_execsql_test 5.4 { CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3"); INSERT INTO t5(t5) VALUES('integrity-check'); } {} finish_test |
Changes to test/fts4growth.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ifcapable !fts3 { finish_test return } source $testdir/genesis.tcl do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; } do_test 1.2 { foreach L { {"See here, young man," said Mulga Bill, "from Walgett to the sea,} {From Conroy's Gap to Castlereagh, there's none can ride like me.} {I'm good all round at everything as everybody knows,} | > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ifcapable !fts3 { finish_test return } source $testdir/genesis.tcl sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; } do_test 1.2 { foreach L { {"See here, young man," said Mulga Bill, "from Walgett to the sea,} {From Conroy's Gap to Castlereagh, there's none can ride like me.} {I'm good all round at everything as everybody knows,} |
︙ | ︙ |
Changes to test/fts4merge.test.
︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | } $expect } do_execsql_test 4.4.1 { SELECT quote(value) FROM t4_stat WHERE rowid=1 } {X'0006'} do_execsql_test 4.4.2 { DELETE FROM t4_stat WHERE rowid=1; INSERT INTO t4(t4) VALUES('merge=1,12'); SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level; } "0 {0 1 2 3 4 5} 1 0" | > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | } $expect } do_execsql_test 4.4.1 { SELECT quote(value) FROM t4_stat WHERE rowid=1 } {X'0006'} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.4.2 { DELETE FROM t4_stat WHERE rowid=1; INSERT INTO t4(t4) VALUES('merge=1,12'); SELECT level, group_concat(idx, ' ') FROM t4_segdir GROUP BY level; } "0 {0 1 2 3 4 5} 1 0" |
︙ | ︙ |
Changes to test/fts4opt.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | # Argument $db is an open database handle. $tbl is the name of an FTS3/4 # table with the database. This command rearranges the contents of the # %_segdir table so that all segments within each index are on the same # level. This means that the 'merge' command can then be used for an # incremental optimize routine. # proc prepare_for_optimize {db tbl} { $db eval [string map [list % $tbl] { BEGIN; CREATE TEMP TABLE tmp_segdir( level, idx, start_block, leaves_end_block, end_block, root ); INSERT INTO temp.tmp_segdir | > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # Argument $db is an open database handle. $tbl is the name of an FTS3/4 # table with the database. This command rearranges the contents of the # %_segdir table so that all segments within each index are on the same # level. This means that the 'merge' command can then be used for an # incremental optimize routine. # proc prepare_for_optimize {db tbl} { sqlite3_db_config $db DEFENSIVE 0 $db eval [string map [list % $tbl] { BEGIN; CREATE TEMP TABLE tmp_segdir( level, idx, start_block, leaves_end_block, end_block, root ); INSERT INTO temp.tmp_segdir |
︙ | ︙ |
Changes to test/fuzzdata7.db.
cannot compute difference between binary files
Changes to test/index.test.
︙ | ︙ | |||
622 623 624 625 626 627 628 | # tested somewhere. do_test index-18.1 { catchsql { CREATE TABLE sqlite_t1(a, b, c); } } {1 {object name reserved for internal use: sqlite_t1}} do_test index-18.1.2 { | < | 622 623 624 625 626 627 628 629 630 631 632 633 634 635 | # tested somewhere. do_test index-18.1 { catchsql { CREATE TABLE sqlite_t1(a, b, c); } } {1 {object name reserved for internal use: sqlite_t1}} do_test index-18.1.2 { catchsql { CREATE TABLE sqlite_t1(a, b, c); } } {1 {object name reserved for internal use: sqlite_t1}} sqlite3_db_config db DEFENSIVE 0 do_test index-18.2 { catchsql { |
︙ | ︙ |
Changes to test/index3.test.
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 | # This test corrupts the database file so it must be the last test # in the series. # do_test index3-99.1 { execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='t1d' } db close catch { sqlite3 db test.db } catchsql { DROP INDEX t1c } | > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | # This test corrupts the database file so it must be the last test # in the series. # do_test index3-99.1 { sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='t1d' } db close catch { sqlite3 db test.db } catchsql { DROP INDEX t1c } |
︙ | ︙ |
Changes to test/loadext.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | # set dlerror_nosuchfile \ {%s: cannot open shared object file: No such file or directory} set dlerror_notadll {%s: file too short} set dlerror_nosymbol {%s: undefined symbol: %s} if {$::tcl_platform(os) eq "Darwin"} { | | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # set dlerror_nosuchfile \ {%s: cannot open shared object file: No such file or directory} set dlerror_notadll {%s: file too short} set dlerror_nosymbol {%s: undefined symbol: %s} if {$::tcl_platform(os) eq "Darwin"} { set dlerror_nosuchfile {dlopen.%s, 10.: .*image.*found.*} set dlerror_notadll {dlopen.%1$s, 10.: .*image.*found.*} set dlerror_nosymbol {dlsym.XXX, %2$s.: symbol not found} } if {$::tcl_platform(platform) eq "windows"} { set dlerror_nosuchfile {The specified module could not be found.*} set dlerror_notadll {%%1 is not a valid Win32 application.*} set dlerror_nosymbol {The specified procedure could not be found.*} } |
︙ | ︙ |
Changes to test/misc1.test.
︙ | ︙ | |||
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 | SELECT ""+3 FROM (SELECT ""+5); } {3} # 2015-04-19: NULL pointer dereference on a corrupt schema # db close sqlite3 db :memory: do_execsql_test misc1-23.1 { CREATE TABLE t1(x); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; DROP TABLE IF EXISTS t3; } {} # 2015-04-19: Faulty assert() statement # db close database_may_be_corrupt sqlite3 db :memory: do_catchsql_test misc1-23.2 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)'; BEGIN; CREATE TABLE t2(x); ROLLBACK; DROP TABLE F; } {1 {no such table: F}} db close sqlite3 db :memory: do_catchsql_test misc1-23.3 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; | > > > | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | SELECT ""+3 FROM (SELECT ""+5); } {3} # 2015-04-19: NULL pointer dereference on a corrupt schema # db close sqlite3 db :memory: sqlite3_db_config db DEFENSIVE 0 do_execsql_test misc1-23.1 { CREATE TABLE t1(x); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; DROP TABLE IF EXISTS t3; } {} # 2015-04-19: Faulty assert() statement # db close database_may_be_corrupt sqlite3 db :memory: sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc1-23.2 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)'; BEGIN; CREATE TABLE t2(x); ROLLBACK; DROP TABLE F; } {1 {no such table: F}} db close sqlite3 db :memory: sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc1-23.3 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; |
︙ | ︙ |
Changes to test/misc4.test.
︙ | ︙ | |||
208 209 210 211 212 213 214 215 216 217 218 219 220 221 | } } {1} # 2015-05-15. Error message formatting problem. # db close sqlite3 db :memory: do_catchsql_test misc4-7.1 { CREATE TABLE t7(x); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE [M%s%s%s%s%s%s%s%s%s%s%s%s%s'; VACUUM; } {1 {unrecognized token: "[M%s%s%s%s%s%s%s%s%s%s%s%s%s"}} | > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | } } {1} # 2015-05-15. Error message formatting problem. # db close sqlite3 db :memory: sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc4-7.1 { CREATE TABLE t7(x); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE [M%s%s%s%s%s%s%s%s%s%s%s%s%s'; VACUUM; } {1 {unrecognized token: "[M%s%s%s%s%s%s%s%s%s%s%s%s%s"}} |
︙ | ︙ |
Changes to test/misc5.test.
︙ | ︙ | |||
586 587 588 589 590 591 592 593 594 595 596 597 598 599 | } {1 {parser stack overflow}} # Parser stack overflow is silently ignored when it occurs while parsing the # schema and PRAGMA writable_schema is turned on. # do_test misc5-7.2 { sqlite3 db2 :memory: catchsql { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; | > | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | } {1 {parser stack overflow}} # Parser stack overflow is silently ignored when it occurs while parsing the # schema and PRAGMA writable_schema is turned on. # do_test misc5-7.2 { sqlite3 db2 :memory: sqlite3_db_config db2 DEFENSIVE 0 catchsql { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)'; BEGIN; CREATE TABLE t2(y); ROLLBACK; |
︙ | ︙ |
Changes to test/misc7.test.
︙ | ︙ | |||
430 431 432 433 434 435 436 437 438 439 440 441 442 443 | } } {0 32} # sqlite3_test_control_pending_page [expr ($::sqlite_pending_byte / 1024) + 1] set ::pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1] sqlite3_test_control_pending_byte $::sqlite_pending_byte do_test misc7-17.3 { db eval { pragma writable_schema = true; UPDATE sqlite_master SET rootpage = $pending_byte_page WHERE type = 'table' AND name = 't3'; } execsql { | > | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | } } {0 32} # sqlite3_test_control_pending_page [expr ($::sqlite_pending_byte / 1024) + 1] set ::pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1] sqlite3_test_control_pending_byte $::sqlite_pending_byte do_test misc7-17.3 { sqlite3_db_config db DEFENSIVE 0 db eval { pragma writable_schema = true; UPDATE sqlite_master SET rootpage = $pending_byte_page WHERE type = 'table' AND name = 't3'; } execsql { |
︙ | ︙ |
Changes to test/mjournal.test.
︙ | ︙ | |||
156 157 158 159 160 161 162 | BEGIN; INSERT INTO t1 VALUES(1); INSERT INTO t4 VALUES(1); COMMIT; } {0} finish_test | < | 156 157 158 159 160 161 162 | BEGIN; INSERT INTO t1 VALUES(1); INSERT INTO t4 VALUES(1); COMMIT; } {0} finish_test |
Changes to test/notnull.test.
︙ | ︙ | |||
602 603 604 605 606 607 608 | do_uses_op_next_test notnull-6.7 "SELECT * FROM t7 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.8 "SELECT * FROM t8 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.9 "SELECT * FROM t8 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.10 "SELECT * FROM t8 WHERE a IS ?" 0 finish_test | < | 602 603 604 605 606 607 608 | do_uses_op_next_test notnull-6.7 "SELECT * FROM t7 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.8 "SELECT * FROM t8 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.9 "SELECT * FROM t8 WHERE a IS ?" 0 do_uses_op_next_test notnull-6.10 "SELECT * FROM t8 WHERE a IS ?" 0 finish_test |
Changes to test/pager1.test.
︙ | ︙ | |||
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 | INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; } } {} do_test pager1-18.2 { set root [db one "SELECT rootpage FROM sqlite_master"] set lockingpage [expr (0x10000/1024) + 1] execsql { PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $lockingpage; } sqlite3 db2 test.db catchsql { SELECT count(*) FROM t1 } db2 } {1 {database disk image is malformed}} | > | 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 | INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; } } {} do_test pager1-18.2 { set root [db one "SELECT rootpage FROM sqlite_master"] set lockingpage [expr (0x10000/1024) + 1] sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $lockingpage; } sqlite3 db2 test.db catchsql { SELECT count(*) FROM t1 } db2 } {1 {database disk image is malformed}} |
︙ | ︙ | |||
1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 | hexio_write test.db [expr ($pgno-1)*1024] 90000000 sqlite3 db2 test.db catchsql { SELECT length(x||'') FROM t2 } db2 } {1 {database disk image is malformed}} db2 close do_test pager1-18.5 { sqlite3 db "" execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; PRAGMA writable_schema = 0; ALTER TABLE t1 RENAME TO x1; | > | 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 | hexio_write test.db [expr ($pgno-1)*1024] 90000000 sqlite3 db2 test.db catchsql { SELECT length(x||'') FROM t2 } db2 } {1 {database disk image is malformed}} db2 close do_test pager1-18.5 { sqlite3 db "" sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; PRAGMA writable_schema = 0; ALTER TABLE t1 RENAME TO x1; |
︙ | ︙ |
Changes to test/parser1.test.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | } {1 {syntax error after column name "b"}} # Verify that a legacy schema in the sqlite_master file is allowed to have # COLLATE, ASC, and DESC keywords on the id list of a FK constraint, and that # those keywords are silently ignored. # do_execsql_test parser1-1.2 { CREATE TABLE t1( a TEXT PRIMARY KEY, b TEXT, FOREIGN KEY(b) REFERENCES t1(a) ); INSERT INTO t1 VALUES('abc',NULL),('xyz','abc'); | > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | } {1 {syntax error after column name "b"}} # Verify that a legacy schema in the sqlite_master file is allowed to have # COLLATE, ASC, and DESC keywords on the id list of a FK constraint, and that # those keywords are silently ignored. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test parser1-1.2 { CREATE TABLE t1( a TEXT PRIMARY KEY, b TEXT, FOREIGN KEY(b) REFERENCES t1(a) ); INSERT INTO t1 VALUES('abc',NULL),('xyz','abc'); |
︙ | ︙ |
Changes to test/pragma.test.
︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 | db eval {PRAGMA integrity_check} } {ok} } # Verify that PRAGMA integrity_check catches UNIQUE and NOT NULL # constraint violations. # do_execsql_test pragma-3.20 { CREATE TABLE t1(a,b); CREATE INDEX t1a ON t1(a); INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(2,4),(NULL,5),(NULL,6); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE UNIQUE INDEX t1a ON t1(a)' WHERE name='t1a'; | > | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | db eval {PRAGMA integrity_check} } {ok} } # Verify that PRAGMA integrity_check catches UNIQUE and NOT NULL # constraint violations. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test pragma-3.20 { CREATE TABLE t1(a,b); CREATE INDEX t1a ON t1(a); INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(2,4),(NULL,5),(NULL,6); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE UNIQUE INDEX t1a ON t1(a)' WHERE name='t1a'; |
︙ | ︙ |
Changes to test/resetdb.test.
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 | PRAGMA page_count; } db2 } {210 6000 ok delete 8} do_test 200 { # Thoroughly corrupt the database file by overwriting the first # page with randomness. catchsql { UPDATE sqlite_dbpage SET data=randomblob(4096) WHERE pgno=1; PRAGMA quick_check; } } {1 {unsupported file format}} do_test 201 { catchsql { | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | PRAGMA page_count; } db2 } {210 6000 ok delete 8} do_test 200 { # Thoroughly corrupt the database file by overwriting the first # page with randomness. sqlite3_db_config db DEFENSIVE 0 catchsql { UPDATE sqlite_dbpage SET data=randomblob(4096) WHERE pgno=1; PRAGMA quick_check; } } {1 {unsupported file format}} do_test 201 { catchsql { |
︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 130 131 132 133 134 | PRAGMA journal_mode; PRAGMA page_size; PRAGMA page_count; } db2 } {210 26000 ok wal 8192 12} # Corrupt the database again do_catchsql_test 320 { UPDATE sqlite_dbpage SET data=randomblob(8192) WHERE pgno=1; PRAGMA quick_check } {1 {file is not a database}} do_test 330 { catchsql { | > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | PRAGMA journal_mode; PRAGMA page_size; PRAGMA page_count; } db2 } {210 26000 ok wal 8192 12} # Corrupt the database again sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 320 { UPDATE sqlite_dbpage SET data=randomblob(8192) WHERE pgno=1; PRAGMA quick_check } {1 {file is not a database}} do_test 330 { catchsql { |
︙ | ︙ | |||
224 225 226 227 228 229 230 231 232 233 234 235 236 237 | } {19 ok} if {[nonzero_reserved_bytes]} { finish_test return } do_execsql_test 710 { UPDATE sqlite_dbpage SET data= X'53514C69746520666F726D61742033000200030100402020000000000000001300000000000000000000000300000004000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000D00000003017C0001D801AC017C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E03061715110145696E6465787431626374310443524541544520494E4445582074316263204F4E20743128622C63292A0206171311013F696E64657874316174310343524541544520494E44455820743161204F4E20743128612926010617111101397461626C657431743102435245415445205441424C4520743128612C622C6329' WHERE pgno=1; } do_execsql_test 720 { PRAGMA integrity_check; | > | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | } {19 ok} if {[nonzero_reserved_bytes]} { finish_test return } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 710 { UPDATE sqlite_dbpage SET data= X'53514C69746520666F726D61742033000200030100402020000000000000001300000000000000000000000300000004000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000D00000003017C0001D801AC017C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E03061715110145696E6465787431626374310443524541544520494E4445582074316263204F4E20743128622C63292A0206171311013F696E64657874316174310343524541544520494E44455820743161204F4E20743128612926010617111101397461626C657431743102435245415445205441424C4520743128612C622C6329' WHERE pgno=1; } do_execsql_test 720 { PRAGMA integrity_check; |
︙ | ︙ |
Changes to test/reuse1.test.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 | 7 { DROP INDEX i1 } 8 { DROP TABLE t1 } 9 { DROP TRIGGER tr1 } 10 { ANALYZE } } { do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | 7 { DROP INDEX i1 } 8 { DROP TABLE t1 } 9 { DROP TRIGGER tr1 } 10 { ANALYZE } } { do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}} } #------------------------------------------------------------------------- # reset_db forcedelete test.db2 ifcapable fts5 { do_execsql_test 2.0 { CREATE VIRTUAL TABLE ft USING fts5(a); INSERT INTO ft VALUES('one'), ('two'), ('three'); ATTACH 'test.db2' AS aux; CREATE VIRTUAL TABLE aux.ft USING fts5(a); INSERT INTO aux.ft VALUES('aux1'), ('aux2'), ('aux3'); } db close sqlite3 db test.db -reuse-schema 1 do_execsql_test 2.1 { ATTACH 'test.db2' AS aux; SELECT * FROM main.ft; } {one two three} do_execsql_test 2.2 { SELECT * FROM aux.ft; } {aux1 aux2 aux3} do_execsql_test 2.2 { SELECT * FROM aux.ft_content; } {1 aux1 2 aux2 3 aux3} } #------------------------------------------------------------------------- # reset_db forcedelete test.db2 do_execsql_test 3.0 { CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE VIEW v1 AS SELECT * FROM t1; CREATE TRIGGER v1_ins INSTEAD OF INSERT ON v1 BEGIN INSERT INTO t1 VALUES(new.a, new.b, new.c); END; CREATE TRIGGER v1_del INSTEAD OF DELETE ON v1 BEGIN DELETE FROM t1 WHERE a=old.a; END; CREATE TRIGGER v1_up INSTEAD OF UPDATE ON v1 BEGIN UPDATE t1 SET a=new.a, b=new.b, c=new.c WHERE a=old.a; END; } forcecopy test.db test.db2 do_test 3.1 { sqlite3 db2 test.db2 execsql { INSERT INTO t1 VALUES(1, 2, 3) } db execsql { INSERT INTO t1 VALUES(4, 5, 6) } db2 db2 close execsql { ATTACH 'test.db2' AS aux; } } {} do_execsql_test 3.2 { SELECT * FROM main.v1; } {1 2 3} do_execsql_test 3.3 { SELECT * FROM aux.v1; } {4 5 6} db close sqlite3 db test.db -reuse-schema 1 do_execsql_test 3.4 { ATTACH 'test.db2' AS aux } {} do_execsql_test 3.5 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.6 { SELECT * FROM aux.v1 } {4 5 6} do_execsql_test 3.7.1 { INSERT INTO aux.t1 VALUES(8, 9, 10); } do_execsql_test 3.7.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.7.3 { SELECT * FROM aux.v1 } {4 5 6 8 9 10} do_execsql_test 3.8.1 { DELETE FROM aux.t1 WHERE b=5 } do_execsql_test 3.8.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.8.3 { SELECT * FROM aux.v1 } {8 9 10} do_execsql_test 3.9.1 { UPDATE aux.t1 SET b='abc' } do_execsql_test 3.9.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.9.3 { SELECT * FROM aux.v1 } {8 abc 10} do_execsql_test 3.10.1 { INSERT INTO aux.v1 VALUES(11, 12, 13) } do_execsql_test 3.10.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.10.3 { SELECT * FROM aux.v1 } {8 abc 10 11 12 13} do_execsql_test 3.11.1 { DELETE FROM aux.v1 WHERE b='abc' } do_execsql_test 3.11.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.11.3 { SELECT * FROM aux.v1 } {11 12 13} do_execsql_test 3.12.1 { UPDATE aux.v1 SET b='def' } do_execsql_test 3.12.2 { SELECT * FROM main.v1 } {1 2 3} do_execsql_test 3.12.3 { SELECT * FROM aux.v1 } {11 def 13} do_execsql_test 3.13.1 { CREATE TEMP TRIGGER xyz AFTER INSERT ON aux.t1 BEGIN INSERT INTO v1 VALUES(new.a, new.b, new.c); END; } do_execsql_test 3.13.2 { INSERT INTO aux.v1 VALUES('x', 'y', 'z'); } do_execsql_test 3.13.3 { SELECT * FROM v1; } {1 2 3 x y z} #------------------------------------------------------------------------- # reset_db forcedelete test.db2 do_execsql_test 4.0 { CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE); CREATE TABLE del(a, b, c); CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN INSERT INTO del VALUES(old.a, old.b, old.c); END; } forcecopy test.db test.db2 db close sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux; PRAGMA recursive_triggers = 1; } do_execsql_test 4.1 { INSERT INTO main.t1 VALUES(1, 2, 3); INSERT INTO aux.t1 VALUES(4, 5, 6); } do_execsql_test 4.2.1 { INSERT OR REPLACE INTO aux.t1 VALUES('a', 'b', 6); SELECT * FROM aux.t1; } {a b 6} do_execsql_test 4.2.2 { SELECT * FROM aux.del } {4 5 6} do_execsql_test 4.2.3 { SELECT * FROM main.del } {} do_execsql_test 4.3.1 { INSERT INTO aux.t1 VALUES('x', 'y', 'z'); UPDATE OR REPLACE aux.t1 SET c='z' WHERE a='a'; } {} do_execsql_test 4.3.2 { SELECT * FROM aux.del } {4 5 6 x y z} do_execsql_test 4.3.3 { SELECT * FROM main.del } {} #------------------------------------------------------------------------- # reset_db do_execsql_test 5.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6); ANALYZE; PRAGMA writable_schema = 1; DELETE FROM sqlite_stat1; } db close forcecopy test.db test.db2 sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux } foreach {tn sql} { 1 { CREATE TABLE t3(x) } 2 { DROP TABLE t2 } 3 { CREATE INDEX i2 ON t2(b) } 4 { DROP INDEX i1 } 5 { ALTER TABLE t1 ADD COLUMN d } 6 { ALTER TABLE t1 RENAME TO t3 } 7 { ALTER TABLE t1 RENAME c TO d } } { do_catchsql_test 5.1.$tn $sql {1 {attempt to modify read-only schema}} } do_execsql_test 5.2.1 { ANALYZE aux.t1 } {} do_execsql_test 5.2.2 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}} do_execsql_test 5.2.3 { SELECT * FROM main.sqlite_stat1 } {} do_test 5.3.0 { sqlite3 db2 test.db2 db2 eval { PRAGMA writable_schema = 1; DELETE FROM sqlite_stat1; } } {} do_execsql_test 5.3.1 { SELECT * FROM aux.sqlite_stat1 } {} do_execsql_test 5.3.2 { ANALYZE aux } {} do_execsql_test 5.3.3 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}} do_execsql_test 5.3.4 { SELECT * FROM main.sqlite_stat1 } {} #------------------------------------------------------------------------- # Attempting to run ANALYZE when the required sqlite_statXX functions # are missing is an error (because it would modify the database schema). # reset_db do_execsql_test 5.4 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6); } db close sqlite3 db test.db -reuse-schema 1 foreach {tn sql} { 1 { ANALYZE } 2 { ANALYZE t1 } 3 { ANALYZE i1 } 4 { ANALYZE main } 5 { ANALYZE main.t1 } 6 { ANALYZE main.i1 } } { do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}} } #------------------------------------------------------------------------- # reset_db do_execsql_test 6.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE VIEW v1 AS SELECT * FROM t1; } db close forcecopy test.db test.db2 sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux } do_execsql_test 6.1 { INSERT INTO main.t1(a) VALUES(1), (2), (3); INSERT INTO aux.t1(a) VALUES(4), (5), (6); CREATE TEMP TABLE t2(i,t); INSERT INTO t2 VALUES(2, 'two'), (5, 'five'); } do_execsql_test 6.2 { SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.t1) } {five} do_execsql_test 6.3 { SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.v1) } {five} #------------------------------------------------------------------------- # reset_db do_execsql_test 7.0 { CREATE TABLE p1(a PRIMARY KEY, b); CREATE TABLE p2(a PRIMARY KEY, b); CREATE TABLE c1(x REFERENCES p1 ON UPDATE CASCADE ON DELETE CASCADE); } db close forcecopy test.db test.db2 sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux } do_execsql_test 7.1 { INSERT INTO aux.p1 VALUES(1, 'one'); INSERT INTO aux.p1 VALUES(2, 'two'); PRAGMA foreign_keys = on; } do_execsql_test 7.2 { INSERT INTO aux.c1 VALUES(2); } do_execsql_test 7.3.1 { PRAGMA foreign_keys = off; INSERT INTO main.p2 SELECT * FROM aux.p1; } do_execsql_test 7.3.2 { SELECT * FROM main.p2; } {1 one 2 two} do_execsql_test 7.3.3 { INSERT INTO aux.p2 VALUES(1, 2); } do_execsql_test 7.3.4 { SELECT main.p2.a FROM main.p2, aux.p2; } {1 2} do_execsql_test 7.3.5 { SELECT * FROM main.p2, aux.p2; } {1 one 1 2 2 two 1 2} do_execsql_test 7.4 { SELECT count(*) FROM aux.p2; } {1} finish_test |
Changes to test/shared8.test.
︙ | ︙ | |||
58 59 60 61 62 63 64 65 66 67 68 69 70 71 | INSERT INTO t1 VALUES(4, 4); CREATE VIEW v1 AS SELECT a, roman(b) FROM t1; SELECT * FROM v1; } db1 } {1 i 2 ii 3 iii 4 iv} do_test 1.1 { execsql { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE 1; PRAGMA writable_schema = 0; SELECT * FROM sqlite_master; } db1 } {} | > | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | INSERT INTO t1 VALUES(4, 4); CREATE VIEW v1 AS SELECT a, roman(b) FROM t1; SELECT * FROM v1; } db1 } {1 i 2 ii 3 iii 4 iv} do_test 1.1 { sqlite3_db_config db1 DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE 1; PRAGMA writable_schema = 0; SELECT * FROM sqlite_master; } db1 } {} |
︙ | ︙ |
Changes to test/snapshot2.test.
︙ | ︙ | |||
234 235 236 237 238 239 240 | execsql { INSERT INTO t2 VALUES('jkl') } execsql BEGIN db2 list [catch { sqlite3_snapshot_open_blob db2 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} finish_test | < | 234 235 236 237 238 239 240 | execsql { INSERT INTO t2 VALUES('jkl') } execsql BEGIN db2 list [catch { sqlite3_snapshot_open_blob db2 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} finish_test |
Changes to test/snapshot3.test.
︙ | ︙ | |||
93 94 95 96 97 98 99 | do_test 1.8 { execsql BEGIN db3 list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} finish_test | < | 93 94 95 96 97 98 99 | do_test 1.8 { execsql BEGIN db3 list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} finish_test |
Changes to test/snapshot4.test.
︙ | ︙ | |||
68 69 70 71 72 73 74 | execsql { SELECT count(*) FROM t1 } } {100} finish_test | < | 68 69 70 71 72 73 74 | execsql { SELECT count(*) FROM t1 } } {100} finish_test |
Changes to test/snapshot_up.test.
︙ | ︙ | |||
177 178 179 180 181 182 183 | set ::res } {1 SQLITE_BUSY} sqlite3_snapshot_free $::snap1 sqlite3_snapshot_free $::snap2 finish_test | < | 177 178 179 180 181 182 183 | set ::res } {1 SQLITE_BUSY} sqlite3_snapshot_free $::snap1 sqlite3_snapshot_free $::snap2 finish_test |
Changes to test/swarmvtab3.test.
︙ | ︙ | |||
227 228 229 230 231 232 233 | } db close forcedelete {*}[glob test.db*] forcedelete {*}[glob test_remote.db*] finish_test | < | 227 228 229 230 231 232 233 | } db close forcedelete {*}[glob test.db*] forcedelete {*}[glob test_remote.db*] finish_test |
Changes to test/swarmvtabfault.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | } -body { execsql { SELECT a FROM xyz } } -test { faultsim_test_result {0 {1 2 9}} {1 {sql error: out of memory}} } finish_test | < | 59 60 61 62 63 64 65 | } -body { execsql { SELECT a FROM xyz } } -test { faultsim_test_result {0 {1 2 9}} {1 {sql error: out of memory}} } finish_test |
Changes to test/table.test.
︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 285 | } } {} do_test table-5.2.2 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t0(a,b); CREATE INDEX t ON t0(a); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE'; BEGIN; CREATE TABLE t1(x); | > | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | } } {} do_test table-5.2.2 { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t0(a,b); CREATE INDEX t ON t0(a); PRAGMA writable_schema=ON; UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE'; BEGIN; CREATE TABLE t1(x); |
︙ | ︙ |
Changes to test/trigger7.test.
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 | } } {} # This test corrupts the database file so it must be the last test # in the series. # do_test trigger7-99.1 { execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense'; } db close catch { sqlite3 db test.db } catchsql { DROP TRIGGER t2r5 } | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | } } {} # This test corrupts the database file so it must be the last test # in the series. # do_test trigger7-99.1 { sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense'; } db close catch { sqlite3 db test.db } catchsql { DROP TRIGGER t2r5 } |
︙ | ︙ |
Changes to test/triggerE.test.
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg] } #------------------------------------------------------------------------- # Test that variable references within trigger definitions loaded from # the sqlite_master table are automatically converted to NULL. # do_execsql_test 2.1 { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES('trigger', 'tr1', 't1', 0, 'CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(?1, ?2); END' ); | > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg] } #------------------------------------------------------------------------- # Test that variable references within trigger definitions loaded from # the sqlite_master table are automatically converted to NULL. # sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.1 { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES('trigger', 'tr1', 't1', 0, 'CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(?1, ?2); END' ); |
︙ | ︙ |
Changes to test/unionvtab.test.
︙ | ︙ | |||
451 452 453 454 455 456 457 | } {five six seven eight nine} do_execsql_test 5.4 { SELECT * FROM cc WHERE two LIKE '6' } {six 6} finish_test | < | 451 452 453 454 455 456 457 | } {five six seven eight nine} do_execsql_test 5.4 { SELECT * FROM cc WHERE two LIKE '6' } {six 6} finish_test |
Changes to test/unionvtabfault.test.
︙ | ︙ | |||
77 78 79 80 81 82 83 | } -test { faultsim_test_result {0 {}} {1 {initialization of unionvtab failed: }} } finish_test | < | 77 78 79 80 81 82 83 | } -test { faultsim_test_result {0 {}} {1 {initialization of unionvtab failed: }} } finish_test |
Changes to test/vtab1.test.
︙ | ︙ | |||
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 | # The following test case exposes an instance in sqlite3_declare_vtab() # an error message was set using a call similar to sqlite3_mprintf(zErr), # where zErr is an arbitrary string. This is no good if the string contains # characters that can be mistaken for printf() formatting directives. # do_test vtab1-17.1 { execsql { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES( 'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)' ); } catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); } | > | 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | # The following test case exposes an instance in sqlite3_declare_vtab() # an error message was set using a call similar to sqlite3_mprintf(zErr), # where zErr is an arbitrary string. This is no good if the string contains # characters that can be mistaken for printf() formatting directives. # do_test vtab1-17.1 { sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES( 'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)' ); } catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); } |
︙ | ︙ |
Changes to test/wherelimit2.test.
︙ | ︙ | |||
293 294 295 296 297 298 299 | set ::log {} execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; } set ::log } {ax a bx b cx c dx d ex a} finish_test | < | 293 294 295 296 297 298 299 | set ::log {} execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; } set ::log } {ax a bx b cx c dx d ex a} finish_test |
Changes to test/window5.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | } {1 {sum() may not be used as a window function}} do_execsql_test 3.1 { SELECT sum(a) FROM t1; } {21} finish_test | < | 90 91 92 93 94 95 96 | } {1 {sum() may not be used as a window function}} do_execsql_test 3.1 { SELECT sum(a) FROM t1; } {21} finish_test |
Changes to test/windowfault.test.
︙ | ︙ | |||
159 160 161 162 163 164 165 | ORDER BY a; } } -test { faultsim_test_result {0 {1 2 5 6 9 10}} } finish_test | < | 159 160 161 162 163 164 165 | ORDER BY a; } } -test { faultsim_test_result {0 {1 2 5 6 9 10}} } finish_test |
Changes to test/zipfile.test.
︙ | ︙ | |||
757 758 759 760 761 762 763 764 | SELECT name, data FROM z ORDER BY name; } {b0 two b2 one} do_execsql_test 11.11 { UPDATE z SET name = name || 'suffix'; SELECT name, data FROM z ORDER BY name; } {b0suffix two b2suffix one} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | SELECT name, data FROM z ORDER BY name; } {b0 two b2 one} do_execsql_test 11.11 { UPDATE z SET name = name || 'suffix'; SELECT name, data FROM z ORDER BY name; } {b0suffix two b2suffix one} if {$tcl_platform(platform)!="windows"} { do_test 12.0 { catch { file delete -force subdir } foreach {path sz} { subdir/x1.txt 143 subdir/x2.txt 153 } { set dir [file dirname $path] catch { file mkdir $dir } set fd [open $path w] puts -nonewline $fd [string repeat 1 $sz] close $fd } } {} do_execsql_test 12.1 { SELECT name FROM fsdir('subdir') ORDER BY 1; } {subdir subdir/x1.txt subdir/x2.txt} do_execsql_test 12.2 { CREATE TABLE d AS SELECT 'subdir' d; CREATE TABLE x AS SELECT 1 x; } do_execsql_test 12.4 { SELECT name FROM d JOIN x JOIN fsdir(d) ORDER BY 1; } {subdir subdir/x1.txt subdir/x2.txt} do_execsql_test 12.5 { SELECT name FROM d JOIN x JOIN fsdir('.', d) ORDER BY 1; } {. ./x1.txt ./x2.txt} } finish_test |
Changes to test/zipfile2.test.
︙ | ︙ | |||
237 238 239 240 241 242 243 | INSERT INTO temp.zip (name,data) VALUES ('test1','test'); INSERT INTO temp.zip (name,data) VALUES ('test2','test'); UPDATE OR REPLACE zip SET name='test2' WHERE name='test1'; SELECT name FROM zip; } {test2} finish_test | < | 237 238 239 240 241 242 243 | INSERT INTO temp.zip (name,data) VALUES ('test1','test'); INSERT INTO temp.zip (name,data) VALUES ('test2','test'); UPDATE OR REPLACE zip SET name='test2' WHERE name='test1'; SELECT name FROM zip; } {test2} finish_test |
Changes to tool/genfkey.test.
︙ | ︙ | |||
347 348 349 350 351 352 353 | } {1 {constraint failed}} do_test genfkey-6.7 { execsql { SELECT * FROM parent; SELECT * FROM child; } } {1 1} | < | 347 348 349 350 351 352 353 | } {1 {constraint failed}} do_test genfkey-6.7 { execsql { SELECT * FROM parent; SELECT * FROM child; } } {1 1} |
Changes to tool/sqldiff.c.
︙ | ︙ | |||
1489 1490 1491 1492 1493 1494 1495 | fwrite(p+n+1, 9-n, 1, out); } } /* ** Write an SQLite value onto out. */ | | | | | | | | | | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 | fwrite(p+n+1, 9-n, 1, out); } } /* ** Write an SQLite value onto out. */ static void putValue(FILE *out, sqlite3_stmt *pStmt, int k){ int iDType = sqlite3_column_type(pStmt, k); sqlite3_int64 iX; double rX; sqlite3_uint64 uX; int j; putc(iDType, out); switch( iDType ){ case SQLITE_INTEGER: iX = sqlite3_column_int64(pStmt, k); memcpy(&uX, &iX, 8); for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); break; case SQLITE_FLOAT: rX = sqlite3_column_double(pStmt, k); memcpy(&uX, &rX, 8); for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); break; case SQLITE_TEXT: iX = sqlite3_column_bytes(pStmt, k); putsVarint(out, (sqlite3_uint64)iX); fwrite(sqlite3_column_text(pStmt, k),1,(size_t)iX,out); break; case SQLITE_BLOB: iX = sqlite3_column_bytes(pStmt, k); putsVarint(out, (sqlite3_uint64)iX); fwrite(sqlite3_column_blob(pStmt, k),1,(size_t)iX,out); break; case SQLITE_NULL: break; } } /* |
︙ | ︙ | |||
1646 1647 1648 1649 1650 1651 1652 | int iType = sqlite3_column_int(pStmt,0); putc(iType, out); putc(0, out); switch( sqlite3_column_int(pStmt,0) ){ case SQLITE_UPDATE: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ | | | | | | | | | 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 | int iType = sqlite3_column_int(pStmt,0); putc(iType, out); putc(0, out); switch( sqlite3_column_int(pStmt,0) ){ case SQLITE_UPDATE: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ putValue(out, pStmt, k); k++; }else if( sqlite3_column_int(pStmt,k) ){ putValue(out, pStmt, k+1); k += 3; }else{ putc(0, out); k += 3; } } for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ putc(0, out); k++; }else if( sqlite3_column_int(pStmt,k) ){ putValue(out, pStmt, k+2); k += 3; }else{ putc(0, out); k += 3; } } break; } case SQLITE_INSERT: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ putValue(out, pStmt, k); k++; }else{ putValue(out, pStmt, k+2); k += 3; } } break; } case SQLITE_DELETE: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ putValue(out, pStmt, k); k++; }else{ putValue(out, pStmt, k+1); k += 3; } } break; } } } |
︙ | ︙ |
Changes to tool/warnings.sh.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # Use these for testing on Linux and Mac OSX: WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long" WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra" fi rm -f sqlite3.c make sqlite3.c | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # Use these for testing on Linux and Mac OSX: WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long" WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra" fi rm -f sqlite3.c make sqlite3.c echo '********** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***' echo '********** ' Options: $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c if test x`uname` = 'xLinux'; then echo '********** Android configuration ******************************' echo '********** ' Options: $WARNING_ANDROID_OPTS gcc -c \ -DHAVE_USLEEP=1 \ |
︙ | ︙ | |||
48 49 50 51 52 53 54 | -Os sqlite3.c shell.c fi echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******' echo '********** ' Options: $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ sqlite3.c | | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 | -Os sqlite3.c shell.c fi echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******' echo '********** ' Options: $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ sqlite3.c echo '********** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******' echo '********** ' Options: $WARNING_OPTS gcc -O3 -c $WARNING_OPTS -std=c89 \ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c |