| | @@ -1171,11 +1171,11 @@ |
| 1171 | 1171 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1172 | 1172 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1173 | 1173 | */ |
| 1174 | 1174 | #define SQLITE_VERSION "3.34.0" |
| 1175 | 1175 | #define SQLITE_VERSION_NUMBER 3034000 |
| 1176 | | -#define SQLITE_SOURCE_ID "2020-09-17 21:11:25 4542d194e2fef5e21e1c3679914bd9e21fab31cfb111cf640524fb3514a8afa3" |
| 1176 | +#define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5" |
| 1177 | 1177 | |
| 1178 | 1178 | /* |
| 1179 | 1179 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1180 | 1180 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1181 | 1181 | ** |
| | @@ -15133,16 +15133,25 @@ |
| 15133 | 15133 | SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); |
| 15134 | 15134 | SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); |
| 15135 | 15135 | SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags); |
| 15136 | 15136 | SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*); |
| 15137 | 15137 | SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); |
| 15138 | + |
| 15138 | 15139 | SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); |
| 15139 | 15140 | SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); |
| 15140 | 15141 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 15141 | 15142 | SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); |
| 15142 | 15143 | #endif |
| 15144 | + |
| 15145 | +/* Savepoints are named, nestable SQL transactions mostly implemented */ |
| 15146 | +/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */ |
| 15143 | 15147 | SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); |
| 15148 | + |
| 15149 | +/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */ |
| 15150 | +#ifndef SQLITE_OMIT_WAL |
| 15151 | +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); |
| 15152 | +#endif |
| 15144 | 15153 | |
| 15145 | 15154 | SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); |
| 15146 | 15155 | SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); |
| 15147 | 15156 | SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); |
| 15148 | 15157 | |
| | @@ -15735,68 +15744,69 @@ |
| 15735 | 15744 | #define OP_SequenceTest 113 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ |
| 15736 | 15745 | #define OP_OpenPseudo 114 /* synopsis: P3 columns in r[P2] */ |
| 15737 | 15746 | #define OP_String8 115 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 15738 | 15747 | #define OP_Close 116 |
| 15739 | 15748 | #define OP_ColumnsUsed 117 |
| 15740 | | -#define OP_SeekHit 118 /* synopsis: set P2<=seekHit<=P3 */ |
| 15741 | | -#define OP_Sequence 119 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 15742 | | -#define OP_NewRowid 120 /* synopsis: r[P2]=rowid */ |
| 15743 | | -#define OP_Insert 121 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 15744 | | -#define OP_Delete 122 |
| 15745 | | -#define OP_ResetCount 123 |
| 15746 | | -#define OP_SorterCompare 124 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 15747 | | -#define OP_SorterData 125 /* synopsis: r[P2]=data */ |
| 15748 | | -#define OP_RowData 126 /* synopsis: r[P2]=data */ |
| 15749 | | -#define OP_Rowid 127 /* synopsis: r[P2]=rowid */ |
| 15750 | | -#define OP_NullRow 128 |
| 15751 | | -#define OP_SeekEnd 129 |
| 15752 | | -#define OP_IdxInsert 130 /* synopsis: key=r[P2] */ |
| 15753 | | -#define OP_SorterInsert 131 /* synopsis: key=r[P2] */ |
| 15754 | | -#define OP_IdxDelete 132 /* synopsis: key=r[P2@P3] */ |
| 15755 | | -#define OP_DeferredSeek 133 /* synopsis: Move P3 to P1.rowid if needed */ |
| 15756 | | -#define OP_IdxRowid 134 /* synopsis: r[P2]=rowid */ |
| 15757 | | -#define OP_FinishSeek 135 |
| 15758 | | -#define OP_Destroy 136 |
| 15759 | | -#define OP_Clear 137 |
| 15760 | | -#define OP_ResetSorter 138 |
| 15761 | | -#define OP_CreateBtree 139 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ |
| 15762 | | -#define OP_SqlExec 140 |
| 15763 | | -#define OP_ParseSchema 141 |
| 15764 | | -#define OP_LoadAnalysis 142 |
| 15765 | | -#define OP_DropTable 143 |
| 15766 | | -#define OP_DropIndex 144 |
| 15767 | | -#define OP_DropTrigger 145 |
| 15768 | | -#define OP_IntegrityCk 146 |
| 15769 | | -#define OP_RowSetAdd 147 /* synopsis: rowset(P1)=r[P2] */ |
| 15770 | | -#define OP_Param 148 |
| 15771 | | -#define OP_FkCounter 149 /* synopsis: fkctr[P1]+=P2 */ |
| 15749 | +#define OP_SeekScan 118 /* synopsis: Scan-ahead up to P1 rows */ |
| 15750 | +#define OP_SeekHit 119 /* synopsis: set P2<=seekHit<=P3 */ |
| 15751 | +#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 15752 | +#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */ |
| 15753 | +#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 15754 | +#define OP_Delete 123 |
| 15755 | +#define OP_ResetCount 124 |
| 15756 | +#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 15757 | +#define OP_SorterData 126 /* synopsis: r[P2]=data */ |
| 15758 | +#define OP_RowData 127 /* synopsis: r[P2]=data */ |
| 15759 | +#define OP_Rowid 128 /* synopsis: r[P2]=rowid */ |
| 15760 | +#define OP_NullRow 129 |
| 15761 | +#define OP_SeekEnd 130 |
| 15762 | +#define OP_IdxInsert 131 /* synopsis: key=r[P2] */ |
| 15763 | +#define OP_SorterInsert 132 /* synopsis: key=r[P2] */ |
| 15764 | +#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */ |
| 15765 | +#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */ |
| 15766 | +#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */ |
| 15767 | +#define OP_FinishSeek 136 |
| 15768 | +#define OP_Destroy 137 |
| 15769 | +#define OP_Clear 138 |
| 15770 | +#define OP_ResetSorter 139 |
| 15771 | +#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ |
| 15772 | +#define OP_SqlExec 141 |
| 15773 | +#define OP_ParseSchema 142 |
| 15774 | +#define OP_LoadAnalysis 143 |
| 15775 | +#define OP_DropTable 144 |
| 15776 | +#define OP_DropIndex 145 |
| 15777 | +#define OP_DropTrigger 146 |
| 15778 | +#define OP_IntegrityCk 147 |
| 15779 | +#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */ |
| 15780 | +#define OP_Param 149 |
| 15772 | 15781 | #define OP_Real 150 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 15773 | | -#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 15774 | | -#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ |
| 15775 | | -#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ |
| 15776 | | -#define OP_AggStep 154 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 15777 | | -#define OP_AggStep1 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 15778 | | -#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */ |
| 15779 | | -#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */ |
| 15780 | | -#define OP_Expire 158 |
| 15781 | | -#define OP_CursorLock 159 |
| 15782 | | -#define OP_CursorUnlock 160 |
| 15783 | | -#define OP_TableLock 161 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 15784 | | -#define OP_VBegin 162 |
| 15785 | | -#define OP_VCreate 163 |
| 15786 | | -#define OP_VDestroy 164 |
| 15787 | | -#define OP_VOpen 165 |
| 15788 | | -#define OP_VColumn 166 /* synopsis: r[P3]=vcolumn(P2) */ |
| 15789 | | -#define OP_VRename 167 |
| 15790 | | -#define OP_Pagecount 168 |
| 15791 | | -#define OP_MaxPgcnt 169 |
| 15792 | | -#define OP_Trace 170 |
| 15793 | | -#define OP_CursorHint 171 |
| 15794 | | -#define OP_ReleaseReg 172 /* synopsis: release r[P1@P2] mask P3 */ |
| 15795 | | -#define OP_Noop 173 |
| 15796 | | -#define OP_Explain 174 |
| 15797 | | -#define OP_Abortable 175 |
| 15782 | +#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */ |
| 15783 | +#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 15784 | +#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ |
| 15785 | +#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ |
| 15786 | +#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 15787 | +#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 15788 | +#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */ |
| 15789 | +#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */ |
| 15790 | +#define OP_Expire 159 |
| 15791 | +#define OP_CursorLock 160 |
| 15792 | +#define OP_CursorUnlock 161 |
| 15793 | +#define OP_TableLock 162 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 15794 | +#define OP_VBegin 163 |
| 15795 | +#define OP_VCreate 164 |
| 15796 | +#define OP_VDestroy 165 |
| 15797 | +#define OP_VOpen 166 |
| 15798 | +#define OP_VColumn 167 /* synopsis: r[P3]=vcolumn(P2) */ |
| 15799 | +#define OP_VRename 168 |
| 15800 | +#define OP_Pagecount 169 |
| 15801 | +#define OP_MaxPgcnt 170 |
| 15802 | +#define OP_Trace 171 |
| 15803 | +#define OP_CursorHint 172 |
| 15804 | +#define OP_ReleaseReg 173 /* synopsis: release r[P1@P2] mask P3 */ |
| 15805 | +#define OP_Noop 174 |
| 15806 | +#define OP_Explain 175 |
| 15807 | +#define OP_Abortable 176 |
| 15798 | 15808 | |
| 15799 | 15809 | /* Properties such as "out2" or "jump" that are specified in |
| 15800 | 15810 | ** comments following the "case" for each opcode in the vdbe.c |
| 15801 | 15811 | ** are encoded into bitvectors as follows: |
| 15802 | 15812 | */ |
| | @@ -15819,19 +15829,19 @@ |
| 15819 | 15829 | /* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ |
| 15820 | 15830 | /* 80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x12,\ |
| 15821 | 15831 | /* 88 */ 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 15822 | 15832 | /* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26,\ |
| 15823 | 15833 | /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ |
| 15824 | | -/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,\ |
| 15825 | | -/* 120 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ |
| 15826 | | -/* 128 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\ |
| 15827 | | -/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ |
| 15828 | | -/* 144 */ 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x10, 0x04,\ |
| 15829 | | -/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15834 | +/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ |
| 15835 | +/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15836 | +/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\ |
| 15837 | +/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\ |
| 15838 | +/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00,\ |
| 15839 | +/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15830 | 15840 | /* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15831 | | -/* 168 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15832 | | -} |
| 15841 | +/* 168 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 15842 | +/* 176 */ 0x00,} |
| 15833 | 15843 | |
| 15834 | 15844 | /* The sqlite3P2Values() routine is able to run faster if it knows |
| 15835 | 15845 | ** the value of the largest JUMP opcode. The smaller the maximum |
| 15836 | 15846 | ** JUMP opcode the better, so the mkopcodeh.tcl script that |
| 15837 | 15847 | ** generated this include file strives to group all JUMP opcodes |
| | @@ -33339,68 +33349,69 @@ |
| 33339 | 33349 | /* 113 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 33340 | 33350 | /* 114 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 33341 | 33351 | /* 115 */ "String8" OpHelp("r[P2]='P4'"), |
| 33342 | 33352 | /* 116 */ "Close" OpHelp(""), |
| 33343 | 33353 | /* 117 */ "ColumnsUsed" OpHelp(""), |
| 33344 | | - /* 118 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), |
| 33345 | | - /* 119 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 33346 | | - /* 120 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 33347 | | - /* 121 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 33348 | | - /* 122 */ "Delete" OpHelp(""), |
| 33349 | | - /* 123 */ "ResetCount" OpHelp(""), |
| 33350 | | - /* 124 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 33351 | | - /* 125 */ "SorterData" OpHelp("r[P2]=data"), |
| 33352 | | - /* 126 */ "RowData" OpHelp("r[P2]=data"), |
| 33353 | | - /* 127 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 33354 | | - /* 128 */ "NullRow" OpHelp(""), |
| 33355 | | - /* 129 */ "SeekEnd" OpHelp(""), |
| 33356 | | - /* 130 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 33357 | | - /* 131 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 33358 | | - /* 132 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 33359 | | - /* 133 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), |
| 33360 | | - /* 134 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 33361 | | - /* 135 */ "FinishSeek" OpHelp(""), |
| 33362 | | - /* 136 */ "Destroy" OpHelp(""), |
| 33363 | | - /* 137 */ "Clear" OpHelp(""), |
| 33364 | | - /* 138 */ "ResetSorter" OpHelp(""), |
| 33365 | | - /* 139 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), |
| 33366 | | - /* 140 */ "SqlExec" OpHelp(""), |
| 33367 | | - /* 141 */ "ParseSchema" OpHelp(""), |
| 33368 | | - /* 142 */ "LoadAnalysis" OpHelp(""), |
| 33369 | | - /* 143 */ "DropTable" OpHelp(""), |
| 33370 | | - /* 144 */ "DropIndex" OpHelp(""), |
| 33371 | | - /* 145 */ "DropTrigger" OpHelp(""), |
| 33372 | | - /* 146 */ "IntegrityCk" OpHelp(""), |
| 33373 | | - /* 147 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 33374 | | - /* 148 */ "Param" OpHelp(""), |
| 33375 | | - /* 149 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 33354 | + /* 118 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), |
| 33355 | + /* 119 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), |
| 33356 | + /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 33357 | + /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 33358 | + /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 33359 | + /* 123 */ "Delete" OpHelp(""), |
| 33360 | + /* 124 */ "ResetCount" OpHelp(""), |
| 33361 | + /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 33362 | + /* 126 */ "SorterData" OpHelp("r[P2]=data"), |
| 33363 | + /* 127 */ "RowData" OpHelp("r[P2]=data"), |
| 33364 | + /* 128 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 33365 | + /* 129 */ "NullRow" OpHelp(""), |
| 33366 | + /* 130 */ "SeekEnd" OpHelp(""), |
| 33367 | + /* 131 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 33368 | + /* 132 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 33369 | + /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 33370 | + /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), |
| 33371 | + /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 33372 | + /* 136 */ "FinishSeek" OpHelp(""), |
| 33373 | + /* 137 */ "Destroy" OpHelp(""), |
| 33374 | + /* 138 */ "Clear" OpHelp(""), |
| 33375 | + /* 139 */ "ResetSorter" OpHelp(""), |
| 33376 | + /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), |
| 33377 | + /* 141 */ "SqlExec" OpHelp(""), |
| 33378 | + /* 142 */ "ParseSchema" OpHelp(""), |
| 33379 | + /* 143 */ "LoadAnalysis" OpHelp(""), |
| 33380 | + /* 144 */ "DropTable" OpHelp(""), |
| 33381 | + /* 145 */ "DropIndex" OpHelp(""), |
| 33382 | + /* 146 */ "DropTrigger" OpHelp(""), |
| 33383 | + /* 147 */ "IntegrityCk" OpHelp(""), |
| 33384 | + /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 33385 | + /* 149 */ "Param" OpHelp(""), |
| 33376 | 33386 | /* 150 */ "Real" OpHelp("r[P2]=P4"), |
| 33377 | | - /* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 33378 | | - /* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 33379 | | - /* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), |
| 33380 | | - /* 154 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 33381 | | - /* 155 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 33382 | | - /* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"), |
| 33383 | | - /* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 33384 | | - /* 158 */ "Expire" OpHelp(""), |
| 33385 | | - /* 159 */ "CursorLock" OpHelp(""), |
| 33386 | | - /* 160 */ "CursorUnlock" OpHelp(""), |
| 33387 | | - /* 161 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 33388 | | - /* 162 */ "VBegin" OpHelp(""), |
| 33389 | | - /* 163 */ "VCreate" OpHelp(""), |
| 33390 | | - /* 164 */ "VDestroy" OpHelp(""), |
| 33391 | | - /* 165 */ "VOpen" OpHelp(""), |
| 33392 | | - /* 166 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 33393 | | - /* 167 */ "VRename" OpHelp(""), |
| 33394 | | - /* 168 */ "Pagecount" OpHelp(""), |
| 33395 | | - /* 169 */ "MaxPgcnt" OpHelp(""), |
| 33396 | | - /* 170 */ "Trace" OpHelp(""), |
| 33397 | | - /* 171 */ "CursorHint" OpHelp(""), |
| 33398 | | - /* 172 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), |
| 33399 | | - /* 173 */ "Noop" OpHelp(""), |
| 33400 | | - /* 174 */ "Explain" OpHelp(""), |
| 33401 | | - /* 175 */ "Abortable" OpHelp(""), |
| 33387 | + /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 33388 | + /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 33389 | + /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 33390 | + /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), |
| 33391 | + /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 33392 | + /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 33393 | + /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"), |
| 33394 | + /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 33395 | + /* 159 */ "Expire" OpHelp(""), |
| 33396 | + /* 160 */ "CursorLock" OpHelp(""), |
| 33397 | + /* 161 */ "CursorUnlock" OpHelp(""), |
| 33398 | + /* 162 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 33399 | + /* 163 */ "VBegin" OpHelp(""), |
| 33400 | + /* 164 */ "VCreate" OpHelp(""), |
| 33401 | + /* 165 */ "VDestroy" OpHelp(""), |
| 33402 | + /* 166 */ "VOpen" OpHelp(""), |
| 33403 | + /* 167 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 33404 | + /* 168 */ "VRename" OpHelp(""), |
| 33405 | + /* 169 */ "Pagecount" OpHelp(""), |
| 33406 | + /* 170 */ "MaxPgcnt" OpHelp(""), |
| 33407 | + /* 171 */ "Trace" OpHelp(""), |
| 33408 | + /* 172 */ "CursorHint" OpHelp(""), |
| 33409 | + /* 173 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), |
| 33410 | + /* 174 */ "Noop" OpHelp(""), |
| 33411 | + /* 175 */ "Explain" OpHelp(""), |
| 33412 | + /* 176 */ "Abortable" OpHelp(""), |
| 33402 | 33413 | }; |
| 33403 | 33414 | return azName[i]; |
| 33404 | 33415 | } |
| 33405 | 33416 | #endif |
| 33406 | 33417 | |
| | @@ -70343,11 +70354,11 @@ |
| 70343 | 70354 | } |
| 70344 | 70355 | } |
| 70345 | 70356 | |
| 70346 | 70357 | pPage = pCur->pPage; |
| 70347 | 70358 | idx = ++pCur->ix; |
| 70348 | | - if( !pPage->isInit ){ |
| 70359 | + if( !pPage->isInit || sqlite3FaultSim(412) ){ |
| 70349 | 70360 | /* The only known way for this to happen is for there to be a |
| 70350 | 70361 | ** recursive SQL function that does a DELETE operation as part of a |
| 70351 | 70362 | ** SELECT which deletes content out from under an active cursor |
| 70352 | 70363 | ** in a corrupt database file where the table being DELETE-ed from |
| 70353 | 70364 | ** has pages in common with the table being queried. See TH3 |
| | @@ -89829,10 +89840,147 @@ |
| 89829 | 89840 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 89830 | 89841 | pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ |
| 89831 | 89842 | } |
| 89832 | 89843 | break; |
| 89833 | 89844 | } |
| 89845 | + |
| 89846 | + |
| 89847 | +/* Opcode: SeekScan P1 * * * * |
| 89848 | +** Synopsis: Scan-ahead up to P1 rows |
| 89849 | +** |
| 89850 | +** This opcode is a prefix opcode to OP_SeekGE. In other words, this |
| 89851 | +** opcode must be immediately followed by OP_SeekGE. Furthermore, the |
| 89852 | +** OP_SeekGE must be followed by OP_IdxGT. These constraints are |
| 89853 | +** checked by assert() statements. |
| 89854 | +** |
| 89855 | +** This opcode uses the P1 through P4 operands of the subsequent |
| 89856 | +** OP_SeekGE. In the text that follows, the operands of the subsequent |
| 89857 | +** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only |
| 89858 | +** the P1 operand of this opcode is used, and it is denoted as This.P1. |
| 89859 | +** |
| 89860 | +** This opcode helps to optimize IN operators on a multi-column index |
| 89861 | +** where the IN operator is on the later terms of the index by avoiding |
| 89862 | +** unnecessary seeks on the btree, substituting steps to the next row |
| 89863 | +** of the b-tree instead. A correct answer is obtained if this opcode |
| 89864 | +** is omitted or is a no-op. |
| 89865 | +** |
| 89866 | +** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which |
| 89867 | +** is the desired entry that we want the cursor SeekGE.P1 to be pointing |
| 89868 | +** to. Call this SeekGE.P4/P5 row the "target". |
| 89869 | +** |
| 89870 | +** If the SeekGE.P1 cursor is not currently pointing to a valid row, |
| 89871 | +** then this opcode is a no-op and control passes through into the OP_SeekGE. |
| 89872 | +** |
| 89873 | +** If the SeekGE.P1 cursor is pointing to a valid row, then that row |
| 89874 | +** might be the target row, or it might be near and slightly before the |
| 89875 | +** target row. This opcode attempts to position the cursor on the target |
| 89876 | +** row by, perhaps stepping by invoking sqlite3BtreeStep() on the cursor |
| 89877 | +** between 0 and This.P1 times. |
| 89878 | +** |
| 89879 | +** There are three possible outcomes from this opcode:<ol> |
| 89880 | +** |
| 89881 | +** <li> If after This.P1 steps, the cursor is still point to a place that |
| 89882 | +** is earlier in the btree than the target row, |
| 89883 | +** then fall through into the subsquence OP_SeekGE opcode. |
| 89884 | +** |
| 89885 | +** <li> If the cursor is successfully moved to the target row by 0 or more |
| 89886 | +** sqlite3BtreeNext() calls, then jump to the first instruction after the |
| 89887 | +** OP_IdxGT opcode - or in other words, skip the next two opcodes. |
| 89888 | +** |
| 89889 | +** <li> If the cursor ends up past the target row (indicating the the target |
| 89890 | +** row does not exist in the btree) then jump to SeekOP.P2. |
| 89891 | +** </ol> |
| 89892 | +*/ |
| 89893 | +case OP_SeekScan: { |
| 89894 | + VdbeCursor *pC; |
| 89895 | + int res; |
| 89896 | + int n; |
| 89897 | + UnpackedRecord r; |
| 89898 | + |
| 89899 | + assert( pOp[1].opcode==OP_SeekGE ); |
| 89900 | + assert( pOp[2].opcode==OP_IdxGT ); |
| 89901 | + assert( pOp[1].p1==pOp[2].p1 ); |
| 89902 | + assert( pOp[1].p2==pOp[2].p2 ); |
| 89903 | + assert( pOp[1].p3==pOp[2].p3 ); |
| 89904 | + assert( pOp[1].p4.i==pOp[2].p4.i ); |
| 89905 | + assert( pOp->p1>0 ); |
| 89906 | + pC = p->apCsr[pOp[1].p1]; |
| 89907 | + assert( pC!=0 ); |
| 89908 | + assert( pC->eCurType==CURTYPE_BTREE ); |
| 89909 | + assert( !pC->isTable ); |
| 89910 | + if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){ |
| 89911 | +#ifdef SQLITE_DEBUG |
| 89912 | + if( db->flags&SQLITE_VdbeTrace ){ |
| 89913 | + printf("... cursor not valid - fall through\n"); |
| 89914 | + } |
| 89915 | +#endif |
| 89916 | + break; |
| 89917 | + } |
| 89918 | + n = pOp->p1; |
| 89919 | + assert( n>=1 ); |
| 89920 | + r.pKeyInfo = pC->pKeyInfo; |
| 89921 | + r.nField = (u16)pOp[1].p4.i; |
| 89922 | + r.default_rc = 0; |
| 89923 | + r.aMem = &aMem[pOp[1].p3]; |
| 89924 | +#ifdef SQLITE_DEBUG |
| 89925 | + { |
| 89926 | + int i; |
| 89927 | + for(i=0; i<r.nField; i++){ |
| 89928 | + assert( memIsValid(&r.aMem[i]) ); |
| 89929 | + REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]); |
| 89930 | + } |
| 89931 | + } |
| 89932 | +#endif |
| 89933 | + res = 0; /* Not needed. Only used to silence a warning. */ |
| 89934 | + while(1){ |
| 89935 | + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); |
| 89936 | + if( rc ) goto abort_due_to_error; |
| 89937 | + if( res>0 ){ |
| 89938 | + seekscan_search_fail: |
| 89939 | +#ifdef SQLITE_DEBUG |
| 89940 | + if( db->flags&SQLITE_VdbeTrace ){ |
| 89941 | + printf("... %d steps and then skip\n", pOp->p1 - n); |
| 89942 | + } |
| 89943 | +#endif |
| 89944 | + VdbeBranchTaken(1,3); |
| 89945 | + pOp++; |
| 89946 | + goto jump_to_p2; |
| 89947 | + } |
| 89948 | + if( res==0 ){ |
| 89949 | +#ifdef SQLITE_DEBUG |
| 89950 | + if( db->flags&SQLITE_VdbeTrace ){ |
| 89951 | + printf("... %d steps and then success\n", pOp->p1 - n); |
| 89952 | + } |
| 89953 | +#endif |
| 89954 | + VdbeBranchTaken(2,3); |
| 89955 | + pOp += 2; |
| 89956 | + break; |
| 89957 | + } |
| 89958 | + if( n<=0 ){ |
| 89959 | +#ifdef SQLITE_DEBUG |
| 89960 | + if( db->flags&SQLITE_VdbeTrace ){ |
| 89961 | + printf("... fall through after %d steps\n", pOp->p1); |
| 89962 | + } |
| 89963 | +#endif |
| 89964 | + VdbeBranchTaken(0,3); |
| 89965 | + break; |
| 89966 | + } |
| 89967 | + n--; |
| 89968 | + rc = sqlite3BtreeNext(pC->uc.pCursor, 0); |
| 89969 | + if( rc ){ |
| 89970 | + if( rc==SQLITE_DONE ){ |
| 89971 | + rc = SQLITE_OK; |
| 89972 | + goto seekscan_search_fail; |
| 89973 | + }else{ |
| 89974 | + goto abort_due_to_error; |
| 89975 | + } |
| 89976 | + } |
| 89977 | + } |
| 89978 | + |
| 89979 | + break; |
| 89980 | +} |
| 89981 | + |
| 89834 | 89982 | |
| 89835 | 89983 | /* Opcode: SeekHit P1 P2 P3 * * |
| 89836 | 89984 | ** Synopsis: set P2<=seekHit<=P3 |
| 89837 | 89985 | ** |
| 89838 | 89986 | ** Increase or decrease the seekHit value for cursor P1, if necessary, |
| | @@ -91361,22 +91509,45 @@ |
| 91361 | 91509 | assert( memIsValid(&r.aMem[i]) ); |
| 91362 | 91510 | REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]); |
| 91363 | 91511 | } |
| 91364 | 91512 | } |
| 91365 | 91513 | #endif |
| 91366 | | - res = 0; /* Not needed. Only used to silence a warning. */ |
| 91367 | | - rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); |
| 91514 | + |
| 91515 | + /* Inlined version of sqlite3VdbeIdxKeyCompare() */ |
| 91516 | + { |
| 91517 | + i64 nCellKey = 0; |
| 91518 | + BtCursor *pCur; |
| 91519 | + Mem m; |
| 91520 | + |
| 91521 | + assert( pC->eCurType==CURTYPE_BTREE ); |
| 91522 | + pCur = pC->uc.pCursor; |
| 91523 | + assert( sqlite3BtreeCursorIsValid(pCur) ); |
| 91524 | + nCellKey = sqlite3BtreePayloadSize(pCur); |
| 91525 | + /* nCellKey will always be between 0 and 0xffffffff because of the way |
| 91526 | + ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ |
| 91527 | + if( nCellKey<=0 || nCellKey>0x7fffffff ){ |
| 91528 | + rc = SQLITE_CORRUPT_BKPT; |
| 91529 | + goto abort_due_to_error; |
| 91530 | + } |
| 91531 | + sqlite3VdbeMemInit(&m, db, 0); |
| 91532 | + rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); |
| 91533 | + if( rc ) goto abort_due_to_error; |
| 91534 | + res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0); |
| 91535 | + sqlite3VdbeMemRelease(&m); |
| 91536 | + } |
| 91537 | + /* End of inlined sqlite3VdbeIdxKeyCompare() */ |
| 91538 | + |
| 91368 | 91539 | assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); |
| 91369 | 91540 | if( (pOp->opcode&1)==(OP_IdxLT&1) ){ |
| 91370 | 91541 | assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); |
| 91371 | 91542 | res = -res; |
| 91372 | 91543 | }else{ |
| 91373 | 91544 | assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); |
| 91374 | 91545 | res++; |
| 91375 | 91546 | } |
| 91376 | 91547 | VdbeBranchTaken(res>0,2); |
| 91377 | | - if( rc ) goto abort_due_to_error; |
| 91548 | + assert( rc==SQLITE_OK ); |
| 91378 | 91549 | if( res>0 ) goto jump_to_p2; |
| 91379 | 91550 | break; |
| 91380 | 91551 | } |
| 91381 | 91552 | |
| 91382 | 91553 | /* Opcode: Destroy P1 P2 P3 * * |
| | @@ -132969,12 +133140,11 @@ |
| 132969 | 133140 | pNew = sqlite3ExprDup(db, pCopy, 0); |
| 132970 | 133141 | if( pNew && pSubst->isLeftJoin ){ |
| 132971 | 133142 | ExprSetProperty(pNew, EP_CanBeNull); |
| 132972 | 133143 | } |
| 132973 | 133144 | if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ |
| 132974 | | - pNew->iRightJoinTable = pExpr->iRightJoinTable; |
| 132975 | | - ExprSetProperty(pNew, EP_FromJoin); |
| 133145 | + sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable); |
| 132976 | 133146 | } |
| 132977 | 133147 | sqlite3ExprDelete(db, pExpr); |
| 132978 | 133148 | pExpr = pNew; |
| 132979 | 133149 | |
| 132980 | 133150 | /* Ensure that the expression now has an implicit collation sequence, |
| | @@ -141334,13 +141504,15 @@ |
| 141334 | 141504 | u16 eOperator; /* A WO_xx value describing <op> */ |
| 141335 | 141505 | u8 nChild; /* Number of children that must disable us */ |
| 141336 | 141506 | u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ |
| 141337 | 141507 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ |
| 141338 | 141508 | int leftCursor; /* Cursor number of X in "X <op> <expr>" */ |
| 141339 | | - int iField; /* Field in (?,?,?) IN (SELECT...) vector */ |
| 141340 | 141509 | union { |
| 141341 | | - int leftColumn; /* Column number of X in "X <op> <expr>" */ |
| 141510 | + struct { |
| 141511 | + int leftColumn; /* Column number of X in "X <op> <expr>" */ |
| 141512 | + int iField; /* Field in (?,?,?) IN (SELECT...) vector */ |
| 141513 | + } x; /* Opcode other than OP_OR or OP_AND */ |
| 141342 | 141514 | WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ |
| 141343 | 141515 | WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ |
| 141344 | 141516 | } u; |
| 141345 | 141517 | Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ |
| 141346 | 141518 | Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
| | @@ -141690,10 +141862,11 @@ |
| 141690 | 141862 | #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ |
| 141691 | 141863 | #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ |
| 141692 | 141864 | #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ |
| 141693 | 141865 | #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ |
| 141694 | 141866 | #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ |
| 141867 | +#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ |
| 141695 | 141868 | |
| 141696 | 141869 | #endif /* !defined(SQLITE_WHEREINT_H) */ |
| 141697 | 141870 | |
| 141698 | 141871 | /************** End of whereInt.h ********************************************/ |
| 141699 | 141872 | /************** Continuing where we left off in wherecode.c ******************/ |
| | @@ -142103,11 +142276,11 @@ |
| 142103 | 142276 | int i; /* Loop counter */ |
| 142104 | 142277 | Select *pSelect; /* Pointer to the SELECT on the RHS */ |
| 142105 | 142278 | |
| 142106 | 142279 | for(i=iEq; i<pLoop->nLTerm; i++){ |
| 142107 | 142280 | if( pLoop->aLTerm[i]->pExpr==pX ){ |
| 142108 | | - int iField = pLoop->aLTerm[i]->iField - 1; |
| 142281 | + int iField = pLoop->aLTerm[i]->u.x.iField - 1; |
| 142109 | 142282 | if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */ |
| 142110 | 142283 | pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); |
| 142111 | 142284 | pOrigRhs->a[iField].pExpr = 0; |
| 142112 | 142285 | assert( pOrigLhs->a[iField].pExpr!=0 ); |
| 142113 | 142286 | pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr); |
| | @@ -142246,11 +142419,11 @@ |
| 142246 | 142419 | |
| 142247 | 142420 | pLoop->wsFlags |= WHERE_IN_ABLE; |
| 142248 | 142421 | if( pLevel->u.in.nIn==0 ){ |
| 142249 | 142422 | pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); |
| 142250 | 142423 | } |
| 142251 | | - if( iEq>0 ){ |
| 142424 | + if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){ |
| 142252 | 142425 | pLoop->wsFlags |= WHERE_IN_EARLYOUT; |
| 142253 | 142426 | } |
| 142254 | 142427 | |
| 142255 | 142428 | i = pLevel->u.in.nIn; |
| 142256 | 142429 | pLevel->u.in.nIn += nEq; |
| | @@ -142284,11 +142457,11 @@ |
| 142284 | 142457 | pIn->eEndLoopOp = OP_Noop; |
| 142285 | 142458 | } |
| 142286 | 142459 | pIn++; |
| 142287 | 142460 | } |
| 142288 | 142461 | } |
| 142289 | | - if( iEq>0 ){ |
| 142462 | + if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){ |
| 142290 | 142463 | sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq); |
| 142291 | 142464 | } |
| 142292 | 142465 | }else{ |
| 142293 | 142466 | pLevel->u.in.nIn = 0; |
| 142294 | 142467 | } |
| | @@ -143439,12 +143612,11 @@ |
| 143439 | 143612 | nConstraint = nEq; |
| 143440 | 143613 | if( pRangeStart ){ |
| 143441 | 143614 | Expr *pRight = pRangeStart->pExpr->pRight; |
| 143442 | 143615 | codeExprOrVector(pParse, pRight, regBase+nEq, nBtm); |
| 143443 | 143616 | whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); |
| 143444 | | - if( !bRev |
| 143445 | | - && (pRangeStart->wtFlags & TERM_VNULL)==0 |
| 143617 | + if( (pRangeStart->wtFlags & TERM_VNULL)==0 |
| 143446 | 143618 | && sqlite3ExprCanBeNull(pRight) |
| 143447 | 143619 | ){ |
| 143448 | 143620 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 143449 | 143621 | VdbeCoverage(v); |
| 143450 | 143622 | } |
| | @@ -143480,10 +143652,24 @@ |
| 143480 | 143652 | VdbeComment((v, "NULL-scan pass ctr")); |
| 143481 | 143653 | } |
| 143482 | 143654 | |
| 143483 | 143655 | op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; |
| 143484 | 143656 | assert( op!=0 ); |
| 143657 | + if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){ |
| 143658 | + assert( op==OP_SeekGE ); |
| 143659 | + assert( regBignull==0 ); |
| 143660 | + /* TUNING: The OP_SeekScan opcode seeks to reduce the number |
| 143661 | + ** of expensive seek operations by replacing a single seek with |
| 143662 | + ** 1 or more step operations. The question is, how many steps |
| 143663 | + ** should we try before giving up and going with a seek. The cost |
| 143664 | + ** of a seek is proportional to the logarithm of the of the number |
| 143665 | + ** of entries in the tree, so basing the number of steps to try |
| 143666 | + ** on the estimated number of rows in the btree seems like a good |
| 143667 | + ** guess. */ |
| 143668 | + sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10); |
| 143669 | + VdbeCoverage(v); |
| 143670 | + } |
| 143485 | 143671 | sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); |
| 143486 | 143672 | VdbeCoverage(v); |
| 143487 | 143673 | VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); |
| 143488 | 143674 | VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); |
| 143489 | 143675 | VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); |
| | @@ -143515,12 +143701,11 @@ |
| 143515 | 143701 | nConstraint = nEq; |
| 143516 | 143702 | if( pRangeEnd ){ |
| 143517 | 143703 | Expr *pRight = pRangeEnd->pExpr->pRight; |
| 143518 | 143704 | codeExprOrVector(pParse, pRight, regBase+nEq, nTop); |
| 143519 | 143705 | whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); |
| 143520 | | - if( bRev |
| 143521 | | - && (pRangeEnd->wtFlags & TERM_VNULL)==0 |
| 143706 | + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 |
| 143522 | 143707 | && sqlite3ExprCanBeNull(pRight) |
| 143523 | 143708 | ){ |
| 143524 | 143709 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 143525 | 143710 | VdbeCoverage(v); |
| 143526 | 143711 | } |
| | @@ -143582,11 +143767,11 @@ |
| 143582 | 143767 | testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); |
| 143583 | 143768 | testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); |
| 143584 | 143769 | testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); |
| 143585 | 143770 | } |
| 143586 | 143771 | |
| 143587 | | - if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ |
| 143772 | + if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){ |
| 143588 | 143773 | sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq); |
| 143589 | 143774 | } |
| 143590 | 143775 | |
| 143591 | 143776 | /* Seek the table cursor, if required */ |
| 143592 | 143777 | omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 |
| | @@ -144090,11 +144275,11 @@ |
| 144090 | 144275 | sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); |
| 144091 | 144276 | } |
| 144092 | 144277 | #endif |
| 144093 | 144278 | assert( !ExprHasProperty(pE, EP_FromJoin) ); |
| 144094 | 144279 | assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); |
| 144095 | | - pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady, |
| 144280 | + pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady, |
| 144096 | 144281 | WO_EQ|WO_IN|WO_IS, 0); |
| 144097 | 144282 | if( pAlt==0 ) continue; |
| 144098 | 144283 | if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 144099 | 144284 | if( (pAlt->eOperator & WO_IN) |
| 144100 | 144285 | && (pAlt->pExpr->flags & EP_xIsSelect) |
| | @@ -144946,11 +145131,11 @@ |
| 144946 | 145131 | testcase( pOrTerm->wtFlags & TERM_COPIED ); |
| 144947 | 145132 | testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); |
| 144948 | 145133 | assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); |
| 144949 | 145134 | continue; |
| 144950 | 145135 | } |
| 144951 | | - iColumn = pOrTerm->u.leftColumn; |
| 145136 | + iColumn = pOrTerm->u.x.leftColumn; |
| 144952 | 145137 | iCursor = pOrTerm->leftCursor; |
| 144953 | 145138 | pLeft = pOrTerm->pExpr->pLeft; |
| 144954 | 145139 | break; |
| 144955 | 145140 | } |
| 144956 | 145141 | if( i<0 ){ |
| | @@ -144968,11 +145153,11 @@ |
| 144968 | 145153 | okToChngToIN = 1; |
| 144969 | 145154 | for(; i>=0 && okToChngToIN; i--, pOrTerm++){ |
| 144970 | 145155 | assert( pOrTerm->eOperator & WO_EQ ); |
| 144971 | 145156 | if( pOrTerm->leftCursor!=iCursor ){ |
| 144972 | 145157 | pOrTerm->wtFlags &= ~TERM_OR_OK; |
| 144973 | | - }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR |
| 145158 | + }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR |
| 144974 | 145159 | && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1) |
| 144975 | 145160 | )){ |
| 144976 | 145161 | okToChngToIN = 0; |
| 144977 | 145162 | }else{ |
| 144978 | 145163 | int affLeft, affRight; |
| | @@ -145003,11 +145188,11 @@ |
| 145003 | 145188 | |
| 145004 | 145189 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ |
| 145005 | 145190 | if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; |
| 145006 | 145191 | assert( pOrTerm->eOperator & WO_EQ ); |
| 145007 | 145192 | assert( pOrTerm->leftCursor==iCursor ); |
| 145008 | | - assert( pOrTerm->u.leftColumn==iColumn ); |
| 145193 | + assert( pOrTerm->u.x.leftColumn==iColumn ); |
| 145009 | 145194 | pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); |
| 145010 | 145195 | pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); |
| 145011 | 145196 | pLeft = pOrTerm->pExpr->pLeft; |
| 145012 | 145197 | } |
| 145013 | 145198 | assert( pLeft!=0 ); |
| | @@ -145239,29 +145424,29 @@ |
| 145239 | 145424 | int aiCurCol[2]; |
| 145240 | 145425 | Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); |
| 145241 | 145426 | Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); |
| 145242 | 145427 | u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; |
| 145243 | 145428 | |
| 145244 | | - if( pTerm->iField>0 ){ |
| 145429 | + if( pTerm->u.x.iField>0 ){ |
| 145245 | 145430 | assert( op==TK_IN ); |
| 145246 | 145431 | assert( pLeft->op==TK_VECTOR ); |
| 145247 | | - pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; |
| 145432 | + pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; |
| 145248 | 145433 | } |
| 145249 | 145434 | |
| 145250 | 145435 | if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){ |
| 145251 | 145436 | pTerm->leftCursor = aiCurCol[0]; |
| 145252 | | - pTerm->u.leftColumn = aiCurCol[1]; |
| 145437 | + pTerm->u.x.leftColumn = aiCurCol[1]; |
| 145253 | 145438 | pTerm->eOperator = operatorMask(op) & opMask; |
| 145254 | 145439 | } |
| 145255 | 145440 | if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; |
| 145256 | 145441 | if( pRight |
| 145257 | 145442 | && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op) |
| 145258 | 145443 | ){ |
| 145259 | 145444 | WhereTerm *pNew; |
| 145260 | 145445 | Expr *pDup; |
| 145261 | 145446 | u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ |
| 145262 | | - assert( pTerm->iField==0 ); |
| 145447 | + assert( pTerm->u.x.iField==0 ); |
| 145263 | 145448 | if( pTerm->leftCursor>=0 ){ |
| 145264 | 145449 | int idxNew; |
| 145265 | 145450 | pDup = sqlite3ExprDup(db, pExpr, 0); |
| 145266 | 145451 | if( db->mallocFailed ){ |
| 145267 | 145452 | sqlite3ExprDelete(db, pDup); |
| | @@ -145283,11 +145468,11 @@ |
| 145283 | 145468 | pDup = pExpr; |
| 145284 | 145469 | pNew = pTerm; |
| 145285 | 145470 | } |
| 145286 | 145471 | pNew->wtFlags |= exprCommute(pParse, pDup); |
| 145287 | 145472 | pNew->leftCursor = aiCurCol[0]; |
| 145288 | | - pNew->u.leftColumn = aiCurCol[1]; |
| 145473 | + pNew->u.x.leftColumn = aiCurCol[1]; |
| 145289 | 145474 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 145290 | 145475 | pNew->prereqRight = prereqLeft | extraRight; |
| 145291 | 145476 | pNew->prereqAll = prereqAll; |
| 145292 | 145477 | pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; |
| 145293 | 145478 | } |
| | @@ -145457,11 +145642,11 @@ |
| 145457 | 145642 | idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); |
| 145458 | 145643 | testcase( idxNew==0 ); |
| 145459 | 145644 | pNewTerm = &pWC->a[idxNew]; |
| 145460 | 145645 | pNewTerm->prereqRight = prereqExpr; |
| 145461 | 145646 | pNewTerm->leftCursor = pLeft->iTable; |
| 145462 | | - pNewTerm->u.leftColumn = pLeft->iColumn; |
| 145647 | + pNewTerm->u.x.leftColumn = pLeft->iColumn; |
| 145463 | 145648 | pNewTerm->eOperator = WO_AUX; |
| 145464 | 145649 | pNewTerm->eMatchOp = eOp2; |
| 145465 | 145650 | markTermAsChild(pWC, idxNew, idxTerm); |
| 145466 | 145651 | pTerm = &pWC->a[idxTerm]; |
| 145467 | 145652 | pTerm->wtFlags |= TERM_COPIED; |
| | @@ -145504,17 +145689,17 @@ |
| 145504 | 145689 | } |
| 145505 | 145690 | |
| 145506 | 145691 | /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create |
| 145507 | 145692 | ** a virtual term for each vector component. The expression object |
| 145508 | 145693 | ** used by each such virtual term is pExpr (the full vector IN(...) |
| 145509 | | - ** expression). The WhereTerm.iField variable identifies the index within |
| 145694 | + ** expression). The WhereTerm.u.x.iField variable identifies the index within |
| 145510 | 145695 | ** the vector on the LHS that the virtual term represents. |
| 145511 | 145696 | ** |
| 145512 | 145697 | ** This only works if the RHS is a simple SELECT (not a compound) that does |
| 145513 | 145698 | ** not use window functions. |
| 145514 | 145699 | */ |
| 145515 | | - if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0 |
| 145700 | + if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0 |
| 145516 | 145701 | && pExpr->pLeft->op==TK_VECTOR |
| 145517 | 145702 | && pExpr->x.pSelect->pPrior==0 |
| 145518 | 145703 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 145519 | 145704 | && pExpr->x.pSelect->pWin==0 |
| 145520 | 145705 | #endif |
| | @@ -145521,11 +145706,11 @@ |
| 145521 | 145706 | ){ |
| 145522 | 145707 | int i; |
| 145523 | 145708 | for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ |
| 145524 | 145709 | int idxNew; |
| 145525 | 145710 | idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); |
| 145526 | | - pWC->a[idxNew].iField = i+1; |
| 145711 | + pWC->a[idxNew].u.x.iField = i+1; |
| 145527 | 145712 | exprAnalyze(pSrc, pWC, idxNew); |
| 145528 | 145713 | markTermAsChild(pWC, idxNew, idxTerm); |
| 145529 | 145714 | } |
| 145530 | 145715 | } |
| 145531 | 145716 | |
| | @@ -145556,11 +145741,11 @@ |
| 145556 | 145741 | TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
| 145557 | 145742 | if( idxNew ){ |
| 145558 | 145743 | pNewTerm = &pWC->a[idxNew]; |
| 145559 | 145744 | pNewTerm->prereqRight = 0; |
| 145560 | 145745 | pNewTerm->leftCursor = pLeft->iTable; |
| 145561 | | - pNewTerm->u.leftColumn = pLeft->iColumn; |
| 145746 | + pNewTerm->u.x.leftColumn = pLeft->iColumn; |
| 145562 | 145747 | pNewTerm->eOperator = WO_GT; |
| 145563 | 145748 | markTermAsChild(pWC, idxNew, idxTerm); |
| 145564 | 145749 | pTerm = &pWC->a[idxTerm]; |
| 145565 | 145750 | pTerm->wtFlags |= TERM_COPIED; |
| 145566 | 145751 | pNewTerm->prereqAll = pTerm->prereqAll; |
| | @@ -146020,11 +146205,11 @@ |
| 146020 | 146205 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 146021 | 146206 | assert( pWC!=0 ); |
| 146022 | 146207 | do{ |
| 146023 | 146208 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 146024 | 146209 | if( pTerm->leftCursor==iCur |
| 146025 | | - && pTerm->u.leftColumn==iColumn |
| 146210 | + && pTerm->u.x.leftColumn==iColumn |
| 146026 | 146211 | && (iColumn!=XN_EXPR |
| 146027 | 146212 | || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, |
| 146028 | 146213 | pScan->pIdxExpr,iCur)==0) |
| 146029 | 146214 | && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) |
| 146030 | 146215 | ){ |
| | @@ -146442,12 +146627,12 @@ |
| 146442 | 146627 | ** the RHS of a LEFT JOIN. Such a term can only be used if it is from |
| 146443 | 146628 | ** the ON clause. */ |
| 146444 | 146629 | return 0; |
| 146445 | 146630 | } |
| 146446 | 146631 | if( (pTerm->prereqRight & notReady)!=0 ) return 0; |
| 146447 | | - if( pTerm->u.leftColumn<0 ) return 0; |
| 146448 | | - aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; |
| 146632 | + if( pTerm->u.x.leftColumn<0 ) return 0; |
| 146633 | + aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity; |
| 146449 | 146634 | if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; |
| 146450 | 146635 | testcase( pTerm->pExpr->op==TK_IS ); |
| 146451 | 146636 | return 1; |
| 146452 | 146637 | } |
| 146453 | 146638 | #endif |
| | @@ -146514,11 +146699,11 @@ |
| 146514 | 146699 | && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ |
| 146515 | 146700 | pPartial = sqlite3ExprAnd(pParse, pPartial, |
| 146516 | 146701 | sqlite3ExprDup(pParse->db, pExpr, 0)); |
| 146517 | 146702 | } |
| 146518 | 146703 | if( termCanDriveIndex(pTerm, pSrc, notReady) ){ |
| 146519 | | - int iCol = pTerm->u.leftColumn; |
| 146704 | + int iCol = pTerm->u.x.leftColumn; |
| 146520 | 146705 | Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); |
| 146521 | 146706 | testcase( iCol==BMS ); |
| 146522 | 146707 | testcase( iCol==BMS-1 ); |
| 146523 | 146708 | if( !sentWarning ){ |
| 146524 | 146709 | sqlite3_log(SQLITE_WARNING_AUTOINDEX, |
| | @@ -146567,18 +146752,18 @@ |
| 146567 | 146752 | pIdx->pTable = pTable; |
| 146568 | 146753 | n = 0; |
| 146569 | 146754 | idxCols = 0; |
| 146570 | 146755 | for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ |
| 146571 | 146756 | if( termCanDriveIndex(pTerm, pSrc, notReady) ){ |
| 146572 | | - int iCol = pTerm->u.leftColumn; |
| 146757 | + int iCol = pTerm->u.x.leftColumn; |
| 146573 | 146758 | Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); |
| 146574 | 146759 | testcase( iCol==BMS-1 ); |
| 146575 | 146760 | testcase( iCol==BMS ); |
| 146576 | 146761 | if( (idxCols & cMask)==0 ){ |
| 146577 | 146762 | Expr *pX = pTerm->pExpr; |
| 146578 | 146763 | idxCols |= cMask; |
| 146579 | | - pIdx->aiColumn[n] = pTerm->u.leftColumn; |
| 146764 | + pIdx->aiColumn[n] = pTerm->u.x.leftColumn; |
| 146580 | 146765 | pColl = sqlite3ExprCompareCollSeq(pParse, pX); |
| 146581 | 146766 | assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ |
| 146582 | 146767 | pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; |
| 146583 | 146768 | n++; |
| 146584 | 146769 | } |
| | @@ -146695,11 +146880,11 @@ |
| 146695 | 146880 | testcase( pTerm->eOperator & WO_ISNULL ); |
| 146696 | 146881 | testcase( pTerm->eOperator & WO_IS ); |
| 146697 | 146882 | testcase( pTerm->eOperator & WO_ALL ); |
| 146698 | 146883 | if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; |
| 146699 | 146884 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 146700 | | - assert( pTerm->u.leftColumn>=(-1) ); |
| 146885 | + assert( pTerm->u.x.leftColumn>=(-1) ); |
| 146701 | 146886 | nTerm++; |
| 146702 | 146887 | } |
| 146703 | 146888 | |
| 146704 | 146889 | /* If the ORDER BY clause contains only columns in the current |
| 146705 | 146890 | ** virtual table then allocate space for the aOrderBy part of |
| | @@ -146755,12 +146940,12 @@ |
| 146755 | 146940 | if( (pSrc->fg.jointype & JT_LEFT)!=0 |
| 146756 | 146941 | && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) |
| 146757 | 146942 | ){ |
| 146758 | 146943 | continue; |
| 146759 | 146944 | } |
| 146760 | | - assert( pTerm->u.leftColumn>=(-1) ); |
| 146761 | | - pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 146945 | + assert( pTerm->u.x.leftColumn>=(-1) ); |
| 146946 | + pIdxCons[j].iColumn = pTerm->u.x.leftColumn; |
| 146762 | 146947 | pIdxCons[j].iTermOffset = i; |
| 146763 | 146948 | op = pTerm->eOperator & WO_ALL; |
| 146764 | 146949 | if( op==WO_IN ) op = WO_EQ; |
| 146765 | 146950 | if( op==WO_AUX ){ |
| 146766 | 146951 | pIdxCons[j].op = pTerm->eMatchOp; |
| | @@ -147519,11 +147704,11 @@ |
| 147519 | 147704 | if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; |
| 147520 | 147705 | if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; |
| 147521 | 147706 | if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C'; |
| 147522 | 147707 | if( pTerm->eOperator & WO_SINGLE ){ |
| 147523 | 147708 | sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}", |
| 147524 | | - pTerm->leftCursor, pTerm->u.leftColumn); |
| 147709 | + pTerm->leftCursor, pTerm->u.x.leftColumn); |
| 147525 | 147710 | }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ |
| 147526 | 147711 | sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", |
| 147527 | 147712 | pTerm->u.pOrInfo->indexable); |
| 147528 | 147713 | }else{ |
| 147529 | 147714 | sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); |
| | @@ -147535,12 +147720,12 @@ |
| 147535 | 147720 | ** shown about each Term */ |
| 147536 | 147721 | if( sqlite3WhereTrace & 0x10000 ){ |
| 147537 | 147722 | sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx", |
| 147538 | 147723 | pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight); |
| 147539 | 147724 | } |
| 147540 | | - if( pTerm->iField ){ |
| 147541 | | - sqlite3DebugPrintf(" iField=%d", pTerm->iField); |
| 147725 | + if( pTerm->u.x.iField ){ |
| 147726 | + sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField); |
| 147542 | 147727 | } |
| 147543 | 147728 | if( pTerm->iParent>=0 ){ |
| 147544 | 147729 | sqlite3DebugPrintf(" iParent=%d", pTerm->iParent); |
| 147545 | 147730 | } |
| 147546 | 147731 | sqlite3DebugPrintf("\n"); |
| | @@ -148327,11 +148512,11 @@ |
| 148327 | 148512 | safetyMargin = 10; /* TUNING: extra weight for indexed IN */ |
| 148328 | 148513 | if( M + logK + safetyMargin < nIn + rLogSize ){ |
| 148329 | 148514 | WHERETRACE(0x40, |
| 148330 | 148515 | ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", |
| 148331 | 148516 | saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); |
| 148332 | | - continue; |
| 148517 | + pNew->wsFlags |= WHERE_IN_SEEKSCAN; |
| 148333 | 148518 | }else{ |
| 148334 | 148519 | WHERETRACE(0x40, |
| 148335 | 148520 | ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n", |
| 148336 | 148521 | saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); |
| 148337 | 148522 | } |
| | @@ -150960,10 +151145,11 @@ |
| 150960 | 151145 | sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); |
| 150961 | 151146 | sqlite3VdbeSetP4KeyInfo(pParse, pIx); |
| 150962 | 151147 | if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 |
| 150963 | 151148 | && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 |
| 150964 | 151149 | && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0 |
| 151150 | + && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 |
| 150965 | 151151 | && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 |
| 150966 | 151152 | && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED |
| 150967 | 151153 | ){ |
| 150968 | 151154 | sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); |
| 150969 | 151155 | } |
| | @@ -151122,11 +151308,13 @@ |
| 151122 | 151308 | sqlite3VdbeResolveLabel(v, pLevel->addrNxt); |
| 151123 | 151309 | for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ |
| 151124 | 151310 | sqlite3VdbeJumpHere(v, pIn->addrInTop+1); |
| 151125 | 151311 | if( pIn->eEndLoopOp!=OP_Noop ){ |
| 151126 | 151312 | if( pIn->nPrefix ){ |
| 151127 | | - assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); |
| 151313 | + int bEarlyOut = |
| 151314 | + (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 |
| 151315 | + && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0; |
| 151128 | 151316 | if( pLevel->iLeftJoin ){ |
| 151129 | 151317 | /* For LEFT JOIN queries, cursor pIn->iCur may not have been |
| 151130 | 151318 | ** opened yet. This occurs for WHERE clauses such as |
| 151131 | 151319 | ** "a = ? AND b IN (...)", where the index is on (a, b). If |
| 151132 | 151320 | ** the RHS of the (a=?) is NULL, then the "b IN (...)" may |
| | @@ -151133,16 +151321,14 @@ |
| 151133 | 151321 | ** never have been coded, but the body of the loop run to |
| 151134 | 151322 | ** return the null-row. So, if the cursor is not open yet, |
| 151135 | 151323 | ** jump over the OP_Next or OP_Prev instruction about to |
| 151136 | 151324 | ** be coded. */ |
| 151137 | 151325 | sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur, |
| 151138 | | - sqlite3VdbeCurrentAddr(v) + 2 + |
| 151139 | | - ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0) |
| 151140 | | - ); |
| 151326 | + sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut); |
| 151141 | 151327 | VdbeCoverage(v); |
| 151142 | 151328 | } |
| 151143 | | - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){ |
| 151329 | + if( bEarlyOut ){ |
| 151144 | 151330 | sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, |
| 151145 | 151331 | sqlite3VdbeCurrentAddr(v)+2, |
| 151146 | 151332 | pIn->iBase, pIn->nPrefix); |
| 151147 | 151333 | VdbeCoverage(v); |
| 151148 | 151334 | } |
| | @@ -157827,12 +158013,13 @@ |
| 157827 | 158013 | int yysize; /* Amount to pop the stack */ |
| 157828 | 158014 | sqlite3ParserARG_FETCH |
| 157829 | 158015 | (void)yyLookahead; |
| 157830 | 158016 | (void)yyLookaheadToken; |
| 157831 | 158017 | yymsp = yypParser->yytos; |
| 158018 | + assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ); |
| 157832 | 158019 | #ifndef NDEBUG |
| 157833 | | - if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ |
| 158020 | + if( yyTraceFILE ){ |
| 157834 | 158021 | yysize = yyRuleInfoNRhs[yyruleno]; |
| 157835 | 158022 | if( yysize ){ |
| 157836 | 158023 | fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", |
| 157837 | 158024 | yyTracePrompt, |
| 157838 | 158025 | yyruleno, yyRuleName[yyruleno], |
| | @@ -209390,11 +209577,11 @@ |
| 209390 | 209577 | static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int); |
| 209391 | 209578 | |
| 209392 | 209579 | /* |
| 209393 | 209580 | ** Functions called by the storage module as part of integrity-check. |
| 209394 | 209581 | */ |
| 209395 | | -static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum); |
| 209582 | +static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum); |
| 209396 | 209583 | |
| 209397 | 209584 | /* |
| 209398 | 209585 | ** Called during virtual module initialization to register UDF |
| 209399 | 209586 | ** fts5_decode() with SQLite |
| 209400 | 209587 | */ |
| | @@ -209545,11 +209732,11 @@ |
| 209545 | 209732 | |
| 209546 | 209733 | static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**); |
| 209547 | 209734 | static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*); |
| 209548 | 209735 | static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64); |
| 209549 | 209736 | |
| 209550 | | -static int sqlite3Fts5StorageIntegrity(Fts5Storage *p); |
| 209737 | +static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg); |
| 209551 | 209738 | |
| 209552 | 209739 | static int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**); |
| 209553 | 209740 | static void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*); |
| 209554 | 209741 | |
| 209555 | 209742 | static int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol); |
| | @@ -210735,12 +210922,13 @@ |
| 210735 | 210922 | int fts5yysize; /* Amount to pop the stack */ |
| 210736 | 210923 | sqlite3Fts5ParserARG_FETCH |
| 210737 | 210924 | (void)fts5yyLookahead; |
| 210738 | 210925 | (void)fts5yyLookaheadToken; |
| 210739 | 210926 | fts5yymsp = fts5yypParser->fts5yytos; |
| 210927 | + assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ); |
| 210740 | 210928 | #ifndef NDEBUG |
| 210741 | | - if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ |
| 210929 | + if( fts5yyTraceFILE ){ |
| 210742 | 210930 | fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno]; |
| 210743 | 210931 | if( fts5yysize ){ |
| 210744 | 210932 | fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", |
| 210745 | 210933 | fts5yyTracePrompt, |
| 210746 | 210934 | fts5yyruleno, fts5yyRuleName[fts5yyruleno], |
| | @@ -222842,11 +223030,11 @@ |
| 222842 | 223030 | ** Return SQLITE_CORRUPT if any of the internal checks fail, or if the |
| 222843 | 223031 | ** checksum does not match. Return SQLITE_OK if all checks pass without |
| 222844 | 223032 | ** error, or some other SQLite error code if another error (e.g. OOM) |
| 222845 | 223033 | ** occurs. |
| 222846 | 223034 | */ |
| 222847 | | -static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ |
| 223035 | +static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){ |
| 222848 | 223036 | int eDetail = p->pConfig->eDetail; |
| 222849 | 223037 | u64 cksum2 = 0; /* Checksum based on contents of indexes */ |
| 222850 | 223038 | Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ |
| 222851 | 223039 | Fts5Iter *pIter; /* Used to iterate through entire index */ |
| 222852 | 223040 | Fts5Structure *pStruct; /* Index structure */ |
| | @@ -222913,11 +223101,11 @@ |
| 222913 | 223101 | } |
| 222914 | 223102 | } |
| 222915 | 223103 | fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); |
| 222916 | 223104 | |
| 222917 | 223105 | fts5MultiIterFree(pIter); |
| 222918 | | - if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; |
| 223106 | + if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; |
| 222919 | 223107 | |
| 222920 | 223108 | fts5StructureRelease(pStruct); |
| 222921 | 223109 | #ifdef SQLITE_DEBUG |
| 222922 | 223110 | fts5BufferFree(&term); |
| 222923 | 223111 | #endif |
| | @@ -224921,11 +225109,12 @@ |
| 224921 | 225109 | rc = sqlite3Fts5StorageOptimize(pTab->pStorage); |
| 224922 | 225110 | }else if( 0==sqlite3_stricmp("merge", zCmd) ){ |
| 224923 | 225111 | int nMerge = sqlite3_value_int(pVal); |
| 224924 | 225112 | rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge); |
| 224925 | 225113 | }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){ |
| 224926 | | - rc = sqlite3Fts5StorageIntegrity(pTab->pStorage); |
| 225114 | + int iArg = sqlite3_value_int(pVal); |
| 225115 | + rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg); |
| 224927 | 225116 | #ifdef SQLITE_DEBUG |
| 224928 | 225117 | }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){ |
| 224929 | 225118 | pConfig->bPrefixIndex = sqlite3_value_int(pVal); |
| 224930 | 225119 | #endif |
| 224931 | 225120 | }else{ |
| | @@ -226155,11 +226344,11 @@ |
| 226155 | 226344 | int nArg, /* Number of args */ |
| 226156 | 226345 | sqlite3_value **apUnused /* Function arguments */ |
| 226157 | 226346 | ){ |
| 226158 | 226347 | assert( nArg==0 ); |
| 226159 | 226348 | UNUSED_PARAM2(nArg, apUnused); |
| 226160 | | - sqlite3_result_text(pCtx, "fts5: 2020-09-17 21:11:25 4542d194e2fef5e21e1c3679914bd9e21fab31cfb111cf640524fb3514a8afa3", -1, SQLITE_TRANSIENT); |
| 226349 | + sqlite3_result_text(pCtx, "fts5: 2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5", -1, SQLITE_TRANSIENT); |
| 226161 | 226350 | } |
| 226162 | 226351 | |
| 226163 | 226352 | /* |
| 226164 | 226353 | ** Return true if zName is the extension on one of the shadow tables used |
| 226165 | 226354 | ** by this module. |
| | @@ -227170,102 +227359,108 @@ |
| 227170 | 227359 | ** Check that the contents of the FTS index match that of the %_content |
| 227171 | 227360 | ** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return |
| 227172 | 227361 | ** some other SQLite error code if an error occurs while attempting to |
| 227173 | 227362 | ** determine this. |
| 227174 | 227363 | */ |
| 227175 | | -static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){ |
| 227364 | +static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){ |
| 227176 | 227365 | Fts5Config *pConfig = p->pConfig; |
| 227177 | | - int rc; /* Return code */ |
| 227366 | + int rc = SQLITE_OK; /* Return code */ |
| 227178 | 227367 | int *aColSize; /* Array of size pConfig->nCol */ |
| 227179 | 227368 | i64 *aTotalSize; /* Array of size pConfig->nCol */ |
| 227180 | 227369 | Fts5IntegrityCtx ctx; |
| 227181 | 227370 | sqlite3_stmt *pScan; |
| 227371 | + int bUseCksum; |
| 227182 | 227372 | |
| 227183 | 227373 | memset(&ctx, 0, sizeof(Fts5IntegrityCtx)); |
| 227184 | 227374 | ctx.pConfig = p->pConfig; |
| 227185 | 227375 | aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64))); |
| 227186 | 227376 | if( !aTotalSize ) return SQLITE_NOMEM; |
| 227187 | 227377 | aColSize = (int*)&aTotalSize[pConfig->nCol]; |
| 227188 | 227378 | memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol); |
| 227189 | 227379 | |
| 227190 | | - /* Generate the expected index checksum based on the contents of the |
| 227191 | | - ** %_content table. This block stores the checksum in ctx.cksum. */ |
| 227192 | | - rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); |
| 227193 | | - if( rc==SQLITE_OK ){ |
| 227194 | | - int rc2; |
| 227195 | | - while( SQLITE_ROW==sqlite3_step(pScan) ){ |
| 227196 | | - int i; |
| 227197 | | - ctx.iRowid = sqlite3_column_int64(pScan, 0); |
| 227198 | | - ctx.szCol = 0; |
| 227199 | | - if( pConfig->bColumnsize ){ |
| 227200 | | - rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize); |
| 227201 | | - } |
| 227202 | | - if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 227203 | | - rc = sqlite3Fts5TermsetNew(&ctx.pTermset); |
| 227204 | | - } |
| 227205 | | - for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){ |
| 227206 | | - if( pConfig->abUnindexed[i] ) continue; |
| 227207 | | - ctx.iCol = i; |
| 227208 | | - ctx.szCol = 0; |
| 227209 | | - if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ |
| 227210 | | - rc = sqlite3Fts5TermsetNew(&ctx.pTermset); |
| 227211 | | - } |
| 227212 | | - if( rc==SQLITE_OK ){ |
| 227213 | | - const char *zText = (const char*)sqlite3_column_text(pScan, i+1); |
| 227214 | | - int nText = sqlite3_column_bytes(pScan, i+1); |
| 227215 | | - rc = sqlite3Fts5Tokenize(pConfig, |
| 227216 | | - FTS5_TOKENIZE_DOCUMENT, |
| 227217 | | - zText, nText, |
| 227218 | | - (void*)&ctx, |
| 227219 | | - fts5StorageIntegrityCallback |
| 227220 | | - ); |
| 227221 | | - } |
| 227222 | | - if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){ |
| 227223 | | - rc = FTS5_CORRUPT; |
| 227224 | | - } |
| 227225 | | - aTotalSize[i] += ctx.szCol; |
| 227226 | | - if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ |
| 227227 | | - sqlite3Fts5TermsetFree(ctx.pTermset); |
| 227228 | | - ctx.pTermset = 0; |
| 227229 | | - } |
| 227230 | | - } |
| 227231 | | - sqlite3Fts5TermsetFree(ctx.pTermset); |
| 227232 | | - ctx.pTermset = 0; |
| 227233 | | - |
| 227234 | | - if( rc!=SQLITE_OK ) break; |
| 227235 | | - } |
| 227236 | | - rc2 = sqlite3_reset(pScan); |
| 227237 | | - if( rc==SQLITE_OK ) rc = rc2; |
| 227238 | | - } |
| 227239 | | - |
| 227240 | | - /* Test that the "totals" (sometimes called "averages") record looks Ok */ |
| 227241 | | - if( rc==SQLITE_OK ){ |
| 227242 | | - int i; |
| 227243 | | - rc = fts5StorageLoadTotals(p, 0); |
| 227244 | | - for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){ |
| 227245 | | - if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT; |
| 227246 | | - } |
| 227247 | | - } |
| 227248 | | - |
| 227249 | | - /* Check that the %_docsize and %_content tables contain the expected |
| 227250 | | - ** number of rows. */ |
| 227251 | | - if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ |
| 227252 | | - i64 nRow = 0; |
| 227253 | | - rc = fts5StorageCount(p, "content", &nRow); |
| 227254 | | - if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; |
| 227255 | | - } |
| 227256 | | - if( rc==SQLITE_OK && pConfig->bColumnsize ){ |
| 227257 | | - i64 nRow = 0; |
| 227258 | | - rc = fts5StorageCount(p, "docsize", &nRow); |
| 227259 | | - if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; |
| 227380 | + bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL |
| 227381 | + || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg) |
| 227382 | + ); |
| 227383 | + if( bUseCksum ){ |
| 227384 | + /* Generate the expected index checksum based on the contents of the |
| 227385 | + ** %_content table. This block stores the checksum in ctx.cksum. */ |
| 227386 | + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); |
| 227387 | + if( rc==SQLITE_OK ){ |
| 227388 | + int rc2; |
| 227389 | + while( SQLITE_ROW==sqlite3_step(pScan) ){ |
| 227390 | + int i; |
| 227391 | + ctx.iRowid = sqlite3_column_int64(pScan, 0); |
| 227392 | + ctx.szCol = 0; |
| 227393 | + if( pConfig->bColumnsize ){ |
| 227394 | + rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize); |
| 227395 | + } |
| 227396 | + if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 227397 | + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); |
| 227398 | + } |
| 227399 | + for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){ |
| 227400 | + if( pConfig->abUnindexed[i] ) continue; |
| 227401 | + ctx.iCol = i; |
| 227402 | + ctx.szCol = 0; |
| 227403 | + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ |
| 227404 | + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); |
| 227405 | + } |
| 227406 | + if( rc==SQLITE_OK ){ |
| 227407 | + const char *zText = (const char*)sqlite3_column_text(pScan, i+1); |
| 227408 | + int nText = sqlite3_column_bytes(pScan, i+1); |
| 227409 | + rc = sqlite3Fts5Tokenize(pConfig, |
| 227410 | + FTS5_TOKENIZE_DOCUMENT, |
| 227411 | + zText, nText, |
| 227412 | + (void*)&ctx, |
| 227413 | + fts5StorageIntegrityCallback |
| 227414 | + ); |
| 227415 | + } |
| 227416 | + if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){ |
| 227417 | + rc = FTS5_CORRUPT; |
| 227418 | + } |
| 227419 | + aTotalSize[i] += ctx.szCol; |
| 227420 | + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ |
| 227421 | + sqlite3Fts5TermsetFree(ctx.pTermset); |
| 227422 | + ctx.pTermset = 0; |
| 227423 | + } |
| 227424 | + } |
| 227425 | + sqlite3Fts5TermsetFree(ctx.pTermset); |
| 227426 | + ctx.pTermset = 0; |
| 227427 | + |
| 227428 | + if( rc!=SQLITE_OK ) break; |
| 227429 | + } |
| 227430 | + rc2 = sqlite3_reset(pScan); |
| 227431 | + if( rc==SQLITE_OK ) rc = rc2; |
| 227432 | + } |
| 227433 | + |
| 227434 | + /* Test that the "totals" (sometimes called "averages") record looks Ok */ |
| 227435 | + if( rc==SQLITE_OK ){ |
| 227436 | + int i; |
| 227437 | + rc = fts5StorageLoadTotals(p, 0); |
| 227438 | + for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){ |
| 227439 | + if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT; |
| 227440 | + } |
| 227441 | + } |
| 227442 | + |
| 227443 | + /* Check that the %_docsize and %_content tables contain the expected |
| 227444 | + ** number of rows. */ |
| 227445 | + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ |
| 227446 | + i64 nRow = 0; |
| 227447 | + rc = fts5StorageCount(p, "content", &nRow); |
| 227448 | + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; |
| 227449 | + } |
| 227450 | + if( rc==SQLITE_OK && pConfig->bColumnsize ){ |
| 227451 | + i64 nRow = 0; |
| 227452 | + rc = fts5StorageCount(p, "docsize", &nRow); |
| 227453 | + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; |
| 227454 | + } |
| 227260 | 227455 | } |
| 227261 | 227456 | |
| 227262 | 227457 | /* Pass the expected checksum down to the FTS index module. It will |
| 227263 | 227458 | ** verify, amongst other things, that it matches the checksum generated by |
| 227264 | 227459 | ** inspecting the index itself. */ |
| 227265 | 227460 | if( rc==SQLITE_OK ){ |
| 227266 | | - rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum); |
| 227461 | + rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum); |
| 227267 | 227462 | } |
| 227268 | 227463 | |
| 227269 | 227464 | sqlite3_free(aTotalSize); |
| 227270 | 227465 | return rc; |
| 227271 | 227466 | } |
| | @@ -230945,12 +231140,12 @@ |
| 230945 | 231140 | } |
| 230946 | 231141 | #endif /* SQLITE_CORE */ |
| 230947 | 231142 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 230948 | 231143 | |
| 230949 | 231144 | /************** End of stmt.c ************************************************/ |
| 230950 | | -#if __LINE__!=230950 |
| 231145 | +#if __LINE__!=231145 |
| 230951 | 231146 | #undef SQLITE_SOURCE_ID |
| 230952 | | -#define SQLITE_SOURCE_ID "2020-09-17 21:11:25 4542d194e2fef5e21e1c3679914bd9e21fab31cfb111cf640524fb3514a8alt2" |
| 231147 | +#define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c4alt2" |
| 230953 | 231148 | #endif |
| 230954 | 231149 | /* Return the source-id for this library */ |
| 230955 | 231150 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 230956 | 231151 | /************************** End of sqlite3.c ******************************/ |
| 230957 | 231152 | |