Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge recent trunk changes (such as the query_only PRAGMA, the defer_foreign_keys PRAGMA, and the SQLITE_DBSTATUS_DEFERRED_FKS parameter to sqlite3_db_status()) into the sessions branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
8dfc0b78c38e519b64a796243ff7c0af |
User & Date: | drh 2013-07-11 15:31:57.120 |
Context
2013-08-02
| ||
20:44 | Merge in the latest trunk changes, including partial indexes, the MAX_PATH fix in os_win.c, and the sqlite3_cancel_auto_extension() API. (check-in: 7e1acb3907 user: drh tags: sessions) | |
2013-07-11
| ||
15:31 | Merge recent trunk changes (such as the query_only PRAGMA, the defer_foreign_keys PRAGMA, and the SQLITE_DBSTATUS_DEFERRED_FKS parameter to sqlite3_db_status()) into the sessions branch. (check-in: 8dfc0b78c3 user: drh tags: sessions) | |
15:22 | Add the experimental "query_only" pragma. (check-in: 6557c40798 user: drh tags: trunk) | |
13:49 | Remove the undocumented sqlite3_foreign_key_check() API and replace it with sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, ...). Add test cases for the new functionality. (check-in: d39e65fe70 user: drh tags: sessions) | |
Changes
Changes to ext/misc/spellfix.c.
︙ | ︙ | |||
2144 2145 2146 2147 2148 2149 2150 | pIdxInfo->aConstraintUsage[iScopeTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iScopeTerm].omit = 1; } if( iPlan&(16|32) ){ pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iDistTerm].omit = 1; } | | | | 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 | pIdxInfo->aConstraintUsage[iScopeTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iScopeTerm].omit = 1; } if( iPlan&(16|32) ){ pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iDistTerm].omit = 1; } pIdxInfo->estimatedCost = 1e5; }else{ pIdxInfo->idxNum = 0; pIdxInfo->estimatedCost = 1e50; } return SQLITE_OK; } /* ** Open a new fuzzy-search cursor. */ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1296 1297 1298 1299 1300 1301 1302 | int nOps, int (*xProgress)(void*), void *pArg ){ sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; | | | 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 | int nOps, int (*xProgress)(void*), void *pArg ){ sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; db->nProgressOps = (unsigned)nOps; db->pProgressArg = pArg; }else{ db->xProgress = 0; db->nProgressOps = 0; db->pProgressArg = 0; } sqlite3_mutex_leave(db->mutex); |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 | { "short_column_names", SQLITE_ShortColNames }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, { "legacy_file_format", SQLITE_LegacyFileFmt }, { "fullfsync", SQLITE_FullFSync }, { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, { "reverse_unordered_selects", SQLITE_ReverseOrder }, #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, | > | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | { "short_column_names", SQLITE_ShortColNames }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, { "legacy_file_format", SQLITE_LegacyFileFmt }, { "fullfsync", SQLITE_FullFSync }, { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, { "reverse_unordered_selects", SQLITE_ReverseOrder }, { "query_only", SQLITE_QueryOnly }, #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
940 941 942 943 944 945 946 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ | | | 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ unsigned nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nVTrans; /* Allocated size of aVTrans */ Hash aModule; /* populated by sqlite3_create_module() */ VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ VTable **aVTrans; /* Virtual tables with open transactions */ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ |
︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | #define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ #define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ | > > | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 | #define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ #define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x01000000 /* Disable database changes */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
558 559 560 561 562 563 564 565 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | > > < | < < | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK unsigned nProgressOps = 0; /* nVmStep at last progress callback. */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ |
︙ | ︙ | |||
592 593 594 595 596 597 598 | assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); | < < < | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ int i; printf("VDBE Program Listing:\n"); sqlite3VdbePrintSql(p); for(i=0; i<p->nOp; i++){ |
︙ | ︙ | |||
640 641 642 643 644 645 646 | #ifdef SQLITE_TEST if( sqlite3_interrupt_count>0 ){ sqlite3_interrupt_count--; if( sqlite3_interrupt_count==0 ){ sqlite3_interrupt(db); } } | < < < < < < < < < < < < < < < < < < < < < | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | #ifdef SQLITE_TEST if( sqlite3_interrupt_count>0 ){ sqlite3_interrupt_count--; if( sqlite3_interrupt_count==0 ){ sqlite3_interrupt(db); } } #endif /* On any opcode with the "out2-prerelease" tag, free any ** external allocations out of mem[p2] and set mem[p2] to be ** an undefined integer. Opcodes will either fill in the integer ** value or convert mem[p2] to a different type. */ |
︙ | ︙ | |||
755 756 757 758 759 760 761 762 | ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { /* jump */ CHECK_FOR_INTERRUPT; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 | ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { /* jump */ pc = pOp->p2 - 1; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon ** completion. Check to see if sqlite3_interrupt() has been called ** or if the progress callback needs to be invoked. ** ** This code uses unstructured "goto" statements and does not look clean. ** But that is not due to sloppy coding habits. The code is written this ** way for performance, to avoid having to run the interrupt and progress ** checks on every opcode. This helps sqlite3_step() to run about 1.5% ** faster according to "valgrind --tool=cachegrind" */ check_for_interrupt: CHECK_FOR_INTERRUPT; #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Call the progress callback if it is configured and the required number ** of VDBE ops have been executed (either since this invocation of ** sqlite3VdbeExec() or since last time the progress callback was called). ** If the progress callback returns non-zero, exit the virtual machine with ** a return code SQLITE_ABORT. */ if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){ int prc; prc = db->xProgress(db->pProgressArg); if( prc!=0 ){ rc = SQLITE_INTERRUPT; goto vdbe_error_halt; } nProgressOps = nVmStep; } #endif break; } /* Opcode: Gosub P1 P2 * * * ** ** Write the current address onto register P1 ** and then jump to address P2. |
︙ | ︙ | |||
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 | case OP_Transaction: { Btree *pBt; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; | > > > > | 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 | case OP_Transaction: { Btree *pBt; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ rc = SQLITE_READONLY; goto abort_due_to_error; } pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; |
︙ | ︙ | |||
4553 4554 4555 4556 4557 4558 4559 | */ case OP_SorterNext: /* jump */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ VdbeCursor *pC; int res; | < | 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 | */ case OP_SorterNext: /* jump */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ VdbeCursor *pC; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p5<=ArraySize(p->aCounter) ); pC = p->apCsr[pOp->p1]; if( pC==0 ){ break; /* See ticket #2273 */ } assert( pC->isSorter==(pOp->opcode==OP_SorterNext) ); |
︙ | ︙ | |||
4582 4583 4584 4585 4586 4587 4588 | pc = pOp->p2 - 1; if( pOp->p5 ) p->aCounter[pOp->p5-1]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif } pC->rowidIsValid = 0; | | | 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 | pc = pOp->p2 - 1; if( pOp->p5 ) p->aCounter[pOp->p5-1]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif } pC->rowidIsValid = 0; goto check_for_interrupt; } /* Opcode: IdxInsert P1 P2 P3 * P5 ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. |
︙ | ︙ | |||
5108 5109 5110 5111 5112 5113 5114 | ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; | | | | 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 | ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0 || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); pc = pOp->p2 - 1; }else{ /* A value was pulled from the index */ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); } goto check_for_interrupt; } /* Opcode: RowSetTest P1 P2 P3 P4 ** ** Register P3 is assumed to hold a 64-bit integer value. If register P1 ** contains a RowSet object and that RowSet object contains ** the value held in P3, jump to register P2. Otherwise, insert the |
︙ | ︙ | |||
6023 6024 6025 6026 6027 6028 6029 | res = pModule->xEof(pCur->pVtabCursor); } if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } | | | 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 | res = pModule->xEof(pCur->pVtabCursor); } if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } goto check_for_interrupt; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VRename P1 * * P4 * ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. |
︙ | ︙ |
Changes to test/progress.test.
︙ | ︙ | |||
162 163 164 165 166 167 168 | INSERT INTO abc VALUES(4, 5, 6); INSERT INTO abc VALUES(7, 8, 9); } set ::res [list] db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | INSERT INTO abc VALUES(4, 5, 6); INSERT INTO abc VALUES(7, 8, 9); } set ::res [list] db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c db progress 5 "expr 1" catch {db eval {SELECT a, b, c FROM abc} { }} msg lappend ::res $msg } set ::res } {1 2 3 interrupted 4 5 6 interrupted 7 8 9 interrupted} |
︙ | ︙ |
Added test/queryonly.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 | # 2013-07-11 # # 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 implements regression tests for SQLite library. # # This file tests the "query_only" pragma. # set testdir [file dirname $argv0] source $testdir/tester.tcl do_execsql_test queryonly-1.1 { CREATE TABLE t1(a); INSERT INTO t1 VALUES(123),(456); SELECT a FROM t1 ORDER BY a; } {123 456} do_execsql_test queryonly-1.2 { PRAGMA query_only; } {0} do_execsql_test queryonly-1.3 { PRAGMA query_only=ON; PRAGMA query_only; } {1} do_test queryonly-1.4 { catchsql {INSERT INTO t1 VALUES(789);} } {1 {attempt to write a readonly database}} do_test queryonly-1.5 { catchsql {DELETE FROM t1;} } {1 {attempt to write a readonly database}} do_test queryonly-1.6 { catchsql {UPDATE t1 SET a=a+1;} } {1 {attempt to write a readonly database}} do_test queryonly-1.7 { catchsql {CREATE TABLE t2(b);} } {1 {attempt to write a readonly database}} do_test queryonly-1.8 { catchsql {CREATE INDEX t1a ON t1(a);} } {1 {attempt to write a readonly database}} do_test queryonly-1.9 { catchsql {DROP TABLE t1;} } {1 {attempt to write a readonly database}} do_test queryonly-1.10 { catchsql {ANALYZE;} } {1 {attempt to write a readonly database}} do_execsql_test queryonly-1.11 { SELECT a FROM t1 ORDER BY a; } {123 456} do_execsql_test queryonly-2.2 { PRAGMA query_only; } {1} do_execsql_test queryonly-2.3 { PRAGMA query_only=OFF; PRAGMA query_only; } {0} do_execsql_test queryonly-2.4 { INSERT INTO t1 VALUES(789); SELECT a FROM t1 ORDER BY a; } {123 456 789} do_execsql_test queryonly-2.5 { UPDATE t1 SET a=a+1; SELECT a FROM t1 ORDER BY a; } {124 457 790} finish_test |