Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/sqlite/src/src/wherecode.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* | - | ||||||||||||||||||
2 | ** 2015-06-06 | - | ||||||||||||||||||
3 | ** | - | ||||||||||||||||||
4 | ** The author disclaims copyright to this source code. In place of | - | ||||||||||||||||||
5 | ** a legal notice, here is a blessing: | - | ||||||||||||||||||
6 | ** | - | ||||||||||||||||||
7 | ** May you do good and not evil. | - | ||||||||||||||||||
8 | ** May you find forgiveness for yourself and forgive others. | - | ||||||||||||||||||
9 | ** May you share freely, never taking more than you give. | - | ||||||||||||||||||
10 | ** | - | ||||||||||||||||||
11 | ************************************************************************* | - | ||||||||||||||||||
12 | ** This module contains C code that generates VDBE code used to process | - | ||||||||||||||||||
13 | ** the WHERE clause of SQL statements. | - | ||||||||||||||||||
14 | ** | - | ||||||||||||||||||
15 | ** This file was split off from where.c on 2015-06-06 in order to reduce the | - | ||||||||||||||||||
16 | ** size of where.c and make it easier to edit. This file contains the routines | - | ||||||||||||||||||
17 | ** that actually generate the bulk of the WHERE loop code. The original where.c | - | ||||||||||||||||||
18 | ** file retains the code that does query planning and analysis. | - | ||||||||||||||||||
19 | */ | - | ||||||||||||||||||
20 | #include "sqliteInt.h" | - | ||||||||||||||||||
21 | #include "whereInt.h" | - | ||||||||||||||||||
22 | - | |||||||||||||||||||
23 | #ifndef SQLITE_OMIT_EXPLAIN | - | ||||||||||||||||||
24 | - | |||||||||||||||||||
25 | /* | - | ||||||||||||||||||
26 | ** Return the name of the i-th column of the pIdx index. | - | ||||||||||||||||||
27 | */ | - | ||||||||||||||||||
28 | static const char *explainIndexColumnName(Index *pIdx, int i){ | - | ||||||||||||||||||
29 | i = pIdx->aiColumn[i]; | - | ||||||||||||||||||
30 | if( i==XN_EXPR ) return "<expr>"; executed 15 times by 1 test: return "<expr>"; Executed by:
| 15-624 | ||||||||||||||||||
31 | if( i==XN_ROWID ) return "rowid"; executed 3 times by 1 test: return "rowid"; Executed by:
| 3-621 | ||||||||||||||||||
32 | return pIdx->pTable->aCol[i].zName; executed 621 times by 1 test: return pIdx->pTable->aCol[i].zName; Executed by:
| 621 | ||||||||||||||||||
33 | } | - | ||||||||||||||||||
34 | - | |||||||||||||||||||
35 | /* | - | ||||||||||||||||||
36 | ** This routine is a helper for explainIndexRange() below | - | ||||||||||||||||||
37 | ** | - | ||||||||||||||||||
38 | ** pStr holds the text of an expression that we are building up one term | - | ||||||||||||||||||
39 | ** at a time. This routine adds a new term to the end of the expression. | - | ||||||||||||||||||
40 | ** Terms are separated by AND so add the "AND" text for second and subsequent | - | ||||||||||||||||||
41 | ** terms only. | - | ||||||||||||||||||
42 | */ | - | ||||||||||||||||||
43 | static void explainAppendTerm( | - | ||||||||||||||||||
44 | StrAccum *pStr, /* The text expression being built */ | - | ||||||||||||||||||
45 | Index *pIdx, /* Index to read column names from */ | - | ||||||||||||||||||
46 | int nTerm, /* Number of terms */ | - | ||||||||||||||||||
47 | int iTerm, /* Zero-based index of first term. */ | - | ||||||||||||||||||
48 | int bAnd, /* Non-zero to append " AND " */ | - | ||||||||||||||||||
49 | const char *zOp /* Name of the operator */ | - | ||||||||||||||||||
50 | ){ | - | ||||||||||||||||||
51 | int i; | - | ||||||||||||||||||
52 | - | |||||||||||||||||||
53 | assert( nTerm>=1 ); | - | ||||||||||||||||||
54 | if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); executed 98 times by 1 test: sqlite3_str_append(pStr, " AND ", 5); Executed by:
| 81-98 | ||||||||||||||||||
55 | - | |||||||||||||||||||
56 | if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, "(", 1); Executed by:
| 6-173 | ||||||||||||||||||
57 | for(i=0; i<nTerm; i++){
| 179-185 | ||||||||||||||||||
58 | if( i ) sqlite3_str_append(pStr, ",", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, ",", 1); Executed by:
| 6-179 | ||||||||||||||||||
59 | sqlite3_str_appendall(pStr, explainIndexColumnName(pIdx, iTerm+i)); | - | ||||||||||||||||||
60 | } executed 185 times by 1 test: end of block Executed by:
| 185 | ||||||||||||||||||
61 | if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, ")", 1); Executed by:
| 6-173 | ||||||||||||||||||
62 | - | |||||||||||||||||||
63 | sqlite3_str_append(pStr, zOp, 1); | - | ||||||||||||||||||
64 | - | |||||||||||||||||||
65 | if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, "(", 1); Executed by:
| 6-173 | ||||||||||||||||||
66 | for(i=0; i<nTerm; i++){
| 179-185 | ||||||||||||||||||
67 | if( i ) sqlite3_str_append(pStr, ",", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, ",", 1); Executed by:
| 6-179 | ||||||||||||||||||
68 | sqlite3_str_append(pStr, "?", 1); | - | ||||||||||||||||||
69 | } executed 185 times by 1 test: end of block Executed by:
| 185 | ||||||||||||||||||
70 | if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); executed 6 times by 1 test: sqlite3_str_append(pStr, ")", 1); Executed by:
| 6-173 | ||||||||||||||||||
71 | } executed 179 times by 1 test: end of block Executed by:
| 179 | ||||||||||||||||||
72 | - | |||||||||||||||||||
73 | /* | - | ||||||||||||||||||
74 | ** Argument pLevel describes a strategy for scanning table pTab. This | - | ||||||||||||||||||
75 | ** function appends text to pStr that describes the subset of table | - | ||||||||||||||||||
76 | ** rows scanned by the strategy in the form of an SQL expression. | - | ||||||||||||||||||
77 | ** | - | ||||||||||||||||||
78 | ** For example, if the query: | - | ||||||||||||||||||
79 | ** | - | ||||||||||||||||||
80 | ** SELECT * FROM t1 WHERE a=1 AND b>2; | - | ||||||||||||||||||
81 | ** | - | ||||||||||||||||||
82 | ** is run and there is an index on (a, b), then this function returns a | - | ||||||||||||||||||
83 | ** string similar to: | - | ||||||||||||||||||
84 | ** | - | ||||||||||||||||||
85 | ** "a=? AND b>?" | - | ||||||||||||||||||
86 | */ | - | ||||||||||||||||||
87 | static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ | - | ||||||||||||||||||
88 | Index *pIndex = pLoop->u.btree.pIndex; | - | ||||||||||||||||||
89 | u16 nEq = pLoop->u.btree.nEq; | - | ||||||||||||||||||
90 | u16 nSkip = pLoop->nSkip; | - | ||||||||||||||||||
91 | int i, j; | - | ||||||||||||||||||
92 | - | |||||||||||||||||||
93 | if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; executed 116 times by 1 test: return; Executed by:
| 81-323 | ||||||||||||||||||
94 | sqlite3_str_append(pStr, " (", 2); | - | ||||||||||||||||||
95 | for(i=0; i<nEq; i++){
| 404-454 | ||||||||||||||||||
96 | const char *z = explainIndexColumnName(pIndex, i); | - | ||||||||||||||||||
97 | if( i ) sqlite3_str_append(pStr, " AND ", 5); executed 131 times by 1 test: sqlite3_str_append(pStr, " AND ", 5); Executed by:
| 131-323 | ||||||||||||||||||
98 | sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); | - | ||||||||||||||||||
99 | } executed 454 times by 1 test: end of block Executed by:
| 454 | ||||||||||||||||||
100 | - | |||||||||||||||||||
101 | j = i; | - | ||||||||||||||||||
102 | if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
| 105-299 | ||||||||||||||||||
103 | explainAppendTerm(pStr, pIndex, pLoop->u.btree.nBtm, j, i, ">"); | - | ||||||||||||||||||
104 | i = 1; | - | ||||||||||||||||||
105 | } executed 105 times by 1 test: end of block Executed by:
| 105 | ||||||||||||||||||
106 | if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
| 74-330 | ||||||||||||||||||
107 | explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); | - | ||||||||||||||||||
108 | } executed 74 times by 1 test: end of block Executed by:
| 74 | ||||||||||||||||||
109 | sqlite3_str_append(pStr, ")", 1); | - | ||||||||||||||||||
110 | } executed 404 times by 1 test: end of block Executed by:
| 404 | ||||||||||||||||||
111 | - | |||||||||||||||||||
112 | /* | - | ||||||||||||||||||
113 | ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN | - | ||||||||||||||||||
114 | ** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was | - | ||||||||||||||||||
115 | ** defined at compile-time. If it is not a no-op, a single OP_Explain opcode | - | ||||||||||||||||||
116 | ** is added to the output to describe the table scan strategy in pLevel. | - | ||||||||||||||||||
117 | ** | - | ||||||||||||||||||
118 | ** If an OP_Explain opcode is added to the VM, its address is returned. | - | ||||||||||||||||||
119 | ** Otherwise, if no OP_Explain is coded, zero is returned. | - | ||||||||||||||||||
120 | */ | - | ||||||||||||||||||
121 | int sqlite3WhereExplainOneScan( | - | ||||||||||||||||||
122 | Parse *pParse, /* Parse context */ | - | ||||||||||||||||||
123 | SrcList *pTabList, /* Table list this loop refers to */ | - | ||||||||||||||||||
124 | WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ | - | ||||||||||||||||||
125 | u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ | - | ||||||||||||||||||
126 | ){ | - | ||||||||||||||||||
127 | int ret = 0; | - | ||||||||||||||||||
128 | #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) | - | ||||||||||||||||||
129 | if( sqlite3ParseToplevel(pParse)->explain==2 )
| 746-295537 | ||||||||||||||||||
130 | #endif | - | ||||||||||||||||||
131 | { | - | ||||||||||||||||||
132 | struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; | - | ||||||||||||||||||
133 | Vdbe *v = pParse->pVdbe; /* VM being constructed */ | - | ||||||||||||||||||
134 | sqlite3 *db = pParse->db; /* Database handle */ | - | ||||||||||||||||||
135 | int isSearch; /* True for a SEARCH. False for SCAN. */ | - | ||||||||||||||||||
136 | WhereLoop *pLoop; /* The controlling WhereLoop object */ | - | ||||||||||||||||||
137 | u32 flags; /* Flags that describe this loop */ | - | ||||||||||||||||||
138 | char *zMsg; /* Text to add to EQP output */ | - | ||||||||||||||||||
139 | StrAccum str; /* EQP output string */ | - | ||||||||||||||||||
140 | char zBuf[100]; /* Initial space for EQP output string */ | - | ||||||||||||||||||
141 | - | |||||||||||||||||||
142 | pLoop = pLevel->pWLoop; | - | ||||||||||||||||||
143 | flags = pLoop->wsFlags; | - | ||||||||||||||||||
144 | if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0; executed 64 times by 1 test: return 0; Executed by:
| 21-929 | ||||||||||||||||||
145 | - | |||||||||||||||||||
146 | isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
| 116-770 | ||||||||||||||||||
147 | || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
| 26-744 | ||||||||||||||||||
148 | || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
| 5-380 | ||||||||||||||||||
149 | - | |||||||||||||||||||
150 | sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); | - | ||||||||||||||||||
151 | sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN"); | - | ||||||||||||||||||
152 | if( pItem->pSelect ){
| 21-865 | ||||||||||||||||||
153 | sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId); | - | ||||||||||||||||||
154 | }else{ executed 21 times by 1 test: end of block Executed by:
| 21 | ||||||||||||||||||
155 | sqlite3_str_appendf(&str, " TABLE %s", pItem->zName); | - | ||||||||||||||||||
156 | } executed 865 times by 1 test: end of block Executed by:
| 865 | ||||||||||||||||||
157 | - | |||||||||||||||||||
158 | if( pItem->zAlias ){
| 42-844 | ||||||||||||||||||
159 | sqlite3_str_appendf(&str, " AS %s", pItem->zAlias); | - | ||||||||||||||||||
160 | } executed 42 times by 1 test: end of block Executed by:
| 42 | ||||||||||||||||||
161 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
| 363-523 | ||||||||||||||||||
162 | const char *zFmt = 0; | - | ||||||||||||||||||
163 | Index *pIdx; | - | ||||||||||||||||||
164 | - | |||||||||||||||||||
165 | assert( pLoop->u.btree.pIndex!=0 ); | - | ||||||||||||||||||
166 | pIdx = pLoop->u.btree.pIndex; | - | ||||||||||||||||||
167 | assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); | - | ||||||||||||||||||
168 | if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
| 12-487 | ||||||||||||||||||
169 | if( isSearch ){
| 3-9 | ||||||||||||||||||
170 | zFmt = "PRIMARY KEY"; | - | ||||||||||||||||||
171 | } executed 9 times by 1 test: end of block Executed by:
| 9 | ||||||||||||||||||
172 | }else if( flags & WHERE_PARTIALIDX ){ executed 12 times by 1 test: end of block Executed by:
| 0-511 | ||||||||||||||||||
173 | zFmt = "AUTOMATIC PARTIAL COVERING INDEX"; | - | ||||||||||||||||||
174 | }else if( flags & WHERE_AUTO_INDEX ){ never executed: end of block
| 0-498 | ||||||||||||||||||
175 | zFmt = "AUTOMATIC COVERING INDEX"; | - | ||||||||||||||||||
176 | }else if( flags & WHERE_IDX_ONLY ){ executed 13 times by 1 test: end of block Executed by:
| 13-328 | ||||||||||||||||||
177 | zFmt = "COVERING INDEX %s"; | - | ||||||||||||||||||
178 | }else{ executed 170 times by 1 test: end of block Executed by:
| 170 | ||||||||||||||||||
179 | zFmt = "INDEX %s"; | - | ||||||||||||||||||
180 | } executed 328 times by 1 test: end of block Executed by:
| 328 | ||||||||||||||||||
181 | if( zFmt ){
| 3-520 | ||||||||||||||||||
182 | sqlite3_str_append(&str, " USING ", 7); | - | ||||||||||||||||||
183 | sqlite3_str_appendf(&str, zFmt, pIdx->zName); | - | ||||||||||||||||||
184 | explainIndexRange(&str, pLoop); | - | ||||||||||||||||||
185 | } executed 520 times by 1 test: end of block Executed by:
| 520 | ||||||||||||||||||
186 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ executed 523 times by 1 test: end of block Executed by:
| 26-523 | ||||||||||||||||||
187 | const char *zRangeOp; | - | ||||||||||||||||||
188 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
| 3-94 | ||||||||||||||||||
189 | zRangeOp = "="; | - | ||||||||||||||||||
190 | }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ executed 94 times by 1 test: end of block Executed by:
| 0-94 | ||||||||||||||||||
191 | zRangeOp = ">? AND rowid<"; | - | ||||||||||||||||||
192 | }else if( flags&WHERE_BTM_LIMIT ){ never executed: end of block
| 0-2 | ||||||||||||||||||
193 | zRangeOp = ">"; | - | ||||||||||||||||||
194 | }else{ executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||
195 | assert( flags&WHERE_TOP_LIMIT); | - | ||||||||||||||||||
196 | zRangeOp = "<"; | - | ||||||||||||||||||
197 | } executed 1 time by 1 test: end of block Executed by:
| 1 | ||||||||||||||||||
198 | sqlite3_str_appendf(&str, | - | ||||||||||||||||||
199 | " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); | - | ||||||||||||||||||
200 | } executed 97 times by 1 test: end of block Executed by:
| 97 | ||||||||||||||||||
201 | #ifndef SQLITE_OMIT_VIRTUALTABLE | - | ||||||||||||||||||
202 | else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
| 26-240 | ||||||||||||||||||
203 | sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s", | - | ||||||||||||||||||
204 | pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); | - | ||||||||||||||||||
205 | } executed 26 times by 1 test: end of block Executed by:
| 26 | ||||||||||||||||||
206 | #endif | - | ||||||||||||||||||
207 | #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS | - | ||||||||||||||||||
208 | if( pLoop->nOut>=10 ){ | - | ||||||||||||||||||
209 | sqlite3_str_appendf(&str, " (~%llu rows)", | - | ||||||||||||||||||
210 | sqlite3LogEstToInt(pLoop->nOut)); | - | ||||||||||||||||||
211 | }else{ | - | ||||||||||||||||||
212 | sqlite3_str_append(&str, " (~1 row)", 9); | - | ||||||||||||||||||
213 | } | - | ||||||||||||||||||
214 | #endif | - | ||||||||||||||||||
215 | zMsg = sqlite3StrAccumFinish(&str); | - | ||||||||||||||||||
216 | ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), | - | ||||||||||||||||||
217 | pParse->addrExplain, 0, zMsg,P4_DYNAMIC); | - | ||||||||||||||||||
218 | } executed 886 times by 1 test: end of block Executed by:
| 886 | ||||||||||||||||||
219 | return ret; executed 296219 times by 435 tests: return ret; Executed by:
| 296219 | ||||||||||||||||||
220 | } | - | ||||||||||||||||||
221 | #endif /* SQLITE_OMIT_EXPLAIN */ | - | ||||||||||||||||||
222 | - | |||||||||||||||||||
223 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS | - | ||||||||||||||||||
224 | /* | - | ||||||||||||||||||
225 | ** Configure the VM passed as the first argument with an | - | ||||||||||||||||||
226 | ** sqlite3_stmt_scanstatus() entry corresponding to the scan used to | - | ||||||||||||||||||
227 | ** implement level pLvl. Argument pSrclist is a pointer to the FROM | - | ||||||||||||||||||
228 | ** clause that the scan reads data from. | - | ||||||||||||||||||
229 | ** | - | ||||||||||||||||||
230 | ** If argument addrExplain is not 0, it must be the address of an | - | ||||||||||||||||||
231 | ** OP_Explain instruction that describes the same loop. | - | ||||||||||||||||||
232 | */ | - | ||||||||||||||||||
233 | void sqlite3WhereAddScanStatus( | - | ||||||||||||||||||
234 | Vdbe *v, /* Vdbe to add scanstatus entry to */ | - | ||||||||||||||||||
235 | SrcList *pSrclist, /* FROM clause pLvl reads data from */ | - | ||||||||||||||||||
236 | WhereLevel *pLvl, /* Level to add scanstatus() entry for */ | - | ||||||||||||||||||
237 | int addrExplain /* Address of OP_Explain (or 0) */ | - | ||||||||||||||||||
238 | ){ | - | ||||||||||||||||||
239 | const char *zObj = 0; | - | ||||||||||||||||||
240 | WhereLoop *pLoop = pLvl->pWLoop; | - | ||||||||||||||||||
241 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ | - | ||||||||||||||||||
242 | zObj = pLoop->u.btree.pIndex->zName; | - | ||||||||||||||||||
243 | }else{ | - | ||||||||||||||||||
244 | zObj = pSrclist->a[pLvl->iFrom].zName; | - | ||||||||||||||||||
245 | } | - | ||||||||||||||||||
246 | sqlite3VdbeScanStatus( | - | ||||||||||||||||||
247 | v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj | - | ||||||||||||||||||
248 | ); | - | ||||||||||||||||||
249 | } | - | ||||||||||||||||||
250 | #endif | - | ||||||||||||||||||
251 | - | |||||||||||||||||||
252 | - | |||||||||||||||||||
253 | /* | - | ||||||||||||||||||
254 | ** Disable a term in the WHERE clause. Except, do not disable the term | - | ||||||||||||||||||
255 | ** if it controls a LEFT OUTER JOIN and it did not originate in the ON | - | ||||||||||||||||||
256 | ** or USING clause of that join. | - | ||||||||||||||||||
257 | ** | - | ||||||||||||||||||
258 | ** Consider the term t2.z='ok' in the following queries: | - | ||||||||||||||||||
259 | ** | - | ||||||||||||||||||
260 | ** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' | - | ||||||||||||||||||
261 | ** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' | - | ||||||||||||||||||
262 | ** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' | - | ||||||||||||||||||
263 | ** | - | ||||||||||||||||||
264 | ** The t2.z='ok' is disabled in the in (2) because it originates | - | ||||||||||||||||||
265 | ** in the ON clause. The term is disabled in (3) because it is not part | - | ||||||||||||||||||
266 | ** of a LEFT OUTER JOIN. In (1), the term is not disabled. | - | ||||||||||||||||||
267 | ** | - | ||||||||||||||||||
268 | ** Disabling a term causes that term to not be tested in the inner loop | - | ||||||||||||||||||
269 | ** of the join. Disabling is an optimization. When terms are satisfied | - | ||||||||||||||||||
270 | ** by indices, we disable them to prevent redundant tests in the inner | - | ||||||||||||||||||
271 | ** loop. We would get the correct results if nothing were ever disabled, | - | ||||||||||||||||||
272 | ** but joins might run a little slower. The trick is to disable as much | - | ||||||||||||||||||
273 | ** as we can without disabling too much. If we disabled in (1), we'd get | - | ||||||||||||||||||
274 | ** the wrong answer. See ticket #813. | - | ||||||||||||||||||
275 | ** | - | ||||||||||||||||||
276 | ** If all the children of a term are disabled, then that term is also | - | ||||||||||||||||||
277 | ** automatically disabled. In this way, terms get disabled if derived | - | ||||||||||||||||||
278 | ** virtual terms are tested first. For example: | - | ||||||||||||||||||
279 | ** | - | ||||||||||||||||||
280 | ** x GLOB 'abc*' AND x>='abc' AND x<'acd' | - | ||||||||||||||||||
281 | ** \___________/ \______/ \_____/ | - | ||||||||||||||||||
282 | ** parent child1 child2 | - | ||||||||||||||||||
283 | ** | - | ||||||||||||||||||
284 | ** Only the parent term was in the original WHERE clause. The child1 | - | ||||||||||||||||||
285 | ** and child2 terms were added by the LIKE optimization. If both of | - | ||||||||||||||||||
286 | ** the virtual child terms are valid, then testing of the parent can be | - | ||||||||||||||||||
287 | ** skipped. | - | ||||||||||||||||||
288 | ** | - | ||||||||||||||||||
289 | ** Usually the parent term is marked as TERM_CODED. But if the parent | - | ||||||||||||||||||
290 | ** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. | - | ||||||||||||||||||
291 | ** The TERM_LIKECOND marking indicates that the term should be coded inside | - | ||||||||||||||||||
292 | ** a conditional such that is only evaluated on the second pass of a | - | ||||||||||||||||||
293 | ** LIKE-optimization loop, when scanning BLOBs instead of strings. | - | ||||||||||||||||||
294 | */ | - | ||||||||||||||||||
295 | static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ | - | ||||||||||||||||||
296 | int nLoop = 0; | - | ||||||||||||||||||
297 | assert( pTerm!=0 ); | - | ||||||||||||||||||
298 | while( (pTerm->wtFlags & TERM_CODED)==0
| 50-93044 | ||||||||||||||||||
299 | && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
| 1-92424 | ||||||||||||||||||
300 | && (pLevel->notReady & pTerm->prereqAll)==0
| 19-93024 | ||||||||||||||||||
301 | ){ | - | ||||||||||||||||||
302 | if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
| 225-87754 | ||||||||||||||||||
303 | pTerm->wtFlags |= TERM_LIKECOND; | - | ||||||||||||||||||
304 | }else{ executed 225 times by 1 test: end of block Executed by:
| 225 | ||||||||||||||||||
305 | pTerm->wtFlags |= TERM_CODED; | - | ||||||||||||||||||
306 | } executed 92799 times by 30 tests: end of block Executed by:
| 92799 | ||||||||||||||||||
307 | if( pTerm->iParent<0 ) break; executed 83755 times by 30 tests: break; Executed by:
| 9269-83755 | ||||||||||||||||||
308 | pTerm = &pTerm->pWC->a[pTerm->iParent]; | - | ||||||||||||||||||
309 | assert( pTerm!=0 ); | - | ||||||||||||||||||
310 | pTerm->nChild--; | - | ||||||||||||||||||
311 | if( pTerm->nChild!=0 ) break; executed 3995 times by 1 test: break; Executed by:
| 3995-5274 | ||||||||||||||||||
312 | nLoop++; | - | ||||||||||||||||||
313 | } executed 5274 times by 1 test: end of block Executed by:
| 5274 | ||||||||||||||||||
314 | } executed 87820 times by 30 tests: end of block Executed by:
| 87820 | ||||||||||||||||||
315 | - | |||||||||||||||||||
316 | /* | - | ||||||||||||||||||
317 | ** Code an OP_Affinity opcode to apply the column affinity string zAff | - | ||||||||||||||||||
318 | ** to the n registers starting at base. | - | ||||||||||||||||||
319 | ** | - | ||||||||||||||||||
320 | ** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the | - | ||||||||||||||||||
321 | ** beginning and end of zAff are ignored. If all entries in zAff are | - | ||||||||||||||||||
322 | ** SQLITE_AFF_BLOB, then no code gets generated. | - | ||||||||||||||||||
323 | ** | - | ||||||||||||||||||
324 | ** This routine makes its own copy of zAff so that the caller is free | - | ||||||||||||||||||
325 | ** to modify zAff after this routine returns. | - | ||||||||||||||||||
326 | */ | - | ||||||||||||||||||
327 | static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ | - | ||||||||||||||||||
328 | Vdbe *v = pParse->pVdbe; | - | ||||||||||||||||||
329 | if( zAff==0 ){
| 8-37176 | ||||||||||||||||||
330 | assert( pParse->db->mallocFailed ); | - | ||||||||||||||||||
331 | return; executed 8 times by 1 test: return; Executed by:
| 8 | ||||||||||||||||||
332 | } | - | ||||||||||||||||||
333 | assert( v!=0 ); | - | ||||||||||||||||||
334 | - | |||||||||||||||||||
335 | /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning | - | ||||||||||||||||||
336 | ** and end of the affinity string. | - | ||||||||||||||||||
337 | */ | - | ||||||||||||||||||
338 | while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
| 894-36383 | ||||||||||||||||||
339 | n--; | - | ||||||||||||||||||
340 | base++; | - | ||||||||||||||||||
341 | zAff++; | - | ||||||||||||||||||
342 | } executed 35489 times by 1 test: end of block Executed by:
| 35489 | ||||||||||||||||||
343 | while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
| 42-37100 | ||||||||||||||||||
344 | n--; | - | ||||||||||||||||||
345 | } executed 42 times by 1 test: end of block Executed by:
| 42 | ||||||||||||||||||
346 | - | |||||||||||||||||||
347 | /* Code the OP_Affinity opcode if there is anything left to do. */ | - | ||||||||||||||||||
348 | if( n>0 ){
| 894-36282 | ||||||||||||||||||
349 | sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); | - | ||||||||||||||||||
350 | } executed 894 times by 1 test: end of block Executed by:
| 894 | ||||||||||||||||||
351 | } executed 37176 times by 2 tests: end of block Executed by:
| 37176 | ||||||||||||||||||
352 | - | |||||||||||||||||||
353 | /* | - | ||||||||||||||||||
354 | ** Expression pRight, which is the RHS of a comparison operation, is | - | ||||||||||||||||||
355 | ** either a vector of n elements or, if n==1, a scalar expression. | - | ||||||||||||||||||
356 | ** Before the comparison operation, affinity zAff is to be applied | - | ||||||||||||||||||
357 | ** to the pRight values. This function modifies characters within the | - | ||||||||||||||||||
358 | ** affinity string to SQLITE_AFF_BLOB if either: | - | ||||||||||||||||||
359 | ** | - | ||||||||||||||||||
360 | ** * the comparison will be performed with no affinity, or | - | ||||||||||||||||||
361 | ** * the affinity change in zAff is guaranteed not to change the value. | - | ||||||||||||||||||
362 | */ | - | ||||||||||||||||||
363 | static void updateRangeAffinityStr( | - | ||||||||||||||||||
364 | Expr *pRight, /* RHS of comparison */ | - | ||||||||||||||||||
365 | int n, /* Number of vector elements in comparison */ | - | ||||||||||||||||||
366 | char *zAff /* Affinity string to modify */ | - | ||||||||||||||||||
367 | ){ | - | ||||||||||||||||||
368 | int i; | - | ||||||||||||||||||
369 | for(i=0; i<n; i++){
| 11895-13882 | ||||||||||||||||||
370 | Expr *p = sqlite3VectorFieldSubexpr(pRight, i); | - | ||||||||||||||||||
371 | if( sqlite3CompareAffinity(p, zAff[i])==SQLITE_AFF_BLOB
| 5014-8868 | ||||||||||||||||||
372 | || sqlite3ExprNeedsNoAffinityChange(p, zAff[i])
| 374-4640 | ||||||||||||||||||
373 | ){ | - | ||||||||||||||||||
374 | zAff[i] = SQLITE_AFF_BLOB; | - | ||||||||||||||||||
375 | } executed 13508 times by 1 test: end of block Executed by:
| 13508 | ||||||||||||||||||
376 | } executed 13882 times by 1 test: end of block Executed by:
| 13882 | ||||||||||||||||||
377 | } executed 11895 times by 1 test: end of block Executed by:
| 11895 | ||||||||||||||||||
378 | - | |||||||||||||||||||
379 | - | |||||||||||||||||||
380 | /* | - | ||||||||||||||||||
381 | ** pX is an expression of the form: (vector) IN (SELECT ...) | - | ||||||||||||||||||
382 | ** In other words, it is a vector IN operator with a SELECT clause on the | - | ||||||||||||||||||
383 | ** LHS. But not all terms in the vector are indexable and the terms might | - | ||||||||||||||||||
384 | ** not be in the correct order for indexing. | - | ||||||||||||||||||
385 | ** | - | ||||||||||||||||||
386 | ** This routine makes a copy of the input pX expression and then adjusts | - | ||||||||||||||||||
387 | ** the vector on the LHS with corresponding changes to the SELECT so that | - | ||||||||||||||||||
388 | ** the vector contains only index terms and those terms are in the correct | - | ||||||||||||||||||
389 | ** order. The modified IN expression is returned. The caller is responsible | - | ||||||||||||||||||
390 | ** for deleting the returned expression. | - | ||||||||||||||||||
391 | ** | - | ||||||||||||||||||
392 | ** Example: | - | ||||||||||||||||||
393 | ** | - | ||||||||||||||||||
394 | ** CREATE TABLE t1(a,b,c,d,e,f); | - | ||||||||||||||||||
395 | ** CREATE INDEX t1x1 ON t1(e,c); | - | ||||||||||||||||||
396 | ** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2) | - | ||||||||||||||||||
397 | ** \_______________________________________/ | - | ||||||||||||||||||
398 | ** The pX expression | - | ||||||||||||||||||
399 | ** | - | ||||||||||||||||||
400 | ** Since only columns e and c can be used with the index, in that order, | - | ||||||||||||||||||
401 | ** the modified IN expression that is returned will be: | - | ||||||||||||||||||
402 | ** | - | ||||||||||||||||||
403 | ** (e,c) IN (SELECT z,x FROM t2) | - | ||||||||||||||||||
404 | ** | - | ||||||||||||||||||
405 | ** The reduced pX is different from the original (obviously) and thus is | - | ||||||||||||||||||
406 | ** only used for indexing, to improve performance. The original unaltered | - | ||||||||||||||||||
407 | ** IN expression must also be run on each output row for correctness. | - | ||||||||||||||||||
408 | */ | - | ||||||||||||||||||
409 | static Expr *removeUnindexableInClauseTerms( | - | ||||||||||||||||||
410 | Parse *pParse, /* The parsing context */ | - | ||||||||||||||||||
411 | int iEq, /* Look at loop terms starting here */ | - | ||||||||||||||||||
412 | WhereLoop *pLoop, /* The current loop */ | - | ||||||||||||||||||
413 | Expr *pX /* The IN expression to be reduced */ | - | ||||||||||||||||||
414 | ){ | - | ||||||||||||||||||
415 | sqlite3 *db = pParse->db; | - | ||||||||||||||||||
416 | Expr *pNew = sqlite3ExprDup(db, pX, 0); | - | ||||||||||||||||||
417 | if( db->mallocFailed==0 ){
| 0-50 | ||||||||||||||||||
418 | ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */ | - | ||||||||||||||||||
419 | ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */ | - | ||||||||||||||||||
420 | ExprList *pRhs = 0; /* New RHS after modifications */ | - | ||||||||||||||||||
421 | ExprList *pLhs = 0; /* New LHS after mods */ | - | ||||||||||||||||||
422 | int i; /* Loop counter */ | - | ||||||||||||||||||
423 | Select *pSelect; /* Pointer to the SELECT on the RHS */ | - | ||||||||||||||||||
424 | - | |||||||||||||||||||
425 | for(i=iEq; i<pLoop->nLTerm; i++){
| 50-82 | ||||||||||||||||||
426 | if( pLoop->aLTerm[i]->pExpr==pX ){
| 3-79 | ||||||||||||||||||
427 | int iField = pLoop->aLTerm[i]->iField - 1; | - | ||||||||||||||||||
428 | assert( pOrigRhs->a[iField].pExpr!=0 ); | - | ||||||||||||||||||
429 | pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); | - | ||||||||||||||||||
430 | pOrigRhs->a[iField].pExpr = 0; | - | ||||||||||||||||||
431 | assert( pOrigLhs->a[iField].pExpr!=0 ); | - | ||||||||||||||||||
432 | pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr); | - | ||||||||||||||||||
433 | pOrigLhs->a[iField].pExpr = 0; | - | ||||||||||||||||||
434 | } executed 79 times by 1 test: end of block Executed by:
| 79 | ||||||||||||||||||
435 | } executed 82 times by 1 test: end of block Executed by:
| 82 | ||||||||||||||||||
436 | sqlite3ExprListDelete(db, pOrigRhs); | - | ||||||||||||||||||
437 | sqlite3ExprListDelete(db, pOrigLhs); | - | ||||||||||||||||||
438 | pNew->pLeft->x.pList = pLhs; | - | ||||||||||||||||||
439 | pNew->x.pSelect->pEList = pRhs; | - | ||||||||||||||||||
440 | if( pLhs && pLhs->nExpr==1 ){
| 0-50 | ||||||||||||||||||
441 | /* Take care here not to generate a TK_VECTOR containing only a | - | ||||||||||||||||||
442 | ** single value. Since the parser never creates such a vector, some | - | ||||||||||||||||||
443 | ** of the subroutines do not handle this case. */ | - | ||||||||||||||||||
444 | Expr *p = pLhs->a[0].pExpr; | - | ||||||||||||||||||
445 | pLhs->a[0].pExpr = 0; | - | ||||||||||||||||||
446 | sqlite3ExprDelete(db, pNew->pLeft); | - | ||||||||||||||||||
447 | pNew->pLeft = p; | - | ||||||||||||||||||
448 | } executed 21 times by 1 test: end of block Executed by:
| 21 | ||||||||||||||||||
449 | pSelect = pNew->x.pSelect; | - | ||||||||||||||||||
450 | if( pSelect->pOrderBy ){
| 3-47 | ||||||||||||||||||
451 | /* If the SELECT statement has an ORDER BY clause, zero the | - | ||||||||||||||||||
452 | ** iOrderByCol variables. These are set to non-zero when an | - | ||||||||||||||||||
453 | ** ORDER BY term exactly matches one of the terms of the | - | ||||||||||||||||||
454 | ** result-set. Since the result-set of the SELECT statement may | - | ||||||||||||||||||
455 | ** have been modified or reordered, these variables are no longer | - | ||||||||||||||||||
456 | ** set correctly. Since setting them is just an optimization, | - | ||||||||||||||||||
457 | ** it's easiest just to zero them here. */ | - | ||||||||||||||||||
458 | ExprList *pOrderBy = pSelect->pOrderBy; | - | ||||||||||||||||||
459 | for(i=0; i<pOrderBy->nExpr; i++){
| 3-6 | ||||||||||||||||||
460 | pOrderBy->a[i].u.x.iOrderByCol = 0; | - | ||||||||||||||||||
461 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||
462 | } executed 3 times by 1 test: end of block Executed by:
| 3 | ||||||||||||||||||
463 | - | |||||||||||||||||||
464 | #if 0 | - | ||||||||||||||||||
465 | printf("For indexing, change the IN expr:\n"); | - | ||||||||||||||||||
466 | sqlite3TreeViewExpr(0, pX, 0); | - | ||||||||||||||||||
467 | printf("Into:\n"); | - | ||||||||||||||||||
468 | sqlite3TreeViewExpr(0, pNew, 0); | - | ||||||||||||||||||
469 | #endif | - | ||||||||||||||||||
470 | } executed 50 times by 1 test: end of block Executed by:
| 50 | ||||||||||||||||||
471 | return pNew; executed 50 times by 1 test: return pNew; Executed by:
| 50 | ||||||||||||||||||
472 | } | - | ||||||||||||||||||
473 | - | |||||||||||||||||||
474 | - | |||||||||||||||||||
475 | /* | - | ||||||||||||||||||
476 | ** Generate code for a single equality term of the WHERE clause. An equality | - | ||||||||||||||||||
477 | ** term can be either X=expr or X IN (...). pTerm is the term to be | - | ||||||||||||||||||
478 | ** coded. | - | ||||||||||||||||||
479 | ** | - | ||||||||||||||||||
480 | ** The current value for the constraint is left in a register, the index | - | ||||||||||||||||||
481 | ** of which is returned. An attempt is made store the result in iTarget but | - | ||||||||||||||||||
482 | ** this is only guaranteed for TK_ISNULL and TK_IN constraints. If the | - | ||||||||||||||||||
483 | ** constraint is a TK_EQ or TK_IS, then the current value might be left in | - | ||||||||||||||||||
484 | ** some other register and it is the caller's responsibility to compensate. | - | ||||||||||||||||||
485 | ** | - | ||||||||||||||||||
486 | ** For a constraint of the form X=expr, the expression is evaluated in | - | ||||||||||||||||||
487 | ** straight-line code. For constraints of the form X IN (...) | - | ||||||||||||||||||
488 | ** this routine sets up a loop that will iterate over all values of X. | - | ||||||||||||||||||
489 | */ | - | ||||||||||||||||||
490 | static int codeEqualityTerm( | - | ||||||||||||||||||
491 | Parse *pParse, /* The parsing context */ | - | ||||||||||||||||||
492 | WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ | - | ||||||||||||||||||
493 | WhereLevel *pLevel, /* The level of the FROM clause we are working on */ | - | ||||||||||||||||||
494 | int iEq, /* Index of the equality term within this level */ | - | ||||||||||||||||||
495 | int bRev, /* True for reverse-order IN operations */ | - | ||||||||||||||||||
496 | int iTarget /* Attempt to leave results in this register */ | - | ||||||||||||||||||
497 | ){ | - | ||||||||||||||||||
498 | Expr *pX = pTerm->pExpr; | - | ||||||||||||||||||
499 | Vdbe *v = pParse->pVdbe; | - | ||||||||||||||||||
500 | int iReg; /* Register holding results */ | - | ||||||||||||||||||
501 | - | |||||||||||||||||||
502 | assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); | - | ||||||||||||||||||
503 | assert( iTarget>0 ); | - | ||||||||||||||||||
504 | if( pX->op==TK_EQ || pX->op==TK_IS ){
| 985-50829 | ||||||||||||||||||
505 | iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); | - | ||||||||||||||||||
506 | }else if( pX->op==TK_ISNULL ){ executed 51858 times by 30 tests: end of block Executed by:
| 172-51858 | ||||||||||||||||||
507 | iReg = iTarget; | - | ||||||||||||||||||
508 | sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); | - | ||||||||||||||||||
509 | #ifndef SQLITE_OMIT_SUBQUERY | - | ||||||||||||||||||
510 | }else{ executed 172 times by 1 test: end of block Executed by:
| 172 | ||||||||||||||||||
511 | int eType = IN_INDEX_NOOP; | - | ||||||||||||||||||
512 | int iTab; | - | ||||||||||||||||||
513 | struct InLoop *pIn; | - | ||||||||||||||||||
514 | WhereLoop *pLoop = pLevel->pWLoop; | - | ||||||||||||||||||
515 | int i; | - | ||||||||||||||||||
516 | int nEq = 0; | - | ||||||||||||||||||
517 | int *aiMap = 0; | - | ||||||||||||||||||
518 | - | |||||||||||||||||||
519 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
| 21-792 | ||||||||||||||||||
520 | && pLoop->u.btree.pIndex!=0
| 74-718 | ||||||||||||||||||
521 | && pLoop->u.btree.pIndex->aSortOrder[iEq]
| 147-571 | ||||||||||||||||||
522 | ){ | - | ||||||||||||||||||
523 | testcase( iEq==0 ); | - | ||||||||||||||||||
524 | testcase( bRev ); | - | ||||||||||||||||||
525 | bRev = !bRev; | - | ||||||||||||||||||
526 | } executed 147 times by 1 test: end of block Executed by:
| 147 | ||||||||||||||||||
527 | assert( pX->op==TK_IN ); | - | ||||||||||||||||||
528 | iReg = iTarget; | - | ||||||||||||||||||
529 | - | |||||||||||||||||||
530 | for(i=0; i<iEq; i++){
| 331-775 | ||||||||||||||||||
531 | if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
| 7-324 | ||||||||||||||||||
532 | disableTerm(pLevel, pTerm); | - | ||||||||||||||||||
533 | return iTarget; executed 38 times by 1 test: return iTarget; Executed by:
| 38 | ||||||||||||||||||
534 | } | - | ||||||||||||||||||
535 | } executed 293 times by 1 test: end of block Executed by:
| 293 | ||||||||||||||||||
536 | for(i=iEq;i<pLoop->nLTerm; i++){
| 775-1142 | ||||||||||||||||||
537 | assert( pLoop->aLTerm[i]!=0 ); | - | ||||||||||||||||||
538 | if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; executed 813 times by 1 test: nEq++; Executed by:
| 329-813 | ||||||||||||||||||
539 | } executed 1142 times by 1 test: end of block Executed by:
| 1142 | ||||||||||||||||||
540 | - | |||||||||||||||||||
541 | if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
| 50-431 | ||||||||||||||||||
542 | eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); | - | ||||||||||||||||||
543 | }else{ executed 725 times by 1 test: end of block Executed by:
| 725 | ||||||||||||||||||
544 | sqlite3 *db = pParse->db; | - | ||||||||||||||||||
545 | pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); | - | ||||||||||||||||||
546 | - | |||||||||||||||||||
547 | if( !db->mallocFailed ){
| 0-50 | ||||||||||||||||||
548 | aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); | - | ||||||||||||||||||
549 | eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); | - | ||||||||||||||||||
550 | pTerm->pExpr->iTable = pX->iTable; | - | ||||||||||||||||||
551 | } executed 50 times by 1 test: end of block Executed by:
| 50 | ||||||||||||||||||
552 | sqlite3ExprDelete(db, pX); | - | ||||||||||||||||||
553 | pX = pTerm->pExpr; | - | ||||||||||||||||||
554 | } executed 50 times by 1 test: end of block Executed by:
| 50 | ||||||||||||||||||
555 | - | |||||||||||||||||||
556 | if( eType==IN_INDEX_INDEX_DESC ){
| 97-678 | ||||||||||||||||||
557 | testcase( bRev ); | - | ||||||||||||||||||
558 | bRev = !bRev; | - | ||||||||||||||||||
559 | } executed 97 times by 1 test: end of block Executed by:
| 97 | ||||||||||||||||||
560 | iTab = pX->iTable; | - | ||||||||||||||||||
561 | sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); | - | ||||||||||||||||||
562 | VdbeCoverageIf(v, bRev); | - | ||||||||||||||||||
563 | VdbeCoverageIf(v, !bRev); | - | ||||||||||||||||||
564 | assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); | - | ||||||||||||||||||
565 | - | |||||||||||||||||||
566 | pLoop->wsFlags |= WHERE_IN_ABLE; | - | ||||||||||||||||||
567 | if( pLevel->u.in.nIn==0 ){
| 96-679 | ||||||||||||||||||
568 | pLevel->addrNxt = sqlite3VdbeMakeLabel(v); | - | ||||||||||||||||||
569 | } executed 679 times by 1 test: end of block Executed by:
| 679 | ||||||||||||||||||
570 | - | |||||||||||||||||||
571 | i = pLevel->u.in.nIn; | - | ||||||||||||||||||
572 | pLevel->u.in.nIn += nEq; | - | ||||||||||||||||||
573 | pLevel->u.in.aInLoop = | - | ||||||||||||||||||
574 | sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, | - | ||||||||||||||||||
575 | sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); | - | ||||||||||||||||||
576 | pIn = pLevel->u.in.aInLoop; | - | ||||||||||||||||||
577 | if( pIn ){
| 0-775 | ||||||||||||||||||
578 | int iMap = 0; /* Index in aiMap[] */ | - | ||||||||||||||||||
579 | pIn += i; | - | ||||||||||||||||||
580 | for(i=iEq;i<pLoop->nLTerm; i++){
| 775-1142 | ||||||||||||||||||
581 | if( pLoop->aLTerm[i]->pExpr==pX ){
| 329-813 | ||||||||||||||||||
582 | int iOut = iReg + i - iEq; | - | ||||||||||||||||||
583 | if( eType==IN_INDEX_ROWID ){
| 74-739 | ||||||||||||||||||
584 | testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */ | - | ||||||||||||||||||
585 | pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut); | - | ||||||||||||||||||
586 | }else{ executed 74 times by 1 test: end of block Executed by:
| 74 | ||||||||||||||||||
587 | int iCol = aiMap ? aiMap[iMap++] : 0;
| 79-660 | ||||||||||||||||||
588 | pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut); | - | ||||||||||||||||||
589 | } executed 739 times by 1 test: end of block Executed by:
| 739 | ||||||||||||||||||
590 | sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); | - | ||||||||||||||||||
591 | if( i==iEq ){
| 38-775 | ||||||||||||||||||
592 | pIn->iCur = iTab; | - | ||||||||||||||||||
593 | pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
| 162-613 | ||||||||||||||||||
594 | if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
| 1-519 | ||||||||||||||||||
595 | pIn->iBase = iReg - i; | - | ||||||||||||||||||
596 | pIn->nPrefix = i; | - | ||||||||||||||||||
597 | pLoop->wsFlags |= WHERE_IN_EARLYOUT; | - | ||||||||||||||||||
598 | }else{ executed 255 times by 1 test: end of block Executed by:
| 255 | ||||||||||||||||||
599 | pIn->nPrefix = 0; | - | ||||||||||||||||||
600 | } executed 520 times by 1 test: end of block Executed by:
| 520 | ||||||||||||||||||
601 | }else{ | - | ||||||||||||||||||
602 | pIn->eEndLoopOp = OP_Noop; | - | ||||||||||||||||||
603 | } executed 38 times by 1 test: end of block Executed by:
| 38 | ||||||||||||||||||
604 | pIn++; | - | ||||||||||||||||||
605 | } executed 813 times by 1 test: end of block Executed by:
| 813 | ||||||||||||||||||
606 | } executed 1142 times by 1 test: end of block Executed by:
| 1142 | ||||||||||||||||||
607 | }else{ executed 775 times by 1 test: end of block Executed by:
| 775 | ||||||||||||||||||
608 | pLevel->u.in.nIn = 0; | - | ||||||||||||||||||
609 | } never executed: end of block | 0 | ||||||||||||||||||
610 | sqlite3DbFree(pParse->db, aiMap); | - | ||||||||||||||||||
611 | #endif | - | ||||||||||||||||||
612 | } executed 775 times by 1 test: end of block Executed by:
| 775 | ||||||||||||||||||
613 | disableTerm(pLevel, pTerm); | - | ||||||||||||||||||
614 | return iReg; executed 52805 times by 30 tests: return iReg; Executed by:
| 52805 | ||||||||||||||||||
615 | } | - | ||||||||||||||||||
616 | - | |||||||||||||||||||
617 | /* | - | ||||||||||||||||||
618 | ** Generate code that will evaluate all == and IN constraints for an | - | ||||||||||||||||||
619 | ** index scan. | - | ||||||||||||||||||
620 | ** | - | ||||||||||||||||||
621 | ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). | - | ||||||||||||||||||
622 | ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 | - | ||||||||||||||||||
623 | ** The index has as many as three equality constraints, but in this | - | ||||||||||||||||||
624 | ** example, the third "c" value is an inequality. So only two | - | ||||||||||||||||||
625 | ** constraints are coded. This routine will generate code to evaluate | - | ||||||||||||||||||
626 | ** a==5 and b IN (1,2,3). The current values for a and b will be stored | - | ||||||||||||||||||
627 | ** in consecutive registers and the index of the first register is returned. | - | ||||||||||||||||||
628 | ** | - | ||||||||||||||||||
629 | ** In the example above nEq==2. But this subroutine works for any value | - | ||||||||||||||||||
630 | ** of nEq including 0. If nEq==0, this routine is nearly a no-op. | - | ||||||||||||||||||
631 | ** The only thing it does is allocate the pLevel->iMem memory cell and | - | ||||||||||||||||||
632 | ** compute the affinity string. | - | ||||||||||||||||||
633 | ** | - | ||||||||||||||||||
634 | ** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints | - | ||||||||||||||||||
635 | ** are == or IN and are covered by the nEq. nExtraReg is 1 if there is | - | ||||||||||||||||||
636 | ** an inequality constraint (such as the "c>=5 AND c<10" in the example) that | - | ||||||||||||||||||
637 | ** occurs after the nEq quality constraints. | - | ||||||||||||||||||
638 | ** | - | ||||||||||||||||||
639 | ** This routine allocates a range of nEq+nExtraReg memory cells and returns | - | ||||||||||||||||||
640 | ** the index of the first memory cell in that range. The code that | - | ||||||||||||||||||
641 | ** calls this routine will use that memory range to store keys for | - | ||||||||||||||||||
642 | ** start and termination conditions of the loop. | - | ||||||||||||||||||
643 | ** key value of the loop. If one or more IN operators appear, then | - | ||||||||||||||||||
644 | ** this routine allocates an additional nEq memory cells for internal | - | ||||||||||||||||||
645 | ** use. | - | ||||||||||||||||||
646 | ** | - | ||||||||||||||||||
647 | ** Before returning, *pzAff is set to point to a buffer containing a | - | ||||||||||||||||||
648 | ** copy of the column affinity string of the index allocated using | - | ||||||||||||||||||
649 | ** sqlite3DbMalloc(). Except, entries in the copy of the string associated | - | ||||||||||||||||||
650 | ** with equality constraints that use BLOB or NONE affinity are set to | - | ||||||||||||||||||
651 | ** SQLITE_AFF_BLOB. This is to deal with SQL such as the following: | - | ||||||||||||||||||
652 | ** | - | ||||||||||||||||||
653 | ** CREATE TABLE t1(a TEXT PRIMARY KEY, b); | - | ||||||||||||||||||
654 | ** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b; | - | ||||||||||||||||||
655 | ** | - | ||||||||||||||||||
656 | ** In the example above, the index on t1(a) has TEXT affinity. But since | - | ||||||||||||||||||
657 | ** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity, | - | ||||||||||||||||||
658 | ** no conversion should be attempted before using a t2.b value as part of | - | ||||||||||||||||||
659 | ** a key to search the index. Hence the first byte in the returned affinity | - | ||||||||||||||||||
660 | ** string in this example would be set to SQLITE_AFF_BLOB. | - | ||||||||||||||||||
661 | */ | - | ||||||||||||||||||
662 | static int codeAllEqualityTerms( | - | ||||||||||||||||||
663 | Parse *pParse, /* Parsing context */ | - | ||||||||||||||||||
664 | WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ | - | ||||||||||||||||||
665 | int bRev, /* Reverse the order of IN operators */ | - | ||||||||||||||||||
666 | int nExtraReg, /* Number of extra registers to allocate */ | - | ||||||||||||||||||
667 | char **pzAff /* OUT: Set to point to affinity string */ | - | ||||||||||||||||||
668 | ){ | - | ||||||||||||||||||
669 | u16 nEq; /* The number of == or IN constraints to code */ | - | ||||||||||||||||||
670 | u16 nSkip; /* Number of left-most columns to skip */ | - | ||||||||||||||||||
671 | Vdbe *v = pParse->pVdbe; /* The vm under construction */ | - | ||||||||||||||||||
672 | Index *pIdx; /* The index being used for this loop */ | - | ||||||||||||||||||
673 | WhereTerm *pTerm; /* A single constraint term */ | - | ||||||||||||||||||
674 | WhereLoop *pLoop; /* The WhereLoop object */ | - | ||||||||||||||||||
675 | int j; /* Loop counter */ | - | ||||||||||||||||||
676 | int regBase; /* Base register */ | - | ||||||||||||||||||
677 | int nReg; /* Number of registers to allocate */ | - | ||||||||||||||||||
678 | char *zAff; /* Affinity string to return */ | - | ||||||||||||||||||
679 | - | |||||||||||||||||||
680 | /* This module is only called on query plans that use an index. */ | - | ||||||||||||||||||
681 | pLoop = pLevel->pWLoop; | - | ||||||||||||||||||
682 | assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); | - | ||||||||||||||||||
683 | nEq = pLoop->u.btree.nEq; | - | ||||||||||||||||||
684 | nSkip = pLoop->nSkip; | - | ||||||||||||||||||
685 | pIdx = pLoop->u.btree.pIndex; | - | ||||||||||||||||||
686 | assert( pIdx!=0 ); | - | ||||||||||||||||||
687 | - | |||||||||||||||||||
688 | /* Figure out how many memory cells we will need then allocate them. | - | ||||||||||||||||||
689 | */ | - | ||||||||||||||||||
690 | regBase = pParse->nMem + 1; | - | ||||||||||||||||||
691 | nReg = pLoop->u.btree.nEq + nExtraReg; | - | ||||||||||||||||||
692 | pParse->nMem += nReg; | - | ||||||||||||||||||
693 | - | |||||||||||||||||||
694 | zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); | - | ||||||||||||||||||
695 | assert( zAff!=0 || pParse->db->mallocFailed ); | - | ||||||||||||||||||
696 | - | |||||||||||||||||||
697 | if( nSkip ){
| 44-31233 | ||||||||||||||||||
698 | int iIdxCur = pLevel->iIdxCur; | - | ||||||||||||||||||
699 | sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); | - | ||||||||||||||||||
700 | VdbeCoverageIf(v, bRev==0); | - | ||||||||||||||||||
701 | VdbeCoverageIf(v, bRev!=0); | - | ||||||||||||||||||
702 | VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); | - | ||||||||||||||||||
703 | j = sqlite3VdbeAddOp0(v, OP_Goto); | - | ||||||||||||||||||
704 | pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), | - | ||||||||||||||||||
705 | iIdxCur, 0, regBase, nSkip); | - | ||||||||||||||||||
706 | VdbeCoverageIf(v, bRev==0); | - | ||||||||||||||||||
707 | VdbeCoverageIf(v, bRev!=0); | - | ||||||||||||||||||
708 | sqlite3VdbeJumpHere(v, j); | - | ||||||||||||||||||
709 | for(j=0; j<nSkip; j++){
| 44-64 | ||||||||||||||||||
710 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); | - | ||||||||||||||||||
711 | testcase( pIdx->aiColumn[j]==XN_EXPR ); | - | ||||||||||||||||||
712 | VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); | - | ||||||||||||||||||
713 | } executed 64 times by 1 test: end of block Executed by:
| 64 | ||||||||||||||||||
714 | } executed 44 times by 1 test: end of block Executed by:
| 44 | ||||||||||||||||||
715 | - | |||||||||||||||||||
716 | /* Evaluate the equality constraints | - | ||||||||||||||||||
717 | */ | - | ||||||||||||||||||
718 | assert( zAff==0 || (int)strlen(zAff)>=nEq ); | - | ||||||||||||||||||
719 | for(j=nSkip; j<nEq; j++){
| 22589-31277 | ||||||||||||||||||
720 | int r1; | - | ||||||||||||||||||
721 | pTerm = pLoop->aLTerm[j]; | - | ||||||||||||||||||
722 | assert( pTerm!=0 ); | - | ||||||||||||||||||
723 | /* The following testcase is true for indices with redundant columns. | - | ||||||||||||||||||
724 | ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ | - | ||||||||||||||||||
725 | testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); | - | ||||||||||||||||||
726 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
727 | r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); | - | ||||||||||||||||||
728 | if( r1!=regBase+j ){
| 988-21601 | ||||||||||||||||||
729 | if( nReg==1 ){
| 195-793 | ||||||||||||||||||
730 | sqlite3ReleaseTempReg(pParse, regBase); | - | ||||||||||||||||||
731 | regBase = r1; | - | ||||||||||||||||||
732 | }else{ executed 195 times by 1 test: end of block Executed by:
| 195 | ||||||||||||||||||
733 | sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); | - | ||||||||||||||||||
734 | } executed 793 times by 1 test: end of block Executed by:
| 793 | ||||||||||||||||||
735 | } | - | ||||||||||||||||||
736 | if( pTerm->eOperator & WO_IN ){
| 718-21871 | ||||||||||||||||||
737 | if( pTerm->pExpr->flags & EP_xIsSelect ){
| 286-432 | ||||||||||||||||||
738 | /* No affinity ever needs to be (or should be) applied to a value | - | ||||||||||||||||||
739 | ** from the RHS of an "? IN (SELECT ...)" expression. The | - | ||||||||||||||||||
740 | ** sqlite3FindInIndex() routine has already ensured that the | - | ||||||||||||||||||
741 | ** affinity of the comparison has been applied to the value. */ | - | ||||||||||||||||||
742 | if( zAff ) zAff[j] = SQLITE_AFF_BLOB; executed 432 times by 1 test: zAff[j] = 'A'; Executed by:
| 0-432 | ||||||||||||||||||
743 | } executed 432 times by 1 test: end of block Executed by:
| 432 | ||||||||||||||||||
744 | }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ executed 718 times by 1 test: end of block Executed by:
| 172-21699 | ||||||||||||||||||
745 | Expr *pRight = pTerm->pExpr->pRight; | - | ||||||||||||||||||
746 | if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
| 1022-20677 | ||||||||||||||||||
747 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); | - | ||||||||||||||||||
748 | VdbeCoverage(v); | - | ||||||||||||||||||
749 | } executed 6202 times by 1 test: end of block Executed by:
| 6202 | ||||||||||||||||||
750 | if( zAff ){
| 24-21675 | ||||||||||||||||||
751 | if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
| 1896-19779 | ||||||||||||||||||
752 | zAff[j] = SQLITE_AFF_BLOB; | - | ||||||||||||||||||
753 | } executed 19779 times by 1 test: end of block Executed by:
| 19779 | ||||||||||||||||||
754 | if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
| 405-21270 | ||||||||||||||||||
755 | zAff[j] = SQLITE_AFF_BLOB; | - | ||||||||||||||||||
756 | } executed 21270 times by 1 test: end of block Executed by:
| 21270 | ||||||||||||||||||
757 | } executed 21675 times by 1 test: end of block Executed by:
| 21675 | ||||||||||||||||||
758 | } executed 21699 times by 1 test: end of block Executed by:
| 21699 | ||||||||||||||||||
759 | } executed 22589 times by 1 test: end of block Executed by:
| 22589 | ||||||||||||||||||
760 | *pzAff = zAff; | - | ||||||||||||||||||
761 | return regBase; executed 31277 times by 2 tests: return regBase; Executed by:
| 31277 | ||||||||||||||||||
762 | } | - | ||||||||||||||||||
763 | - | |||||||||||||||||||
764 | #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS | - | ||||||||||||||||||
765 | /* | - | ||||||||||||||||||
766 | ** If the most recently coded instruction is a constant range constraint | - | ||||||||||||||||||
767 | ** (a string literal) that originated from the LIKE optimization, then | - | ||||||||||||||||||
768 | ** set P3 and P5 on the OP_String opcode so that the string will be cast | - | ||||||||||||||||||
769 | ** to a BLOB at appropriate times. | - | ||||||||||||||||||
770 | ** | - | ||||||||||||||||||
771 | ** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range | - | ||||||||||||||||||
772 | ** expression: "x>='ABC' AND x<'abd'". But this requires that the range | - | ||||||||||||||||||
773 | ** scan loop run twice, once for strings and a second time for BLOBs. | - | ||||||||||||||||||
774 | ** The OP_String opcodes on the second pass convert the upper and lower | - | ||||||||||||||||||
775 | ** bound string constants to blobs. This routine makes the necessary changes | - | ||||||||||||||||||
776 | ** to the OP_String opcodes for that to happen. | - | ||||||||||||||||||
777 | ** | - | ||||||||||||||||||
778 | ** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then | - | ||||||||||||||||||
779 | ** only the one pass through the string space is required, so this routine | - | ||||||||||||||||||
780 | ** becomes a no-op. | - | ||||||||||||||||||
781 | */ | - | ||||||||||||||||||
782 | static void whereLikeOptimizationStringFixup( | - | ||||||||||||||||||
783 | Vdbe *v, /* prepared statement under construction */ | - | ||||||||||||||||||
784 | WhereLevel *pLevel, /* The loop that contains the LIKE operator */ | - | ||||||||||||||||||
785 | WhereTerm *pTerm /* The upper or lower bound just coded */ | - | ||||||||||||||||||
786 | ){ | - | ||||||||||||||||||
787 | if( pTerm->wtFlags & TERM_LIKEOPT ){
| 3452-8453 | ||||||||||||||||||
788 | VdbeOp *pOp; | - | ||||||||||||||||||
789 | assert( pLevel->iLikeRepCntr>0 ); | - | ||||||||||||||||||
790 | pOp = sqlite3VdbeGetOp(v, -1); | - | ||||||||||||||||||
791 | assert( pOp!=0 ); | - | ||||||||||||||||||
792 | assert( pOp->opcode==OP_String8 | - | ||||||||||||||||||
793 | || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); | - | ||||||||||||||||||
794 | pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */ | - | ||||||||||||||||||
795 | pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */ | - | ||||||||||||||||||
796 | } executed 3452 times by 1 test: end of block Executed by:
| 3452 | ||||||||||||||||||
797 | } executed 11905 times by 1 test: end of block Executed by:
| 11905 | ||||||||||||||||||
798 | #else | - | ||||||||||||||||||
799 | # define whereLikeOptimizationStringFixup(A,B,C) | - | ||||||||||||||||||
800 | #endif | - | ||||||||||||||||||
801 | - | |||||||||||||||||||
802 | #ifdef SQLITE_ENABLE_CURSOR_HINTS | - | ||||||||||||||||||
803 | /* | - | ||||||||||||||||||
804 | ** Information is passed from codeCursorHint() down to individual nodes of | - | ||||||||||||||||||
805 | ** the expression tree (by sqlite3WalkExpr()) using an instance of this | - | ||||||||||||||||||
806 | ** structure. | - | ||||||||||||||||||
807 | */ | - | ||||||||||||||||||
808 | struct CCurHint { | - | ||||||||||||||||||
809 | int iTabCur; /* Cursor for the main table */ | - | ||||||||||||||||||
810 | int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */ | - | ||||||||||||||||||
811 | Index *pIdx; /* The index used to access the table */ | - | ||||||||||||||||||
812 | }; | - | ||||||||||||||||||
813 | - | |||||||||||||||||||
814 | /* | - | ||||||||||||||||||
815 | ** This function is called for every node of an expression that is a candidate | - | ||||||||||||||||||
816 | ** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference | - | ||||||||||||||||||
817 | ** the table CCurHint.iTabCur, verify that the same column can be | - | ||||||||||||||||||
818 | ** accessed through the index. If it cannot, then set pWalker->eCode to 1. | - | ||||||||||||||||||
819 | */ | - | ||||||||||||||||||
820 | static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ | - | ||||||||||||||||||
821 | struct CCurHint *pHint = pWalker->u.pCCurHint; | - | ||||||||||||||||||
822 | assert( pHint->pIdx!=0 ); | - | ||||||||||||||||||
823 | if( pExpr->op==TK_COLUMN | - | ||||||||||||||||||
824 | && pExpr->iTable==pHint->iTabCur | - | ||||||||||||||||||
825 | && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0 | - | ||||||||||||||||||
826 | ){ | - | ||||||||||||||||||
827 | pWalker->eCode = 1; | - | ||||||||||||||||||
828 | } | - | ||||||||||||||||||
829 | return WRC_Continue; | - | ||||||||||||||||||
830 | } | - | ||||||||||||||||||
831 | - | |||||||||||||||||||
832 | /* | - | ||||||||||||||||||
833 | ** Test whether or not expression pExpr, which was part of a WHERE clause, | - | ||||||||||||||||||
834 | ** should be included in the cursor-hint for a table that is on the rhs | - | ||||||||||||||||||
835 | ** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the | - | ||||||||||||||||||
836 | ** expression is not suitable. | - | ||||||||||||||||||
837 | ** | - | ||||||||||||||||||
838 | ** An expression is unsuitable if it might evaluate to non NULL even if | - | ||||||||||||||||||
839 | ** a TK_COLUMN node that does affect the value of the expression is set | - | ||||||||||||||||||
840 | ** to NULL. For example: | - | ||||||||||||||||||
841 | ** | - | ||||||||||||||||||
842 | ** col IS NULL | - | ||||||||||||||||||
843 | ** col IS NOT NULL | - | ||||||||||||||||||
844 | ** coalesce(col, 1) | - | ||||||||||||||||||
845 | ** CASE WHEN col THEN 0 ELSE 1 END | - | ||||||||||||||||||
846 | */ | - | ||||||||||||||||||
847 | static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ | - | ||||||||||||||||||
848 | if( pExpr->op==TK_IS | - | ||||||||||||||||||
849 | || pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT | - | ||||||||||||||||||
850 | || pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE | - | ||||||||||||||||||
851 | ){ | - | ||||||||||||||||||
852 | pWalker->eCode = 1; | - | ||||||||||||||||||
853 | }else if( pExpr->op==TK_FUNCTION ){ | - | ||||||||||||||||||
854 | int d1; | - | ||||||||||||||||||
855 | char d2[4]; | - | ||||||||||||||||||
856 | if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ | - | ||||||||||||||||||
857 | pWalker->eCode = 1; | - | ||||||||||||||||||
858 | } | - | ||||||||||||||||||
859 | } | - | ||||||||||||||||||
860 | - | |||||||||||||||||||
861 | return WRC_Continue; | - | ||||||||||||||||||
862 | } | - | ||||||||||||||||||
863 | - | |||||||||||||||||||
864 | - | |||||||||||||||||||
865 | /* | - | ||||||||||||||||||
866 | ** This function is called on every node of an expression tree used as an | - | ||||||||||||||||||
867 | ** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN | - | ||||||||||||||||||
868 | ** that accesses any table other than the one identified by | - | ||||||||||||||||||
869 | ** CCurHint.iTabCur, then do the following: | - | ||||||||||||||||||
870 | ** | - | ||||||||||||||||||
871 | ** 1) allocate a register and code an OP_Column instruction to read | - | ||||||||||||||||||
872 | ** the specified column into the new register, and | - | ||||||||||||||||||
873 | ** | - | ||||||||||||||||||
874 | ** 2) transform the expression node to a TK_REGISTER node that reads | - | ||||||||||||||||||
875 | ** from the newly populated register. | - | ||||||||||||||||||
876 | ** | - | ||||||||||||||||||
877 | ** Also, if the node is a TK_COLUMN that does access the table idenified | - | ||||||||||||||||||
878 | ** by pCCurHint.iTabCur, and an index is being used (which we will | - | ||||||||||||||||||
879 | ** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into | - | ||||||||||||||||||
880 | ** an access of the index rather than the original table. | - | ||||||||||||||||||
881 | */ | - | ||||||||||||||||||
882 | static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ | - | ||||||||||||||||||
883 | int rc = WRC_Continue; | - | ||||||||||||||||||
884 | struct CCurHint *pHint = pWalker->u.pCCurHint; | - | ||||||||||||||||||
885 | if( pExpr->op==TK_COLUMN ){ | - | ||||||||||||||||||
886 | if( pExpr->iTable!=pHint->iTabCur ){ | - | ||||||||||||||||||
887 | int reg = ++pWalker->pParse->nMem; /* Register for column value */ | - | ||||||||||||||||||
888 | sqlite3ExprCode(pWalker->pParse, pExpr, reg); | - | ||||||||||||||||||
889 | pExpr->op = TK_REGISTER; | - | ||||||||||||||||||
890 | pExpr->iTable = reg; | - | ||||||||||||||||||
891 | }else if( pHint->pIdx!=0 ){ | - | ||||||||||||||||||
892 | pExpr->iTable = pHint->iIdxCur; | - | ||||||||||||||||||
893 | pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); | - | ||||||||||||||||||
894 | assert( pExpr->iColumn>=0 ); | - | ||||||||||||||||||
895 | } | - | ||||||||||||||||||
896 | }else if( pExpr->op==TK_AGG_FUNCTION ){ | - | ||||||||||||||||||
897 | /* An aggregate function in the WHERE clause of a query means this must | - | ||||||||||||||||||
898 | ** be a correlated sub-query, and expression pExpr is an aggregate from | - | ||||||||||||||||||
899 | ** the parent context. Do not walk the function arguments in this case. | - | ||||||||||||||||||
900 | ** | - | ||||||||||||||||||
901 | ** todo: It should be possible to replace this node with a TK_REGISTER | - | ||||||||||||||||||
902 | ** expression, as the result of the expression must be stored in a | - | ||||||||||||||||||
903 | ** register at this point. The same holds for TK_AGG_COLUMN nodes. */ | - | ||||||||||||||||||
904 | rc = WRC_Prune; | - | ||||||||||||||||||
905 | } | - | ||||||||||||||||||
906 | return rc; | - | ||||||||||||||||||
907 | } | - | ||||||||||||||||||
908 | - | |||||||||||||||||||
909 | /* | - | ||||||||||||||||||
910 | ** Insert an OP_CursorHint instruction if it is appropriate to do so. | - | ||||||||||||||||||
911 | */ | - | ||||||||||||||||||
912 | static void codeCursorHint( | - | ||||||||||||||||||
913 | struct SrcList_item *pTabItem, /* FROM clause item */ | - | ||||||||||||||||||
914 | WhereInfo *pWInfo, /* The where clause */ | - | ||||||||||||||||||
915 | WhereLevel *pLevel, /* Which loop to provide hints for */ | - | ||||||||||||||||||
916 | WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */ | - | ||||||||||||||||||
917 | ){ | - | ||||||||||||||||||
918 | Parse *pParse = pWInfo->pParse; | - | ||||||||||||||||||
919 | sqlite3 *db = pParse->db; | - | ||||||||||||||||||
920 | Vdbe *v = pParse->pVdbe; | - | ||||||||||||||||||
921 | Expr *pExpr = 0; | - | ||||||||||||||||||
922 | WhereLoop *pLoop = pLevel->pWLoop; | - | ||||||||||||||||||
923 | int iCur; | - | ||||||||||||||||||
924 | WhereClause *pWC; | - | ||||||||||||||||||
925 | WhereTerm *pTerm; | - | ||||||||||||||||||
926 | int i, j; | - | ||||||||||||||||||
927 | struct CCurHint sHint; | - | ||||||||||||||||||
928 | Walker sWalker; | - | ||||||||||||||||||
929 | - | |||||||||||||||||||
930 | if( OptimizationDisabled(db, SQLITE_CursorHints) ) return; | - | ||||||||||||||||||
931 | iCur = pLevel->iTabCur; | - | ||||||||||||||||||
932 | assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor ); | - | ||||||||||||||||||
933 | sHint.iTabCur = iCur; | - | ||||||||||||||||||
934 | sHint.iIdxCur = pLevel->iIdxCur; | - | ||||||||||||||||||
935 | sHint.pIdx = pLoop->u.btree.pIndex; | - | ||||||||||||||||||
936 | memset(&sWalker, 0, sizeof(sWalker)); | - | ||||||||||||||||||
937 | sWalker.pParse = pParse; | - | ||||||||||||||||||
938 | sWalker.u.pCCurHint = &sHint; | - | ||||||||||||||||||
939 | pWC = &pWInfo->sWC; | - | ||||||||||||||||||
940 | for(i=0; i<pWC->nTerm; i++){ | - | ||||||||||||||||||
941 | pTerm = &pWC->a[i]; | - | ||||||||||||||||||
942 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; | - | ||||||||||||||||||
943 | if( pTerm->prereqAll & pLevel->notReady ) continue; | - | ||||||||||||||||||
944 | - | |||||||||||||||||||
945 | /* Any terms specified as part of the ON(...) clause for any LEFT | - | ||||||||||||||||||
946 | ** JOIN for which the current table is not the rhs are omitted | - | ||||||||||||||||||
947 | ** from the cursor-hint. | - | ||||||||||||||||||
948 | ** | - | ||||||||||||||||||
949 | ** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms | - | ||||||||||||||||||
950 | ** that were specified as part of the WHERE clause must be excluded. | - | ||||||||||||||||||
951 | ** This is to address the following: | - | ||||||||||||||||||
952 | ** | - | ||||||||||||||||||
953 | ** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL; | - | ||||||||||||||||||
954 | ** | - | ||||||||||||||||||
955 | ** Say there is a single row in t2 that matches (t1.a=t2.b), but its | - | ||||||||||||||||||
956 | ** t2.c values is not NULL. If the (t2.c IS NULL) constraint is | - | ||||||||||||||||||
957 | ** pushed down to the cursor, this row is filtered out, causing | - | ||||||||||||||||||
958 | ** SQLite to synthesize a row of NULL values. Which does match the | - | ||||||||||||||||||
959 | ** WHERE clause, and so the query returns a row. Which is incorrect. | - | ||||||||||||||||||
960 | ** | - | ||||||||||||||||||
961 | ** For the same reason, WHERE terms such as: | - | ||||||||||||||||||
962 | ** | - | ||||||||||||||||||
963 | ** WHERE 1 = (t2.c IS NULL) | - | ||||||||||||||||||
964 | ** | - | ||||||||||||||||||
965 | ** are also excluded. See codeCursorHintIsOrFunction() for details. | - | ||||||||||||||||||
966 | */ | - | ||||||||||||||||||
967 | if( pTabItem->fg.jointype & JT_LEFT ){ | - | ||||||||||||||||||
968 | Expr *pExpr = pTerm->pExpr; | - | ||||||||||||||||||
969 | if( !ExprHasProperty(pExpr, EP_FromJoin) | - | ||||||||||||||||||
970 | || pExpr->iRightJoinTable!=pTabItem->iCursor | - | ||||||||||||||||||
971 | ){ | - | ||||||||||||||||||
972 | sWalker.eCode = 0; | - | ||||||||||||||||||
973 | sWalker.xExprCallback = codeCursorHintIsOrFunction; | - | ||||||||||||||||||
974 | sqlite3WalkExpr(&sWalker, pTerm->pExpr); | - | ||||||||||||||||||
975 | if( sWalker.eCode ) continue; | - | ||||||||||||||||||
976 | } | - | ||||||||||||||||||
977 | }else{ | - | ||||||||||||||||||
978 | if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; | - | ||||||||||||||||||
979 | } | - | ||||||||||||||||||
980 | - | |||||||||||||||||||
981 | /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize | - | ||||||||||||||||||
982 | ** the cursor. These terms are not needed as hints for a pure range | - | ||||||||||||||||||
983 | ** scan (that has no == terms) so omit them. */ | - | ||||||||||||||||||
984 | if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){ | - | ||||||||||||||||||
985 | for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){} | - | ||||||||||||||||||
986 | if( j<pLoop->nLTerm ) continue; | - | ||||||||||||||||||
987 | } | - | ||||||||||||||||||
988 | - | |||||||||||||||||||
989 | /* No subqueries or non-deterministic functions allowed */ | - | ||||||||||||||||||
990 | if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue; | - | ||||||||||||||||||
991 | - | |||||||||||||||||||
992 | /* For an index scan, make sure referenced columns are actually in | - | ||||||||||||||||||
993 | ** the index. */ | - | ||||||||||||||||||
994 | if( sHint.pIdx!=0 ){ | - | ||||||||||||||||||
995 | sWalker.eCode = 0; | - | ||||||||||||||||||
996 | sWalker.xExprCallback = codeCursorHintCheckExpr; | - | ||||||||||||||||||
997 | sqlite3WalkExpr(&sWalker, pTerm->pExpr); | - | ||||||||||||||||||
998 | if( sWalker.eCode ) continue; | - | ||||||||||||||||||
999 | } | - | ||||||||||||||||||
1000 | - | |||||||||||||||||||
1001 | /* If we survive all prior tests, that means this term is worth hinting */ | - | ||||||||||||||||||
1002 | pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); | - | ||||||||||||||||||
1003 | } | - | ||||||||||||||||||
1004 | if( pExpr!=0 ){ | - | ||||||||||||||||||
1005 | sWalker.xExprCallback = codeCursorHintFixExpr; | - | ||||||||||||||||||
1006 | sqlite3WalkExpr(&sWalker, pExpr); | - | ||||||||||||||||||
1007 | sqlite3VdbeAddOp4(v, OP_CursorHint, | - | ||||||||||||||||||
1008 | (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, | - | ||||||||||||||||||
1009 | (const char*)pExpr, P4_EXPR); | - | ||||||||||||||||||
1010 | } | - | ||||||||||||||||||
1011 | } | - | ||||||||||||||||||
1012 | #else | - | ||||||||||||||||||
1013 | # define codeCursorHint(A,B,C,D) /* No-op */ | - | ||||||||||||||||||
1014 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ | - | ||||||||||||||||||
1015 | - | |||||||||||||||||||
1016 | /* | - | ||||||||||||||||||
1017 | ** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains | - | ||||||||||||||||||
1018 | ** a rowid value just read from cursor iIdxCur, open on index pIdx. This | - | ||||||||||||||||||
1019 | ** function generates code to do a deferred seek of cursor iCur to the | - | ||||||||||||||||||
1020 | ** rowid stored in register iRowid. | - | ||||||||||||||||||
1021 | ** | - | ||||||||||||||||||
1022 | ** Normally, this is just: | - | ||||||||||||||||||
1023 | ** | - | ||||||||||||||||||
1024 | ** OP_DeferredSeek $iCur $iRowid | - | ||||||||||||||||||
1025 | ** | - | ||||||||||||||||||
1026 | ** However, if the scan currently being coded is a branch of an OR-loop and | - | ||||||||||||||||||
1027 | ** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek | - | ||||||||||||||||||
1028 | ** is set to iIdxCur and P4 is set to point to an array of integers | - | ||||||||||||||||||
1029 | ** containing one entry for each column of the table cursor iCur is open | - | ||||||||||||||||||
1030 | ** on. For each table column, if the column is the i'th column of the | - | ||||||||||||||||||
1031 | ** index, then the corresponding array entry is set to (i+1). If the column | - | ||||||||||||||||||
1032 | ** does not appear in the index at all, the array entry is set to 0. | - | ||||||||||||||||||
1033 | */ | - | ||||||||||||||||||
1034 | static void codeDeferredSeek( | - | ||||||||||||||||||
1035 | WhereInfo *pWInfo, /* Where clause context */ | - | ||||||||||||||||||
1036 | Index *pIdx, /* Index scan is using */ | - | ||||||||||||||||||
1037 | int iCur, /* Cursor for IPK b-tree */ | - | ||||||||||||||||||
1038 | int iIdxCur /* Index cursor */ | - | ||||||||||||||||||
1039 | ){ | - | ||||||||||||||||||
1040 | Parse *pParse = pWInfo->pParse; /* Parse context */ | - | ||||||||||||||||||
1041 | Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ | - | ||||||||||||||||||
1042 | - | |||||||||||||||||||
1043 | assert( iIdxCur>0 ); | - | ||||||||||||||||||
1044 | assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); | - | ||||||||||||||||||
1045 | - | |||||||||||||||||||
1046 | sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); | - | ||||||||||||||||||
1047 | if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
| 7809-13263 | ||||||||||||||||||
1048 | && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
| 4-13259 | ||||||||||||||||||
1049 | ){ | - | ||||||||||||||||||
1050 | int i; | - | ||||||||||||||||||
1051 | Table *pTab = pIdx->pTable; | - | ||||||||||||||||||
1052 | int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); | - | ||||||||||||||||||
1053 | if( ai ){
| 0-13243 | ||||||||||||||||||
1054 | ai[0] = pTab->nCol; | - | ||||||||||||||||||
1055 | for(i=0; i<pIdx->nColumn-1; i++){
| 13243-19594 | ||||||||||||||||||
1056 | assert( pIdx->aiColumn[i]<pTab->nCol ); | - | ||||||||||||||||||
1057 | if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; executed 19594 times by 1 test: ai[pIdx->aiColumn[i]+1] = i+1; Executed by:
| 0-19594 | ||||||||||||||||||
1058 | } executed 19594 times by 1 test: end of block Executed by:
| 19594 | ||||||||||||||||||
1059 | sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); | - | ||||||||||||||||||
1060 | } executed 13243 times by 1 test: end of block Executed by:
| 13243 | ||||||||||||||||||
1061 | } executed 13243 times by 1 test: end of block Executed by:
| 13243 | ||||||||||||||||||
1062 | } executed 21072 times by 2 tests: end of block Executed by:
| 21072 | ||||||||||||||||||
1063 | - | |||||||||||||||||||
1064 | /* | - | ||||||||||||||||||
1065 | ** If the expression passed as the second argument is a vector, generate | - | ||||||||||||||||||
1066 | ** code to write the first nReg elements of the vector into an array | - | ||||||||||||||||||
1067 | ** of registers starting with iReg. | - | ||||||||||||||||||
1068 | ** | - | ||||||||||||||||||
1069 | ** If the expression is not a vector, then nReg must be passed 1. In | - | ||||||||||||||||||
1070 | ** this case, generate code to evaluate the expression and leave the | - | ||||||||||||||||||
1071 | ** result in register iReg. | - | ||||||||||||||||||
1072 | */ | - | ||||||||||||||||||
1073 | static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ | - | ||||||||||||||||||
1074 | assert( nReg>0 ); | - | ||||||||||||||||||
1075 | if( p && sqlite3ExprIsVector(p) ){
| 3-32652 | ||||||||||||||||||
1076 | #ifndef SQLITE_OMIT_SUBQUERY | - | ||||||||||||||||||
1077 | if( (p->flags & EP_xIsSelect) ){
| 907-1147 | ||||||||||||||||||
1078 | Vdbe *v = pParse->pVdbe; | - | ||||||||||||||||||
1079 | int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0); | - | ||||||||||||||||||
1080 | sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1); | - | ||||||||||||||||||
1081 | }else executed 907 times by 1 test: end of block Executed by:
| 907 | ||||||||||||||||||
1082 | #endif | - | ||||||||||||||||||
1083 | { | - | ||||||||||||||||||
1084 | int i; | - | ||||||||||||||||||
1085 | ExprList *pList = p->x.pList; | - | ||||||||||||||||||
1086 | assert( nReg<=pList->nExpr ); | - | ||||||||||||||||||
1087 | for(i=0; i<nReg; i++){
| 1147-2227 | ||||||||||||||||||
1088 | sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i); | - | ||||||||||||||||||
1089 | } executed 2227 times by 1 test: end of block Executed by:
| 2227 | ||||||||||||||||||
1090 | } executed 1147 times by 1 test: end of block Executed by:
| 1147 | ||||||||||||||||||
1091 | }else{ | - | ||||||||||||||||||
1092 | assert( nReg==1 ); | - | ||||||||||||||||||
1093 | sqlite3ExprCode(pParse, p, iReg); | - | ||||||||||||||||||
1094 | } executed 30601 times by 1 test: end of block Executed by:
| 30601 | ||||||||||||||||||
1095 | } | - | ||||||||||||||||||
1096 | - | |||||||||||||||||||
1097 | /* An instance of the IdxExprTrans object carries information about a | - | ||||||||||||||||||
1098 | ** mapping from an expression on table columns into a column in an index | - | ||||||||||||||||||
1099 | ** down through the Walker. | - | ||||||||||||||||||
1100 | */ | - | ||||||||||||||||||
1101 | typedef struct IdxExprTrans { | - | ||||||||||||||||||
1102 | Expr *pIdxExpr; /* The index expression */ | - | ||||||||||||||||||
1103 | int iTabCur; /* The cursor of the corresponding table */ | - | ||||||||||||||||||
1104 | int iIdxCur; /* The cursor for the index */ | - | ||||||||||||||||||
1105 | int iIdxCol; /* The column for the index */ | - | ||||||||||||||||||
1106 | } IdxExprTrans; | - | ||||||||||||||||||
1107 | - | |||||||||||||||||||
1108 | /* The walker node callback used to transform matching expressions into | - | ||||||||||||||||||
1109 | ** a reference to an index column for an index on an expression. | - | ||||||||||||||||||
1110 | ** | - | ||||||||||||||||||
1111 | ** If pExpr matches, then transform it into a reference to the index column | - | ||||||||||||||||||
1112 | ** that contains the value of pExpr. | - | ||||||||||||||||||
1113 | */ | - | ||||||||||||||||||
1114 | static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ | - | ||||||||||||||||||
1115 | IdxExprTrans *pX = p->u.pIdxTrans; | - | ||||||||||||||||||
1116 | if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
| 72-303 | ||||||||||||||||||
1117 | pExpr->op = TK_COLUMN; | - | ||||||||||||||||||
1118 | pExpr->iTable = pX->iIdxCur; | - | ||||||||||||||||||
1119 | pExpr->iColumn = pX->iIdxCol; | - | ||||||||||||||||||
1120 | pExpr->y.pTab = 0; | - | ||||||||||||||||||
1121 | return WRC_Prune; executed 72 times by 1 test: return 1; Executed by:
| 72 | ||||||||||||||||||
1122 | }else{ | - | ||||||||||||||||||
1123 | return WRC_Continue; executed 303 times by 1 test: return 0; Executed by:
| 303 | ||||||||||||||||||
1124 | } | - | ||||||||||||||||||
1125 | } | - | ||||||||||||||||||
1126 | - | |||||||||||||||||||
1127 | /* | - | ||||||||||||||||||
1128 | ** For an indexes on expression X, locate every instance of expression X | - | ||||||||||||||||||
1129 | ** in pExpr and change that subexpression into a reference to the appropriate | - | ||||||||||||||||||
1130 | ** column of the index. | - | ||||||||||||||||||
1131 | */ | - | ||||||||||||||||||
1132 | static void whereIndexExprTrans( | - | ||||||||||||||||||
1133 | Index *pIdx, /* The Index */ | - | ||||||||||||||||||
1134 | int iTabCur, /* Cursor of the table that is being indexed */ | - | ||||||||||||||||||
1135 | int iIdxCur, /* Cursor of the index itself */ | - | ||||||||||||||||||
1136 | WhereInfo *pWInfo /* Transform expressions in this WHERE clause */ | - | ||||||||||||||||||
1137 | ){ | - | ||||||||||||||||||
1138 | int iIdxCol; /* Column number of the index */ | - | ||||||||||||||||||
1139 | ExprList *aColExpr; /* Expressions that are indexed */ | - | ||||||||||||||||||
1140 | Walker w; | - | ||||||||||||||||||
1141 | IdxExprTrans x; | - | ||||||||||||||||||
1142 | aColExpr = pIdx->aColExpr; | - | ||||||||||||||||||
1143 | if( aColExpr==0 ) return; /* Not an index on expressions */ executed 30967 times by 2 tests: return; Executed by:
| 62-30967 | ||||||||||||||||||
1144 | memset(&w, 0, sizeof(w)); | - | ||||||||||||||||||
1145 | w.xExprCallback = whereIndexExprTransNode; | - | ||||||||||||||||||
1146 | w.u.pIdxTrans = &x; | - | ||||||||||||||||||
1147 | x.iTabCur = iTabCur; | - | ||||||||||||||||||
1148 | x.iIdxCur = iIdxCur; | - | ||||||||||||||||||
1149 | for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
| 62-79 | ||||||||||||||||||
1150 | if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue; executed 16 times by 1 test: continue; Executed by:
| 16-63 | ||||||||||||||||||
1151 | assert( aColExpr->a[iIdxCol].pExpr!=0 ); | - | ||||||||||||||||||
1152 | x.iIdxCol = iIdxCol; | - | ||||||||||||||||||
1153 | x.pIdxExpr = aColExpr->a[iIdxCol].pExpr; | - | ||||||||||||||||||
1154 | sqlite3WalkExpr(&w, pWInfo->pWhere); | - | ||||||||||||||||||
1155 | sqlite3WalkExprList(&w, pWInfo->pOrderBy); | - | ||||||||||||||||||
1156 | sqlite3WalkExprList(&w, pWInfo->pResultSet); | - | ||||||||||||||||||
1157 | } executed 63 times by 1 test: end of block Executed by:
| 63 | ||||||||||||||||||
1158 | } executed 62 times by 1 test: end of block Executed by:
| 62 | ||||||||||||||||||
1159 | - | |||||||||||||||||||
1160 | /* | - | ||||||||||||||||||
1161 | ** Generate code for the start of the iLevel-th loop in the WHERE clause | - | ||||||||||||||||||
1162 | ** implementation described by pWInfo. | - | ||||||||||||||||||
1163 | */ | - | ||||||||||||||||||
1164 | Bitmask sqlite3WhereCodeOneLoopStart( | - | ||||||||||||||||||
1165 | WhereInfo *pWInfo, /* Complete information about the WHERE clause */ | - | ||||||||||||||||||
1166 | int iLevel, /* Which level of pWInfo->a[] should be coded */ | - | ||||||||||||||||||
1167 | Bitmask notReady /* Which tables are currently available */ | - | ||||||||||||||||||
1168 | ){ | - | ||||||||||||||||||
1169 | int j, k; /* Loop counters */ | - | ||||||||||||||||||
1170 | int iCur; /* The VDBE cursor for the table */ | - | ||||||||||||||||||
1171 | int addrNxt; /* Where to jump to continue with the next IN case */ | - | ||||||||||||||||||
1172 | int omitTable; /* True if we use the index only */ | - | ||||||||||||||||||
1173 | int bRev; /* True if we need to scan in reverse order */ | - | ||||||||||||||||||
1174 | WhereLevel *pLevel; /* The where level to be coded */ | - | ||||||||||||||||||
1175 | WhereLoop *pLoop; /* The WhereLoop object being coded */ | - | ||||||||||||||||||
1176 | WhereClause *pWC; /* Decomposition of the entire WHERE clause */ | - | ||||||||||||||||||
1177 | WhereTerm *pTerm; /* A WHERE clause term */ | - | ||||||||||||||||||
1178 | Parse *pParse; /* Parsing context */ | - | ||||||||||||||||||
1179 | sqlite3 *db; /* Database connection */ | - | ||||||||||||||||||
1180 | Vdbe *v; /* The prepared stmt under constructions */ | - | ||||||||||||||||||
1181 | struct SrcList_item *pTabItem; /* FROM clause term being coded */ | - | ||||||||||||||||||
1182 | int addrBrk; /* Jump here to break out of the loop */ | - | ||||||||||||||||||
1183 | int addrHalt; /* addrBrk for the outermost loop */ | - | ||||||||||||||||||
1184 | int addrCont; /* Jump here to continue with next cycle */ | - | ||||||||||||||||||
1185 | int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ | - | ||||||||||||||||||
1186 | int iReleaseReg = 0; /* Temp register to free before returning */ | - | ||||||||||||||||||
1187 | Index *pIdx = 0; /* Index used by loop (if any) */ | - | ||||||||||||||||||
1188 | int iLoop; /* Iteration of constraint generator loop */ | - | ||||||||||||||||||
1189 | - | |||||||||||||||||||
1190 | pParse = pWInfo->pParse; | - | ||||||||||||||||||
1191 | v = pParse->pVdbe; | - | ||||||||||||||||||
1192 | pWC = &pWInfo->sWC; | - | ||||||||||||||||||
1193 | db = pParse->db; | - | ||||||||||||||||||
1194 | pLevel = &pWInfo->a[iLevel]; | - | ||||||||||||||||||
1195 | pLoop = pLevel->pWLoop; | - | ||||||||||||||||||
1196 | pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; | - | ||||||||||||||||||
1197 | iCur = pTabItem->iCursor; | - | ||||||||||||||||||
1198 | pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); | - | ||||||||||||||||||
1199 | bRev = (pWInfo->revMask>>iLevel)&1; | - | ||||||||||||||||||
1200 | omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
| 11022-267474 | ||||||||||||||||||
1201 | && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
| 1195-9827 | ||||||||||||||||||
1202 | VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName)); | - | ||||||||||||||||||
1203 | - | |||||||||||||||||||
1204 | /* Create labels for the "break" and "continue" instructions | - | ||||||||||||||||||
1205 | ** for the current loop. Jump to addrBrk to break out of a loop. | - | ||||||||||||||||||
1206 | ** Jump to cont to go immediately to the next iteration of the | - | ||||||||||||||||||
1207 | ** loop. | - | ||||||||||||||||||
1208 | ** | - | ||||||||||||||||||
1209 | ** When there is an IN operator, we also have a "addrNxt" label that | - | ||||||||||||||||||
1210 | ** means to continue with the next IN value combination. When | - | ||||||||||||||||||
1211 | ** there are no IN operators in the constraints, the "addrNxt" label | - | ||||||||||||||||||
1212 | ** is the same as "addrBrk". | - | ||||||||||||||||||
1213 | */ | - | ||||||||||||||||||
1214 | addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); | - | ||||||||||||||||||
1215 | addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); | - | ||||||||||||||||||
1216 | - | |||||||||||||||||||
1217 | /* If this is the right table of a LEFT OUTER JOIN, allocate and | - | ||||||||||||||||||
1218 | ** initialize a memory cell that records if this table matches any | - | ||||||||||||||||||
1219 | ** row of the left table of the join. | - | ||||||||||||||||||
1220 | */ | - | ||||||||||||||||||
1221 | assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) | - | ||||||||||||||||||
1222 | || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 | - | ||||||||||||||||||
1223 | ); | - | ||||||||||||||||||
1224 | if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
| 425-267368 | ||||||||||||||||||
1225 | pLevel->iLeftJoin = ++pParse->nMem; | - | ||||||||||||||||||
1226 | sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); | - | ||||||||||||||||||
1227 | VdbeComment((v, "init LEFT JOIN no-match flag")); | - | ||||||||||||||||||
1228 | } executed 425 times by 1 test: end of block Executed by:
| 425 | ||||||||||||||||||
1229 | - | |||||||||||||||||||
1230 | /* Compute a safe address to jump to if we discover that the table for | - | ||||||||||||||||||
1231 | ** this loop is empty and can never contribute content. */ | - | ||||||||||||||||||
1232 | for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} executed 98867 times by 1 test: end of block Executed by:
| 460-278036 | ||||||||||||||||||
1233 | addrHalt = pWInfo->a[j].addrBrk; | - | ||||||||||||||||||
1234 | - | |||||||||||||||||||
1235 | /* Special case of a FROM clause subquery implemented as a co-routine */ | - | ||||||||||||||||||
1236 | if( pTabItem->fg.viaCoroutine ){
| 35364-243132 | ||||||||||||||||||
1237 | int regYield = pTabItem->regReturn; | - | ||||||||||||||||||
1238 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); | - | ||||||||||||||||||
1239 | pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); | - | ||||||||||||||||||
1240 | VdbeCoverage(v); | - | ||||||||||||||||||
1241 | VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); | - | ||||||||||||||||||
1242 | pLevel->op = OP_Goto; | - | ||||||||||||||||||
1243 | }else executed 35364 times by 1 test: end of block Executed by:
| 35364 | ||||||||||||||||||
1244 | - | |||||||||||||||||||
1245 | #ifndef SQLITE_OMIT_VIRTUALTABLE | - | ||||||||||||||||||
1246 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
| 11058-232074 | ||||||||||||||||||
1247 | /* Case 1: The table is a virtual-table. Use the VFilter and VNext | - | ||||||||||||||||||
1248 | ** to access the data. | - | ||||||||||||||||||
1249 | */ | - | ||||||||||||||||||
1250 | int iReg; /* P3 Value for OP_VFilter */ | - | ||||||||||||||||||
1251 | int addrNotFound; | - | ||||||||||||||||||
1252 | int nConstraint = pLoop->nLTerm; | - | ||||||||||||||||||
1253 | int iIn; /* Counter for IN constraints */ | - | ||||||||||||||||||
1254 | - | |||||||||||||||||||
1255 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); | - | ||||||||||||||||||
1256 | addrNotFound = pLevel->addrBrk; | - | ||||||||||||||||||
1257 | for(j=0; j<nConstraint; j++){
| 11058-18422 | ||||||||||||||||||
1258 | int iTarget = iReg+j+2; | - | ||||||||||||||||||
1259 | pTerm = pLoop->aLTerm[j]; | - | ||||||||||||||||||
1260 | if( NEVER(pTerm==0) ) continue; never executed: continue;
| 0-18422 | ||||||||||||||||||
1261 | if( pTerm->eOperator & WO_IN ){
| 21-18401 | ||||||||||||||||||
1262 | codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); | - | ||||||||||||||||||
1263 | addrNotFound = pLevel->addrNxt; | - | ||||||||||||||||||
1264 | }else{ executed 21 times by 1 test: end of block Executed by:
| 21 | ||||||||||||||||||
1265 | Expr *pRight = pTerm->pExpr->pRight; | - | ||||||||||||||||||
1266 | codeExprOrVector(pParse, pRight, iTarget, 1); | - | ||||||||||||||||||
1267 | } executed 18401 times by 1 test: end of block Executed by:
| 18401 | ||||||||||||||||||
1268 | } | - | ||||||||||||||||||
1269 | sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); | - | ||||||||||||||||||
1270 | sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); | - | ||||||||||||||||||
1271 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, | - | ||||||||||||||||||
1272 | pLoop->u.vtab.idxStr, | - | ||||||||||||||||||
1273 | pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); | - | ||||||||||||||||||
1274 | VdbeCoverage(v); | - | ||||||||||||||||||
1275 | pLoop->u.vtab.needFree = 0; | - | ||||||||||||||||||
1276 | pLevel->p1 = iCur; | - | ||||||||||||||||||
1277 | pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
| 8-11050 | ||||||||||||||||||
1278 | pLevel->p2 = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
1279 | iIn = pLevel->u.in.nIn; | - | ||||||||||||||||||
1280 | for(j=nConstraint-1; j>=0; j--){
| 11058-18422 | ||||||||||||||||||
1281 | pTerm = pLoop->aLTerm[j]; | - | ||||||||||||||||||
1282 | if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
| 0-18422 | ||||||||||||||||||
1283 | disableTerm(pLevel, pTerm); | - | ||||||||||||||||||
1284 | }else if( (pTerm->eOperator & WO_IN)!=0 ){ executed 17776 times by 1 test: end of block Executed by:
| 8-17776 | ||||||||||||||||||
1285 | Expr *pCompare; /* The comparison operator */ | - | ||||||||||||||||||
1286 | Expr *pRight; /* RHS of the comparison */ | - | ||||||||||||||||||
1287 | VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ | - | ||||||||||||||||||
1288 | - | |||||||||||||||||||
1289 | /* Reload the constraint value into reg[iReg+j+2]. The same value | - | ||||||||||||||||||
1290 | ** was loaded into the same register prior to the OP_VFilter, but | - | ||||||||||||||||||
1291 | ** the xFilter implementation might have changed the datatype or | - | ||||||||||||||||||
1292 | ** encoding of the value in the register, so it *must* be reloaded. */ | - | ||||||||||||||||||
1293 | assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); | - | ||||||||||||||||||
1294 | if( !db->mallocFailed ){
| 0-8 | ||||||||||||||||||
1295 | assert( iIn>0 ); | - | ||||||||||||||||||
1296 | pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); | - | ||||||||||||||||||
1297 | assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); | - | ||||||||||||||||||
1298 | assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); | - | ||||||||||||||||||
1299 | assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); | - | ||||||||||||||||||
1300 | testcase( pOp->opcode==OP_Rowid ); | - | ||||||||||||||||||
1301 | sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); | - | ||||||||||||||||||
1302 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||
1303 | - | |||||||||||||||||||
1304 | /* Generate code that will continue to the next row if | - | ||||||||||||||||||
1305 | ** the IN constraint is not satisfied */ | - | ||||||||||||||||||
1306 | pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); | - | ||||||||||||||||||
1307 | assert( pCompare!=0 || db->mallocFailed ); | - | ||||||||||||||||||
1308 | if( pCompare ){
| 0-8 | ||||||||||||||||||
1309 | pCompare->pLeft = pTerm->pExpr->pLeft; | - | ||||||||||||||||||
1310 | pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); | - | ||||||||||||||||||
1311 | if( pRight ){
| 0-8 | ||||||||||||||||||
1312 | pRight->iTable = iReg+j+2; | - | ||||||||||||||||||
1313 | sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); | - | ||||||||||||||||||
1314 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||
1315 | pCompare->pLeft = 0; | - | ||||||||||||||||||
1316 | sqlite3ExprDelete(db, pCompare); | - | ||||||||||||||||||
1317 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||
1318 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||
1319 | } executed 18422 times by 1 test: end of block Executed by:
| 18422 | ||||||||||||||||||
1320 | /* These registers need to be preserved in case there is an IN operator | - | ||||||||||||||||||
1321 | ** loop. So we could deallocate the registers here (and potentially | - | ||||||||||||||||||
1322 | ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems | - | ||||||||||||||||||
1323 | ** simpler and safer to simply not reuse the registers. | - | ||||||||||||||||||
1324 | ** | - | ||||||||||||||||||
1325 | ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); | - | ||||||||||||||||||
1326 | */ | - | ||||||||||||||||||
1327 | }else executed 11058 times by 1 test: end of block Executed by:
| 11058 | ||||||||||||||||||
1328 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ | - | ||||||||||||||||||
1329 | - | |||||||||||||||||||
1330 | if( (pLoop->wsFlags & WHERE_IPK)!=0
| 33643-198431 | ||||||||||||||||||
1331 | && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
| 30233-168198 | ||||||||||||||||||
1332 | ){ | - | ||||||||||||||||||
1333 | /* Case 2: We can directly reference a single row using an | - | ||||||||||||||||||
1334 | ** equality comparison against the ROWID field. Or | - | ||||||||||||||||||
1335 | ** we reference multiple rows using a "rowid IN (...)" | - | ||||||||||||||||||
1336 | ** construct. | - | ||||||||||||||||||
1337 | */ | - | ||||||||||||||||||
1338 | assert( pLoop->u.btree.nEq==1 ); | - | ||||||||||||||||||
1339 | pTerm = pLoop->aLTerm[0]; | - | ||||||||||||||||||
1340 | assert( pTerm!=0 ); | - | ||||||||||||||||||
1341 | assert( pTerm->pExpr!=0 ); | - | ||||||||||||||||||
1342 | assert( omitTable==0 ); | - | ||||||||||||||||||
1343 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1344 | iReleaseReg = ++pParse->nMem; | - | ||||||||||||||||||
1345 | iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); | - | ||||||||||||||||||
1346 | if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); executed 23620 times by 30 tests: sqlite3ReleaseTempReg(pParse, iReleaseReg); Executed by:
| 6613-23620 | ||||||||||||||||||
1347 | addrNxt = pLevel->addrNxt; | - | ||||||||||||||||||
1348 | sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); | - | ||||||||||||||||||
1349 | VdbeCoverage(v); | - | ||||||||||||||||||
1350 | pLevel->op = OP_Noop; | - | ||||||||||||||||||
1351 | }else if( (pLoop->wsFlags & WHERE_IPK)!=0 executed 30233 times by 30 tests: end of block Executed by:
| 30233-168198 | ||||||||||||||||||
1352 | && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
| 3124-165074 | ||||||||||||||||||
1353 | ){ | - | ||||||||||||||||||
1354 | /* Case 3: We have an inequality comparison against the ROWID field. | - | ||||||||||||||||||
1355 | */ | - | ||||||||||||||||||
1356 | int testOp = OP_Noop; | - | ||||||||||||||||||
1357 | int start; | - | ||||||||||||||||||
1358 | int memEndValue = 0; | - | ||||||||||||||||||
1359 | WhereTerm *pStart, *pEnd; | - | ||||||||||||||||||
1360 | - | |||||||||||||||||||
1361 | assert( omitTable==0 ); | - | ||||||||||||||||||
1362 | j = 0; | - | ||||||||||||||||||
1363 | pStart = pEnd = 0; | - | ||||||||||||||||||
1364 | if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++]; executed 2561 times by 1 test: pStart = pLoop->aLTerm[j++]; Executed by:
| 563-2561 | ||||||||||||||||||
1365 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; executed 2458 times by 1 test: pEnd = pLoop->aLTerm[j++]; Executed by:
| 666-2458 | ||||||||||||||||||
1366 | assert( pStart!=0 || pEnd!=0 ); | - | ||||||||||||||||||
1367 | if( bRev ){
| 440-2684 | ||||||||||||||||||
1368 | pTerm = pStart; | - | ||||||||||||||||||
1369 | pStart = pEnd; | - | ||||||||||||||||||
1370 | pEnd = pTerm; | - | ||||||||||||||||||
1371 | } executed 440 times by 1 test: end of block Executed by:
| 440 | ||||||||||||||||||
1372 | codeCursorHint(pTabItem, pWInfo, pLevel, pEnd); | - | ||||||||||||||||||
1373 | if( pStart ){
| 416-2708 | ||||||||||||||||||
1374 | Expr *pX; /* The expression that defines the start bound */ | - | ||||||||||||||||||
1375 | int r1, rTemp; /* Registers for holding the start boundary */ | - | ||||||||||||||||||
1376 | int op; /* Cursor seek operation */ | - | ||||||||||||||||||
1377 | - | |||||||||||||||||||
1378 | /* The following constant maps TK_xx codes into corresponding | - | ||||||||||||||||||
1379 | ** seek opcodes. It depends on a particular ordering of TK_xx | - | ||||||||||||||||||
1380 | */ | - | ||||||||||||||||||
1381 | const u8 aMoveOp[] = { | - | ||||||||||||||||||
1382 | /* TK_GT */ OP_SeekGT, | - | ||||||||||||||||||
1383 | /* TK_LE */ OP_SeekLE, | - | ||||||||||||||||||
1384 | /* TK_LT */ OP_SeekLT, | - | ||||||||||||||||||
1385 | /* TK_GE */ OP_SeekGE | - | ||||||||||||||||||
1386 | }; | - | ||||||||||||||||||
1387 | assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ | - | ||||||||||||||||||
1388 | assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ | - | ||||||||||||||||||
1389 | assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ | - | ||||||||||||||||||
1390 | - | |||||||||||||||||||
1391 | assert( (pStart->wtFlags & TERM_VNULL)==0 ); | - | ||||||||||||||||||
1392 | testcase( pStart->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1393 | pX = pStart->pExpr; | - | ||||||||||||||||||
1394 | assert( pX!=0 ); | - | ||||||||||||||||||
1395 | testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ | - | ||||||||||||||||||
1396 | if( sqlite3ExprIsVector(pX->pRight) ){
| 38-2670 | ||||||||||||||||||
1397 | r1 = rTemp = sqlite3GetTempReg(pParse); | - | ||||||||||||||||||
1398 | codeExprOrVector(pParse, pX->pRight, r1, 1); | - | ||||||||||||||||||
1399 | testcase( pX->op==TK_GT ); | - | ||||||||||||||||||
1400 | testcase( pX->op==TK_GE ); | - | ||||||||||||||||||
1401 | testcase( pX->op==TK_LT ); | - | ||||||||||||||||||
1402 | testcase( pX->op==TK_LE ); | - | ||||||||||||||||||
1403 | op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; | - | ||||||||||||||||||
1404 | assert( pX->op!=TK_GT || op==OP_SeekGE ); | - | ||||||||||||||||||
1405 | assert( pX->op!=TK_GE || op==OP_SeekGE ); | - | ||||||||||||||||||
1406 | assert( pX->op!=TK_LT || op==OP_SeekLE ); | - | ||||||||||||||||||
1407 | assert( pX->op!=TK_LE || op==OP_SeekLE ); | - | ||||||||||||||||||
1408 | }else{ executed 38 times by 1 test: end of block Executed by:
| 38 | ||||||||||||||||||
1409 | r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); | - | ||||||||||||||||||
1410 | disableTerm(pLevel, pStart); | - | ||||||||||||||||||
1411 | op = aMoveOp[(pX->op - TK_GT)]; | - | ||||||||||||||||||
1412 | } executed 2670 times by 1 test: end of block Executed by:
| 2670 | ||||||||||||||||||
1413 | sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); | - | ||||||||||||||||||
1414 | VdbeComment((v, "pk")); | - | ||||||||||||||||||
1415 | VdbeCoverageIf(v, pX->op==TK_GT); | - | ||||||||||||||||||
1416 | VdbeCoverageIf(v, pX->op==TK_LE); | - | ||||||||||||||||||
1417 | VdbeCoverageIf(v, pX->op==TK_LT); | - | ||||||||||||||||||
1418 | VdbeCoverageIf(v, pX->op==TK_GE); | - | ||||||||||||||||||
1419 | sqlite3ReleaseTempReg(pParse, rTemp); | - | ||||||||||||||||||
1420 | }else{ executed 2708 times by 1 test: end of block Executed by:
| 2708 | ||||||||||||||||||
1421 | sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); | - | ||||||||||||||||||
1422 | VdbeCoverageIf(v, bRev==0); | - | ||||||||||||||||||
1423 | VdbeCoverageIf(v, bRev!=0); | - | ||||||||||||||||||
1424 | } executed 416 times by 1 test: end of block Executed by:
| 416 | ||||||||||||||||||
1425 | if( pEnd ){
| 813-2311 | ||||||||||||||||||
1426 | Expr *pX; | - | ||||||||||||||||||
1427 | pX = pEnd->pExpr; | - | ||||||||||||||||||
1428 | assert( pX!=0 ); | - | ||||||||||||||||||
1429 | assert( (pEnd->wtFlags & TERM_VNULL)==0 ); | - | ||||||||||||||||||
1430 | testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ | - | ||||||||||||||||||
1431 | testcase( pEnd->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1432 | memEndValue = ++pParse->nMem; | - | ||||||||||||||||||
1433 | codeExprOrVector(pParse, pX->pRight, memEndValue, 1); | - | ||||||||||||||||||
1434 | if( 0==sqlite3ExprIsVector(pX->pRight)
| 4-2307 | ||||||||||||||||||
1435 | && (pX->op==TK_LT || pX->op==TK_GT)
| 74-2187 | ||||||||||||||||||
1436 | ){ | - | ||||||||||||||||||
1437 | testOp = bRev ? OP_Le : OP_Ge;
| 74-120 | ||||||||||||||||||
1438 | }else{ executed 194 times by 1 test: end of block Executed by:
| 194 | ||||||||||||||||||
1439 | testOp = bRev ? OP_Lt : OP_Gt;
| 73-2044 | ||||||||||||||||||
1440 | } executed 2117 times by 1 test: end of block Executed by:
| 2117 | ||||||||||||||||||
1441 | if( 0==sqlite3ExprIsVector(pX->pRight) ){
| 4-2307 | ||||||||||||||||||
1442 | disableTerm(pLevel, pEnd); | - | ||||||||||||||||||
1443 | } executed 2307 times by 1 test: end of block Executed by:
| 2307 | ||||||||||||||||||
1444 | } executed 2311 times by 1 test: end of block Executed by:
| 2311 | ||||||||||||||||||
1445 | start = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
1446 | pLevel->op = bRev ? OP_Prev : OP_Next;
| 440-2684 | ||||||||||||||||||
1447 | pLevel->p1 = iCur; | - | ||||||||||||||||||
1448 | pLevel->p2 = start; | - | ||||||||||||||||||
1449 | assert( pLevel->p5==0 ); | - | ||||||||||||||||||
1450 | if( testOp!=OP_Noop ){
| 813-2311 | ||||||||||||||||||
1451 | iRowidReg = ++pParse->nMem; | - | ||||||||||||||||||
1452 | sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); | - | ||||||||||||||||||
1453 | sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); | - | ||||||||||||||||||
1454 | VdbeCoverageIf(v, testOp==OP_Le); | - | ||||||||||||||||||
1455 | VdbeCoverageIf(v, testOp==OP_Lt); | - | ||||||||||||||||||
1456 | VdbeCoverageIf(v, testOp==OP_Ge); | - | ||||||||||||||||||
1457 | VdbeCoverageIf(v, testOp==OP_Gt); | - | ||||||||||||||||||
1458 | sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); | - | ||||||||||||||||||
1459 | } executed 2311 times by 1 test: end of block Executed by:
| 2311 | ||||||||||||||||||
1460 | }else if( pLoop->wsFlags & WHERE_INDEXED ){ executed 3124 times by 1 test: end of block Executed by:
| 3124-167440 | ||||||||||||||||||
1461 | /* Case 4: A scan using an index. | - | ||||||||||||||||||
1462 | ** | - | ||||||||||||||||||
1463 | ** The WHERE clause may contain zero or more equality | - | ||||||||||||||||||
1464 | ** terms ("==" or "IN" operators) that refer to the N | - | ||||||||||||||||||
1465 | ** left-most columns of the index. It may also contain | - | ||||||||||||||||||
1466 | ** inequality constraints (>, <, >= or <=) on the indexed | - | ||||||||||||||||||
1467 | ** column that immediately follows the N equalities. Only | - | ||||||||||||||||||
1468 | ** the right-most column can be an inequality - the rest must | - | ||||||||||||||||||
1469 | ** use the "==" and "IN" operators. For example, if the | - | ||||||||||||||||||
1470 | ** index is on (x,y,z), then the following clauses are all | - | ||||||||||||||||||
1471 | ** optimized: | - | ||||||||||||||||||
1472 | ** | - | ||||||||||||||||||
1473 | ** x=5 | - | ||||||||||||||||||
1474 | ** x=5 AND y=10 | - | ||||||||||||||||||
1475 | ** x=5 AND y<10 | - | ||||||||||||||||||
1476 | ** x=5 AND y>5 AND y<10 | - | ||||||||||||||||||
1477 | ** x=5 AND y=5 AND z<=10 | - | ||||||||||||||||||
1478 | ** | - | ||||||||||||||||||
1479 | ** The z<10 term of the following cannot be used, only | - | ||||||||||||||||||
1480 | ** the x=5 term: | - | ||||||||||||||||||
1481 | ** | - | ||||||||||||||||||
1482 | ** x=5 AND z<10 | - | ||||||||||||||||||
1483 | ** | - | ||||||||||||||||||
1484 | ** N may be zero if there are inequality constraints. | - | ||||||||||||||||||
1485 | ** If there are no inequality constraints, then N is at | - | ||||||||||||||||||
1486 | ** least one. | - | ||||||||||||||||||
1487 | ** | - | ||||||||||||||||||
1488 | ** This case is also used when there are no WHERE clause | - | ||||||||||||||||||
1489 | ** constraints but an index is selected anyway, in order | - | ||||||||||||||||||
1490 | ** to force the output order to conform to an ORDER BY. | - | ||||||||||||||||||
1491 | */ | - | ||||||||||||||||||
1492 | static const u8 aStartOp[] = { | - | ||||||||||||||||||
1493 | 0, | - | ||||||||||||||||||
1494 | 0, | - | ||||||||||||||||||
1495 | OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ | - | ||||||||||||||||||
1496 | OP_Last, /* 3: (!start_constraints && startEq && bRev) */ | - | ||||||||||||||||||
1497 | OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */ | - | ||||||||||||||||||
1498 | OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */ | - | ||||||||||||||||||
1499 | OP_SeekGE, /* 6: (start_constraints && startEq && !bRev) */ | - | ||||||||||||||||||
1500 | OP_SeekLE /* 7: (start_constraints && startEq && bRev) */ | - | ||||||||||||||||||
1501 | }; | - | ||||||||||||||||||
1502 | static const u8 aEndOp[] = { | - | ||||||||||||||||||
1503 | OP_IdxGE, /* 0: (end_constraints && !bRev && !endEq) */ | - | ||||||||||||||||||
1504 | OP_IdxGT, /* 1: (end_constraints && !bRev && endEq) */ | - | ||||||||||||||||||
1505 | OP_IdxLE, /* 2: (end_constraints && bRev && !endEq) */ | - | ||||||||||||||||||
1506 | OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ | - | ||||||||||||||||||
1507 | }; | - | ||||||||||||||||||
1508 | u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ | - | ||||||||||||||||||
1509 | u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */ | - | ||||||||||||||||||
1510 | u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */ | - | ||||||||||||||||||
1511 | int regBase; /* Base register holding constraint values */ | - | ||||||||||||||||||
1512 | WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ | - | ||||||||||||||||||
1513 | WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ | - | ||||||||||||||||||
1514 | int startEq; /* True if range start uses ==, >= or <= */ | - | ||||||||||||||||||
1515 | int endEq; /* True if range end uses ==, >= or <= */ | - | ||||||||||||||||||
1516 | int start_constraints; /* Start of range is constrained */ | - | ||||||||||||||||||
1517 | int nConstraint; /* Number of constraint terms */ | - | ||||||||||||||||||
1518 | int iIdxCur; /* The VDBE cursor for the index */ | - | ||||||||||||||||||
1519 | int nExtraReg = 0; /* Number of extra registers needed */ | - | ||||||||||||||||||
1520 | int op; /* Instruction opcode */ | - | ||||||||||||||||||
1521 | char *zStartAff; /* Affinity for start of range constraint */ | - | ||||||||||||||||||
1522 | char *zEndAff = 0; /* Affinity for end of range constraint */ | - | ||||||||||||||||||
1523 | u8 bSeekPastNull = 0; /* True to seek past initial nulls */ | - | ||||||||||||||||||
1524 | u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ | - | ||||||||||||||||||
1525 | - | |||||||||||||||||||
1526 | pIdx = pLoop->u.btree.pIndex; | - | ||||||||||||||||||
1527 | iIdxCur = pLevel->iIdxCur; | - | ||||||||||||||||||
1528 | assert( nEq>=pLoop->nSkip ); | - | ||||||||||||||||||
1529 | - | |||||||||||||||||||
1530 | /* If this loop satisfies a sort order (pOrderBy) request that | - | ||||||||||||||||||
1531 | ** was passed to this function to implement a "SELECT min(x) ..." | - | ||||||||||||||||||
1532 | ** query, then the caller will only allow the loop to run for | - | ||||||||||||||||||
1533 | ** a single iteration. This means that the first row returned | - | ||||||||||||||||||
1534 | ** should not have a NULL value stored in 'x'. If column 'x' is | - | ||||||||||||||||||
1535 | ** the first one after the nEq equality constraints in the index, | - | ||||||||||||||||||
1536 | ** this requires some special handling. | - | ||||||||||||||||||
1537 | */ | - | ||||||||||||||||||
1538 | assert( pWInfo->pOrderBy==0 | - | ||||||||||||||||||
1539 | || pWInfo->pOrderBy->nExpr==1 | - | ||||||||||||||||||
1540 | || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 ); | - | ||||||||||||||||||
1541 | if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
| 57-31220 | ||||||||||||||||||
1542 | && pWInfo->nOBSat>0
| 5-52 | ||||||||||||||||||
1543 | && (pIdx->nKeyCol>nEq)
| 2-50 | ||||||||||||||||||
1544 | ){ | - | ||||||||||||||||||
1545 | assert( pLoop->nSkip==0 ); | - | ||||||||||||||||||
1546 | bSeekPastNull = 1; | - | ||||||||||||||||||
1547 | nExtraReg = 1; | - | ||||||||||||||||||
1548 | } executed 50 times by 1 test: end of block Executed by:
| 50 | ||||||||||||||||||
1549 | - | |||||||||||||||||||
1550 | /* Find any inequality constraint terms for the start and end | - | ||||||||||||||||||
1551 | ** of the range. | - | ||||||||||||||||||
1552 | */ | - | ||||||||||||||||||
1553 | j = nEq; | - | ||||||||||||||||||
1554 | if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
| 5997-25280 | ||||||||||||||||||
1555 | pRangeStart = pLoop->aLTerm[j++]; | - | ||||||||||||||||||
1556 | nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm);
| 0-5997 | ||||||||||||||||||
1557 | /* Like optimization range constraints always occur in pairs */ | - | ||||||||||||||||||
1558 | assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || | - | ||||||||||||||||||
1559 | (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); | - | ||||||||||||||||||
1560 | } executed 5997 times by 1 test: end of block Executed by:
| 5997 | ||||||||||||||||||
1561 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
| 5908-25369 | ||||||||||||||||||
1562 | pRangeEnd = pLoop->aLTerm[j++]; | - | ||||||||||||||||||
1563 | nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop);
| 0-5908 | ||||||||||||||||||
1564 | #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS | - | ||||||||||||||||||
1565 | if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
| 1726-4182 | ||||||||||||||||||
1566 | assert( pRangeStart!=0 ); /* LIKE opt constraints */ | - | ||||||||||||||||||
1567 | assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ | - | ||||||||||||||||||
1568 | pLevel->iLikeRepCntr = (u32)++pParse->nMem; | - | ||||||||||||||||||
1569 | sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr); | - | ||||||||||||||||||
1570 | VdbeComment((v, "LIKE loop counter")); | - | ||||||||||||||||||
1571 | pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
1572 | /* iLikeRepCntr actually stores 2x the counter register number. The | - | ||||||||||||||||||
1573 | ** bottom bit indicates whether the search order is ASC or DESC. */ | - | ||||||||||||||||||
1574 | testcase( bRev ); | - | ||||||||||||||||||
1575 | testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); | - | ||||||||||||||||||
1576 | assert( (bRev & ~1)==0 ); | - | ||||||||||||||||||
1577 | pLevel->iLikeRepCntr <<=1; | - | ||||||||||||||||||
1578 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); | - | ||||||||||||||||||
1579 | } executed 1726 times by 1 test: end of block Executed by:
| 1726 | ||||||||||||||||||
1580 | #endif | - | ||||||||||||||||||
1581 | if( pRangeStart==0 ){
| 1812-4096 | ||||||||||||||||||
1582 | j = pIdx->aiColumn[nEq]; | - | ||||||||||||||||||
1583 | if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
| 6-1658 | ||||||||||||||||||
1584 | bSeekPastNull = 1; | - | ||||||||||||||||||
1585 | } executed 1655 times by 1 test: end of block Executed by:
| 1655 | ||||||||||||||||||
1586 | } executed 1812 times by 1 test: end of block Executed by:
| 1812 | ||||||||||||||||||
1587 | } executed 5908 times by 1 test: end of block Executed by:
| 5908 | ||||||||||||||||||
1588 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); | - | ||||||||||||||||||
1589 | - | |||||||||||||||||||
1590 | /* If we are doing a reverse order scan on an ascending index, or | - | ||||||||||||||||||
1591 | ** a forward order scan on a descending index, interchange the | - | ||||||||||||||||||
1592 | ** start and end terms (pRangeStart and pRangeEnd). | - | ||||||||||||||||||
1593 | */ | - | ||||||||||||||||||
1594 | if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
| 1399-15722 | ||||||||||||||||||
1595 | || (bRev && pIdx->nKeyCol==nEq)
| 36-29671 | ||||||||||||||||||
1596 | ){ | - | ||||||||||||||||||
1597 | SWAP(WhereTerm *, pRangeEnd, pRangeStart); | - | ||||||||||||||||||
1598 | SWAP(u8, bSeekPastNull, bStopAtNull); | - | ||||||||||||||||||
1599 | SWAP(u8, nBtm, nTop); | - | ||||||||||||||||||
1600 | } executed 1570 times by 1 test: end of block Executed by:
| 1570 | ||||||||||||||||||
1601 | - | |||||||||||||||||||
1602 | /* Generate code to evaluate all constraint terms using == or IN | - | ||||||||||||||||||
1603 | ** and store the values of those terms in an array of registers | - | ||||||||||||||||||
1604 | ** starting at regBase. | - | ||||||||||||||||||
1605 | */ | - | ||||||||||||||||||
1606 | codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); | - | ||||||||||||||||||
1607 | regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); | - | ||||||||||||||||||
1608 | assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); | - | ||||||||||||||||||
1609 | if( zStartAff && nTop ){
| 8-31269 | ||||||||||||||||||
1610 | zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); | - | ||||||||||||||||||
1611 | } executed 5909 times by 1 test: end of block Executed by:
| 5909 | ||||||||||||||||||
1612 | addrNxt = pLevel->addrNxt; | - | ||||||||||||||||||
1613 | - | |||||||||||||||||||
1614 | testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); | - | ||||||||||||||||||
1615 | testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); | - | ||||||||||||||||||
1616 | testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); | - | ||||||||||||||||||
1617 | testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); | - | ||||||||||||||||||
1618 | startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
| 1097-25285 | ||||||||||||||||||
1619 | endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
| 1192-25364 | ||||||||||||||||||
1620 | start_constraints = pRangeStart || nEq>0;
| 5992-25285 | ||||||||||||||||||
1621 | - | |||||||||||||||||||
1622 | /* Seek the index cursor to the start of the range. */ | - | ||||||||||||||||||
1623 | nConstraint = nEq; | - | ||||||||||||||||||
1624 | if( pRangeStart ){
| 5992-25285 | ||||||||||||||||||
1625 | Expr *pRight = pRangeStart->pExpr->pRight; | - | ||||||||||||||||||
1626 | codeExprOrVector(pParse, pRight, regBase+nEq, nBtm); | - | ||||||||||||||||||
1627 | whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); | - | ||||||||||||||||||
1628 | if( (pRangeStart->wtFlags & TERM_VNULL)==0
| 0-5992 | ||||||||||||||||||
1629 | && sqlite3ExprCanBeNull(pRight)
| 1141-4851 | ||||||||||||||||||
1630 | ){ | - | ||||||||||||||||||
1631 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); | - | ||||||||||||||||||
1632 | VdbeCoverage(v); | - | ||||||||||||||||||
1633 | } executed 1141 times by 1 test: end of block Executed by:
| 1141 | ||||||||||||||||||
1634 | if( zStartAff ){
| 4-5988 | ||||||||||||||||||
1635 | updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); | - | ||||||||||||||||||
1636 | } executed 5988 times by 1 test: end of block Executed by:
| 5988 | ||||||||||||||||||
1637 | nConstraint += nBtm; | - | ||||||||||||||||||
1638 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1639 | if( sqlite3ExprIsVector(pRight)==0 ){
| 1008-4984 | ||||||||||||||||||
1640 | disableTerm(pLevel, pRangeStart); | - | ||||||||||||||||||
1641 | }else{ executed 4984 times by 1 test: end of block Executed by:
| 4984 | ||||||||||||||||||
1642 | startEq = 1; | - | ||||||||||||||||||
1643 | } executed 1008 times by 1 test: end of block Executed by:
| 1008 | ||||||||||||||||||
1644 | bSeekPastNull = 0; | - | ||||||||||||||||||
1645 | }else if( bSeekPastNull ){ executed 5992 times by 1 test: end of block Executed by:
| 1527-23758 | ||||||||||||||||||
1646 | sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); | - | ||||||||||||||||||
1647 | nConstraint++; | - | ||||||||||||||||||
1648 | startEq = 0; | - | ||||||||||||||||||
1649 | start_constraints = 1; | - | ||||||||||||||||||
1650 | } executed 1527 times by 1 test: end of block Executed by:
| 1527 | ||||||||||||||||||
1651 | codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); | - | ||||||||||||||||||
1652 | if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
| 0-31233 | ||||||||||||||||||
1653 | /* The skip-scan logic inside the call to codeAllEqualityConstraints() | - | ||||||||||||||||||
1654 | ** above has already left the cursor sitting on the correct row, | - | ||||||||||||||||||
1655 | ** so no further seeking is needed */ | - | ||||||||||||||||||
1656 | }else{ never executed: end of block | 0 | ||||||||||||||||||
1657 | if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
| 223-31054 | ||||||||||||||||||
1658 | sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); | - | ||||||||||||||||||
1659 | } executed 223 times by 1 test: end of block Executed by:
| 223 | ||||||||||||||||||
1660 | op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; | - | ||||||||||||||||||
1661 | assert( op!=0 ); | - | ||||||||||||||||||
1662 | sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); | - | ||||||||||||||||||
1663 | VdbeCoverage(v); | - | ||||||||||||||||||
1664 | VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); | - | ||||||||||||||||||
1665 | VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); | - | ||||||||||||||||||
1666 | VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); | - | ||||||||||||||||||
1667 | VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); | - | ||||||||||||||||||
1668 | VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); | - | ||||||||||||||||||
1669 | VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); | - | ||||||||||||||||||
1670 | } executed 31277 times by 2 tests: end of block Executed by:
| 31277 | ||||||||||||||||||
1671 | - | |||||||||||||||||||
1672 | /* Load the value for the inequality constraint at the end of the | - | ||||||||||||||||||
1673 | ** range (if any). | - | ||||||||||||||||||
1674 | */ | - | ||||||||||||||||||
1675 | nConstraint = nEq; | - | ||||||||||||||||||
1676 | if( pRangeEnd ){
| 5913-25364 | ||||||||||||||||||
1677 | Expr *pRight = pRangeEnd->pExpr->pRight; | - | ||||||||||||||||||
1678 | codeExprOrVector(pParse, pRight, regBase+nEq, nTop); | - | ||||||||||||||||||
1679 | whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); | - | ||||||||||||||||||
1680 | if( (pRangeEnd->wtFlags & TERM_VNULL)==0
| 0-5913 | ||||||||||||||||||
1681 | && sqlite3ExprCanBeNull(pRight)
| 1122-4791 | ||||||||||||||||||
1682 | ){ | - | ||||||||||||||||||
1683 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); | - | ||||||||||||||||||
1684 | VdbeCoverage(v); | - | ||||||||||||||||||
1685 | } executed 1122 times by 1 test: end of block Executed by:
| 1122 | ||||||||||||||||||
1686 | if( zEndAff ){
| 6-5907 | ||||||||||||||||||
1687 | updateRangeAffinityStr(pRight, nTop, zEndAff); | - | ||||||||||||||||||
1688 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); | - | ||||||||||||||||||
1689 | }else{ executed 5907 times by 1 test: end of block Executed by:
| 5907 | ||||||||||||||||||
1690 | assert( pParse->db->mallocFailed ); | - | ||||||||||||||||||
1691 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||
1692 | nConstraint += nTop; | - | ||||||||||||||||||
1693 | testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1694 | - | |||||||||||||||||||
1695 | if( sqlite3ExprIsVector(pRight)==0 ){
| 1000-4913 | ||||||||||||||||||
1696 | disableTerm(pLevel, pRangeEnd); | - | ||||||||||||||||||
1697 | }else{ executed 4913 times by 1 test: end of block Executed by:
| 4913 | ||||||||||||||||||
1698 | endEq = 1; | - | ||||||||||||||||||
1699 | } executed 1000 times by 1 test: end of block Executed by:
| 1000 | ||||||||||||||||||
1700 | }else if( bStopAtNull ){
| 163-25201 | ||||||||||||||||||
1701 | sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); | - | ||||||||||||||||||
1702 | endEq = 0; | - | ||||||||||||||||||
1703 | nConstraint++; | - | ||||||||||||||||||
1704 | } executed 163 times by 1 test: end of block Executed by:
| 163 | ||||||||||||||||||
1705 | sqlite3DbFree(db, zStartAff); | - | ||||||||||||||||||
1706 | sqlite3DbFree(db, zEndAff); | - | ||||||||||||||||||
1707 | - | |||||||||||||||||||
1708 | /* Top of the loop body */ | - | ||||||||||||||||||
1709 | pLevel->p2 = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
1710 | - | |||||||||||||||||||
1711 | /* Check if the index cursor is past the end of the range. */ | - | ||||||||||||||||||
1712 | if( nConstraint ){
| 6226-25051 | ||||||||||||||||||
1713 | op = aEndOp[bRev*2 + endEq]; | - | ||||||||||||||||||
1714 | sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); | - | ||||||||||||||||||
1715 | testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); | - | ||||||||||||||||||
1716 | testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); | - | ||||||||||||||||||
1717 | testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); | - | ||||||||||||||||||
1718 | testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); | - | ||||||||||||||||||
1719 | } executed 25051 times by 1 test: end of block Executed by:
| 25051 | ||||||||||||||||||
1720 | - | |||||||||||||||||||
1721 | if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
| 223-31054 | ||||||||||||||||||
1722 | sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); | - | ||||||||||||||||||
1723 | } executed 223 times by 1 test: end of block Executed by:
| 223 | ||||||||||||||||||
1724 | - | |||||||||||||||||||
1725 | /* Seek the table cursor, if required */ | - | ||||||||||||||||||
1726 | if( omitTable ){
| 9827-21450 | ||||||||||||||||||
1727 | /* pIdx is a covering index. No need to access the main table. */ | - | ||||||||||||||||||
1728 | }else if( HasRowid(pIdx->pTable) ){ executed 9827 times by 1 test: end of block Executed by:
| 45-21405 | ||||||||||||||||||
1729 | if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
| 247-21158 | ||||||||||||||||||
1730 | (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
| 131-21027 | ||||||||||||||||||
1731 | && (pWInfo->eOnePass==ONEPASS_SINGLE)
| 45-86 | ||||||||||||||||||
1732 | )){ | - | ||||||||||||||||||
1733 | iRowidReg = ++pParse->nMem; | - | ||||||||||||||||||
1734 | sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); | - | ||||||||||||||||||
1735 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); | - | ||||||||||||||||||
1736 | VdbeCoverage(v); | - | ||||||||||||||||||
1737 | }else{ executed 333 times by 1 test: end of block Executed by:
| 333 | ||||||||||||||||||
1738 | codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); | - | ||||||||||||||||||
1739 | } executed 21072 times by 2 tests: end of block Executed by:
| 21072 | ||||||||||||||||||
1740 | }else if( iCur!=iIdxCur ){
| 7-38 | ||||||||||||||||||
1741 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); | - | ||||||||||||||||||
1742 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); | - | ||||||||||||||||||
1743 | for(j=0; j<pPk->nKeyCol; j++){
| 38-42 | ||||||||||||||||||
1744 | k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); | - | ||||||||||||||||||
1745 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); | - | ||||||||||||||||||
1746 | } executed 42 times by 1 test: end of block Executed by:
| 42 | ||||||||||||||||||
1747 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, | - | ||||||||||||||||||
1748 | iRowidReg, pPk->nKeyCol); VdbeCoverage(v); | - | ||||||||||||||||||
1749 | } executed 38 times by 1 test: end of block Executed by:
| 38 | ||||||||||||||||||
1750 | - | |||||||||||||||||||
1751 | /* If pIdx is an index on one or more expressions, then look through | - | ||||||||||||||||||
1752 | ** all the expressions in pWInfo and try to transform matching expressions | - | ||||||||||||||||||
1753 | ** into reference to index columns. | - | ||||||||||||||||||
1754 | ** | - | ||||||||||||||||||
1755 | ** Do not do this for the RHS of a LEFT JOIN. This is because the | - | ||||||||||||||||||
1756 | ** expression may be evaluated after OP_NullRow has been executed on | - | ||||||||||||||||||
1757 | ** the cursor. In this case it is important to do the full evaluation, | - | ||||||||||||||||||
1758 | ** as the result of the expression may not be NULL, even if all table | - | ||||||||||||||||||
1759 | ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a | - | ||||||||||||||||||
1760 | */ | - | ||||||||||||||||||
1761 | if( pLevel->iLeftJoin==0 ){
| 248-31029 | ||||||||||||||||||
1762 | whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); | - | ||||||||||||||||||
1763 | } executed 31029 times by 2 tests: end of block Executed by:
| 31029 | ||||||||||||||||||
1764 | - | |||||||||||||||||||
1765 | /* Record the instruction used to terminate the loop. */ | - | ||||||||||||||||||
1766 | if( pLoop->wsFlags & WHERE_ONEROW ){
| 878-30399 | ||||||||||||||||||
1767 | pLevel->op = OP_Noop; | - | ||||||||||||||||||
1768 | }else if( bRev ){ executed 878 times by 1 test: end of block Executed by:
| 878-28901 | ||||||||||||||||||
1769 | pLevel->op = OP_Prev; | - | ||||||||||||||||||
1770 | }else{ executed 1498 times by 1 test: end of block Executed by:
| 1498 | ||||||||||||||||||
1771 | pLevel->op = OP_Next; | - | ||||||||||||||||||
1772 | } executed 28901 times by 2 tests: end of block Executed by:
| 28901 | ||||||||||||||||||
1773 | pLevel->p1 = iIdxCur; | - | ||||||||||||||||||
1774 | pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0;
| 11785-19492 | ||||||||||||||||||
1775 | if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
| 4766-26511 | ||||||||||||||||||
1776 | pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; | - | ||||||||||||||||||
1777 | }else{ executed 4766 times by 2 tests: end of block Executed by:
| 4766 | ||||||||||||||||||
1778 | assert( pLevel->p5==0 ); | - | ||||||||||||||||||
1779 | } executed 26511 times by 1 test: end of block Executed by:
| 26511 | ||||||||||||||||||
1780 | if( omitTable ) pIdx = 0; executed 9827 times by 1 test: pIdx = 0; Executed by:
| 9827-21450 | ||||||||||||||||||
1781 | }else executed 31277 times by 2 tests: end of block Executed by:
| 31277 | ||||||||||||||||||
1782 | - | |||||||||||||||||||
1783 | #ifndef SQLITE_OMIT_OR_OPTIMIZATION | - | ||||||||||||||||||
1784 | if( pLoop->wsFlags & WHERE_MULTI_OR ){
| 2366-165074 | ||||||||||||||||||
1785 | /* Case 5: Two or more separately indexed terms connected by OR | - | ||||||||||||||||||
1786 | ** | - | ||||||||||||||||||
1787 | ** Example: | - | ||||||||||||||||||
1788 | ** | - | ||||||||||||||||||
1789 | ** CREATE TABLE t1(a,b,c,d); | - | ||||||||||||||||||
1790 | ** CREATE INDEX i1 ON t1(a); | - | ||||||||||||||||||
1791 | ** CREATE INDEX i2 ON t1(b); | - | ||||||||||||||||||
1792 | ** CREATE INDEX i3 ON t1(c); | - | ||||||||||||||||||
1793 | ** | - | ||||||||||||||||||
1794 | ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13) | - | ||||||||||||||||||
1795 | ** | - | ||||||||||||||||||
1796 | ** In the example, there are three indexed terms connected by OR. | - | ||||||||||||||||||
1797 | ** The top of the loop looks like this: | - | ||||||||||||||||||
1798 | ** | - | ||||||||||||||||||
1799 | ** Null 1 # Zero the rowset in reg 1 | - | ||||||||||||||||||
1800 | ** | - | ||||||||||||||||||
1801 | ** Then, for each indexed term, the following. The arguments to | - | ||||||||||||||||||
1802 | ** RowSetTest are such that the rowid of the current row is inserted | - | ||||||||||||||||||
1803 | ** into the RowSet. If it is already present, control skips the | - | ||||||||||||||||||
1804 | ** Gosub opcode and jumps straight to the code generated by WhereEnd(). | - | ||||||||||||||||||
1805 | ** | - | ||||||||||||||||||
1806 | ** sqlite3WhereBegin(<term>) | - | ||||||||||||||||||
1807 | ** RowSetTest # Insert rowid into rowset | - | ||||||||||||||||||
1808 | ** Gosub 2 A | - | ||||||||||||||||||
1809 | ** sqlite3WhereEnd() | - | ||||||||||||||||||
1810 | ** | - | ||||||||||||||||||
1811 | ** Following the above, code to terminate the loop. Label A, the target | - | ||||||||||||||||||
1812 | ** of the Gosub above, jumps to the instruction right after the Goto. | - | ||||||||||||||||||
1813 | ** | - | ||||||||||||||||||
1814 | ** Null 1 # Zero the rowset in reg 1 | - | ||||||||||||||||||
1815 | ** Goto B # The loop is finished. | - | ||||||||||||||||||
1816 | ** | - | ||||||||||||||||||
1817 | ** A: <loop body> # Return data, whatever. | - | ||||||||||||||||||
1818 | ** | - | ||||||||||||||||||
1819 | ** Return 2 # Jump back to the Gosub | - | ||||||||||||||||||
1820 | ** | - | ||||||||||||||||||
1821 | ** B: <after the loop> | - | ||||||||||||||||||
1822 | ** | - | ||||||||||||||||||
1823 | ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then | - | ||||||||||||||||||
1824 | ** use an ephemeral index instead of a RowSet to record the primary | - | ||||||||||||||||||
1825 | ** keys of the rows we have already seen. | - | ||||||||||||||||||
1826 | ** | - | ||||||||||||||||||
1827 | */ | - | ||||||||||||||||||
1828 | WhereClause *pOrWc; /* The OR-clause broken out into subterms */ | - | ||||||||||||||||||
1829 | SrcList *pOrTab; /* Shortened table list or OR-clause generation */ | - | ||||||||||||||||||
1830 | Index *pCov = 0; /* Potential covering index (or NULL) */ | - | ||||||||||||||||||
1831 | int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ | - | ||||||||||||||||||
1832 | - | |||||||||||||||||||
1833 | int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ | - | ||||||||||||||||||
1834 | int regRowset = 0; /* Register for RowSet object */ | - | ||||||||||||||||||
1835 | int regRowid = 0; /* Register holding rowid */ | - | ||||||||||||||||||
1836 | int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */ | - | ||||||||||||||||||
1837 | int iRetInit; /* Address of regReturn init */ | - | ||||||||||||||||||
1838 | int untestedTerms = 0; /* Some terms not completely tested */ | - | ||||||||||||||||||
1839 | int ii; /* Loop counter */ | - | ||||||||||||||||||
1840 | u16 wctrlFlags; /* Flags for sub-WHERE clause */ | - | ||||||||||||||||||
1841 | Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ | - | ||||||||||||||||||
1842 | Table *pTab = pTabItem->pTab; | - | ||||||||||||||||||
1843 | - | |||||||||||||||||||
1844 | pTerm = pLoop->aLTerm[0]; | - | ||||||||||||||||||
1845 | assert( pTerm!=0 ); | - | ||||||||||||||||||
1846 | assert( pTerm->eOperator & WO_OR ); | - | ||||||||||||||||||
1847 | assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); | - | ||||||||||||||||||
1848 | pOrWc = &pTerm->u.pOrInfo->wc; | - | ||||||||||||||||||
1849 | pLevel->op = OP_Return; | - | ||||||||||||||||||
1850 | pLevel->p1 = regReturn; | - | ||||||||||||||||||
1851 | - | |||||||||||||||||||
1852 | /* Set up a new SrcList in pOrTab containing the table being scanned | - | ||||||||||||||||||
1853 | ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. | - | ||||||||||||||||||
1854 | ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). | - | ||||||||||||||||||
1855 | */ | - | ||||||||||||||||||
1856 | if( pWInfo->nLevel>1 ){
| 120-2246 | ||||||||||||||||||
1857 | int nNotReady; /* The number of notReady tables */ | - | ||||||||||||||||||
1858 | struct SrcList_item *origSrc; /* Original list of tables */ | - | ||||||||||||||||||
1859 | nNotReady = pWInfo->nLevel - iLevel - 1; | - | ||||||||||||||||||
1860 | pOrTab = sqlite3StackAllocRaw(db, | - | ||||||||||||||||||
1861 | sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0])); | - | ||||||||||||||||||
1862 | if( pOrTab==0 ) return notReady; never executed: return notReady;
| 0-120 | ||||||||||||||||||
1863 | pOrTab->nAlloc = (u8)(nNotReady + 1); | - | ||||||||||||||||||
1864 | pOrTab->nSrc = pOrTab->nAlloc; | - | ||||||||||||||||||
1865 | memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); | - | ||||||||||||||||||
1866 | origSrc = pWInfo->pTabList->a; | - | ||||||||||||||||||
1867 | for(k=1; k<=nNotReady; k++){
| 83-120 | ||||||||||||||||||
1868 | memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); | - | ||||||||||||||||||
1869 | } executed 83 times by 1 test: end of block Executed by:
| 83 | ||||||||||||||||||
1870 | }else{ executed 120 times by 1 test: end of block Executed by:
| 120 | ||||||||||||||||||
1871 | pOrTab = pWInfo->pTabList; | - | ||||||||||||||||||
1872 | } executed 2246 times by 1 test: end of block Executed by:
| 2246 | ||||||||||||||||||
1873 | - | |||||||||||||||||||
1874 | /* Initialize the rowset register to contain NULL. An SQL NULL is | - | ||||||||||||||||||
1875 | ** equivalent to an empty rowset. Or, create an ephemeral index | - | ||||||||||||||||||
1876 | ** capable of holding primary keys in the case of a WITHOUT ROWID. | - | ||||||||||||||||||
1877 | ** | - | ||||||||||||||||||
1878 | ** Also initialize regReturn to contain the address of the instruction | - | ||||||||||||||||||
1879 | ** immediately following the OP_Return at the bottom of the loop. This | - | ||||||||||||||||||
1880 | ** is required in a few obscure LEFT JOIN cases where control jumps | - | ||||||||||||||||||
1881 | ** over the top of the loop into the body of it. In this case the | - | ||||||||||||||||||
1882 | ** correct response for the end-of-loop code (the OP_Return) is to | - | ||||||||||||||||||
1883 | ** fall through to the next instruction, just as an OP_Next does if | - | ||||||||||||||||||
1884 | ** called on an uninitialized cursor. | - | ||||||||||||||||||
1885 | */ | - | ||||||||||||||||||
1886 | if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
| 14-2352 | ||||||||||||||||||
1887 | if( HasRowid(pTab) ){
| 12-2340 | ||||||||||||||||||
1888 | regRowset = ++pParse->nMem; | - | ||||||||||||||||||
1889 | sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); | - | ||||||||||||||||||
1890 | }else{ executed 2340 times by 1 test: end of block Executed by:
| 2340 | ||||||||||||||||||
1891 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); | - | ||||||||||||||||||
1892 | regRowset = pParse->nTab++; | - | ||||||||||||||||||
1893 | sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol); | - | ||||||||||||||||||
1894 | sqlite3VdbeSetP4KeyInfo(pParse, pPk); | - | ||||||||||||||||||
1895 | } executed 12 times by 1 test: end of block Executed by:
| 12 | ||||||||||||||||||
1896 | regRowid = ++pParse->nMem; | - | ||||||||||||||||||
1897 | } executed 2352 times by 1 test: end of block Executed by:
| 2352 | ||||||||||||||||||
1898 | iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); | - | ||||||||||||||||||
1899 | - | |||||||||||||||||||
1900 | /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y | - | ||||||||||||||||||
1901 | ** Then for every term xN, evaluate as the subexpression: xN AND z | - | ||||||||||||||||||
1902 | ** That way, terms in y that are factored into the disjunction will | - | ||||||||||||||||||
1903 | ** be picked up by the recursive calls to sqlite3WhereBegin() below. | - | ||||||||||||||||||
1904 | ** | - | ||||||||||||||||||
1905 | ** Actually, each subexpression is converted to "xN AND w" where w is | - | ||||||||||||||||||
1906 | ** the "interesting" terms of z - terms that did not originate in the | - | ||||||||||||||||||
1907 | ** ON or USING clause of a LEFT JOIN, and terms that are usable as | - | ||||||||||||||||||
1908 | ** indices. | - | ||||||||||||||||||
1909 | ** | - | ||||||||||||||||||
1910 | ** This optimization also only applies if the (x1 OR x2 OR ...) term | - | ||||||||||||||||||
1911 | ** is not contained in the ON clause of a LEFT JOIN. | - | ||||||||||||||||||
1912 | ** See ticket http://www.sqlite.org/src/info/f2369304e4 | - | ||||||||||||||||||
1913 | */ | - | ||||||||||||||||||
1914 | if( pWC->nTerm>1 ){
| 66-2300 | ||||||||||||||||||
1915 | int iTerm; | - | ||||||||||||||||||
1916 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
| 66-166 | ||||||||||||||||||
1917 | Expr *pExpr = pWC->a[iTerm].pExpr; | - | ||||||||||||||||||
1918 | if( &pWC->a[iTerm] == pTerm ) continue; executed 66 times by 1 test: continue; Executed by:
| 66-100 | ||||||||||||||||||
1919 | testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
1920 | testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); | - | ||||||||||||||||||
1921 | if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; executed 60 times by 1 test: continue; Executed by:
| 40-60 | ||||||||||||||||||
1922 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; executed 8 times by 1 test: continue; Executed by:
| 8-32 | ||||||||||||||||||
1923 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); | - | ||||||||||||||||||
1924 | pExpr = sqlite3ExprDup(db, pExpr, 0); | - | ||||||||||||||||||
1925 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); | - | ||||||||||||||||||
1926 | } executed 32 times by 1 test: end of block Executed by:
| 32 | ||||||||||||||||||
1927 | if( pAndExpr ){
| 26-40 | ||||||||||||||||||
1928 | pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr); | - | ||||||||||||||||||
1929 | } executed 26 times by 1 test: end of block Executed by:
| 26 | ||||||||||||||||||
1930 | } executed 66 times by 1 test: end of block Executed by:
| 66 | ||||||||||||||||||
1931 | - | |||||||||||||||||||
1932 | /* Run a separate WHERE clause for each term of the OR clause. After | - | ||||||||||||||||||
1933 | ** eliminating duplicates from other WHERE clauses, the action for each | - | ||||||||||||||||||
1934 | ** sub-WHERE clause is to to invoke the main loop body as a subroutine. | - | ||||||||||||||||||
1935 | */ | - | ||||||||||||||||||
1936 | wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); | - | ||||||||||||||||||
1937 | ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); | - | ||||||||||||||||||
1938 | for(ii=0; ii<pOrWc->nTerm; ii++){
| 2366-17848 | ||||||||||||||||||
1939 | WhereTerm *pOrTerm = &pOrWc->a[ii]; | - | ||||||||||||||||||
1940 | if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
| 61-9714 | ||||||||||||||||||
1941 | WhereInfo *pSubWInfo; /* Info for single OR-term scan */ | - | ||||||||||||||||||
1942 | Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ | - | ||||||||||||||||||
1943 | int jmp1 = 0; /* Address of jump operation */ | - | ||||||||||||||||||
1944 | assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 | - | ||||||||||||||||||
1945 | || ExprHasProperty(pOrExpr, EP_FromJoin) | - | ||||||||||||||||||
1946 | ); | - | ||||||||||||||||||
1947 | if( pAndExpr ){
| 1608-16179 | ||||||||||||||||||
1948 | pAndExpr->pLeft = pOrExpr; | - | ||||||||||||||||||
1949 | pOrExpr = pAndExpr; | - | ||||||||||||||||||
1950 | } executed 1608 times by 1 test: end of block Executed by:
| 1608 | ||||||||||||||||||
1951 | /* Loop through table entries that match term pOrTerm. */ | - | ||||||||||||||||||
1952 | WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); | - | ||||||||||||||||||
1953 | pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, | - | ||||||||||||||||||
1954 | wctrlFlags, iCovCur); | - | ||||||||||||||||||
1955 | assert( pSubWInfo || pParse->nErr || db->mallocFailed ); | - | ||||||||||||||||||
1956 | if( pSubWInfo ){
| 0-17787 | ||||||||||||||||||
1957 | WhereLoop *pSubLoop; | - | ||||||||||||||||||
1958 | int addrExplain = sqlite3WhereExplainOneScan( | - | ||||||||||||||||||
1959 | pParse, pOrTab, &pSubWInfo->a[0], 0 | - | ||||||||||||||||||
1960 | ); | - | ||||||||||||||||||
1961 | sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); | - | ||||||||||||||||||
1962 | - | |||||||||||||||||||
1963 | /* This is the sub-WHERE clause body. First skip over | - | ||||||||||||||||||
1964 | ** duplicate rows from prior sub-WHERE clauses, and record the | - | ||||||||||||||||||
1965 | ** rowid (or PRIMARY KEY) for the current row so that the same | - | ||||||||||||||||||
1966 | ** row will be skipped in subsequent sub-WHERE clauses. | - | ||||||||||||||||||
1967 | */ | - | ||||||||||||||||||
1968 | if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
| 36-17751 | ||||||||||||||||||
1969 | int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
| 2335-15416 | ||||||||||||||||||
1970 | if( HasRowid(pTab) ){
| 25-17726 | ||||||||||||||||||
1971 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); | - | ||||||||||||||||||
1972 | jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, | - | ||||||||||||||||||
1973 | regRowid, iSet); | - | ||||||||||||||||||
1974 | VdbeCoverage(v); | - | ||||||||||||||||||
1975 | }else{ executed 17726 times by 1 test: end of block Executed by:
| 17726 | ||||||||||||||||||
1976 | Index *pPk = sqlite3PrimaryKeyIndex(pTab); | - | ||||||||||||||||||
1977 | int nPk = pPk->nKeyCol; | - | ||||||||||||||||||
1978 | int iPk; | - | ||||||||||||||||||
1979 | int r; | - | ||||||||||||||||||
1980 | - | |||||||||||||||||||
1981 | /* Read the PK into an array of temp registers. */ | - | ||||||||||||||||||
1982 | r = sqlite3GetTempRange(pParse, nPk); | - | ||||||||||||||||||
1983 | for(iPk=0; iPk<nPk; iPk++){
| 25-33 | ||||||||||||||||||
1984 | int iCol = pPk->aiColumn[iPk]; | - | ||||||||||||||||||
1985 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk); | - | ||||||||||||||||||
1986 | } executed 33 times by 1 test: end of block Executed by:
| 33 | ||||||||||||||||||
1987 | - | |||||||||||||||||||
1988 | /* Check if the temp table already contains this key. If so, | - | ||||||||||||||||||
1989 | ** the row has already been included in the result set and | - | ||||||||||||||||||
1990 | ** can be ignored (by jumping past the Gosub below). Otherwise, | - | ||||||||||||||||||
1991 | ** insert the key into the temp table and proceed with processing | - | ||||||||||||||||||
1992 | ** the row. | - | ||||||||||||||||||
1993 | ** | - | ||||||||||||||||||
1994 | ** Use some of the same optimizations as OP_RowSetTest: If iSet | - | ||||||||||||||||||
1995 | ** is zero, assume that the key cannot already be present in | - | ||||||||||||||||||
1996 | ** the temp table. And if iSet is -1, assume that there is no | - | ||||||||||||||||||
1997 | ** need to insert the key into the temp table, as it will never | - | ||||||||||||||||||
1998 | ** be tested for. */ | - | ||||||||||||||||||
1999 | if( iSet ){
| 12-13 | ||||||||||||||||||
2000 | jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); | - | ||||||||||||||||||
2001 | VdbeCoverage(v); | - | ||||||||||||||||||
2002 | } executed 13 times by 1 test: end of block Executed by:
| 13 | ||||||||||||||||||
2003 | if( iSet>=0 ){
| 12-13 | ||||||||||||||||||
2004 | sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); | - | ||||||||||||||||||
2005 | sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid, | - | ||||||||||||||||||
2006 | r, nPk); | - | ||||||||||||||||||
2007 | if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); executed 1 time by 1 test: sqlite3VdbeChangeP5(v, 0x10); Executed by:
| 1-12 | ||||||||||||||||||
2008 | } executed 13 times by 1 test: end of block Executed by:
| 13 | ||||||||||||||||||
2009 | - | |||||||||||||||||||
2010 | /* Release the array of temp registers */ | - | ||||||||||||||||||
2011 | sqlite3ReleaseTempRange(pParse, r, nPk); | - | ||||||||||||||||||
2012 | } executed 25 times by 1 test: end of block Executed by:
| 25 | ||||||||||||||||||
2013 | } | - | ||||||||||||||||||
2014 | - | |||||||||||||||||||
2015 | /* Invoke the main loop body as a subroutine */ | - | ||||||||||||||||||
2016 | sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); | - | ||||||||||||||||||
2017 | - | |||||||||||||||||||
2018 | /* Jump here (skipping the main loop body subroutine) if the | - | ||||||||||||||||||
2019 | ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */ | - | ||||||||||||||||||
2020 | if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1); executed 17739 times by 1 test: sqlite3VdbeJumpHere(v, jmp1); Executed by:
| 48-17739 | ||||||||||||||||||
2021 | - | |||||||||||||||||||
2022 | /* The pSubWInfo->untestedTerms flag means that this OR term | - | ||||||||||||||||||
2023 | ** contained one or more AND term from a notReady table. The | - | ||||||||||||||||||
2024 | ** terms from the notReady table could not be tested and will | - | ||||||||||||||||||
2025 | ** need to be tested later. | - | ||||||||||||||||||
2026 | */ | - | ||||||||||||||||||
2027 | if( pSubWInfo->untestedTerms ) untestedTerms = 1; executed 73 times by 1 test: untestedTerms = 1; Executed by:
| 73-17714 | ||||||||||||||||||
2028 | - | |||||||||||||||||||
2029 | /* If all of the OR-connected terms are optimized using the same | - | ||||||||||||||||||
2030 | ** index, and the index is opened using the same cursor number | - | ||||||||||||||||||
2031 | ** by each call to sqlite3WhereBegin() made by this loop, it may | - | ||||||||||||||||||
2032 | ** be possible to use that index as a covering index. | - | ||||||||||||||||||
2033 | ** | - | ||||||||||||||||||
2034 | ** If the call to sqlite3WhereBegin() above resulted in a scan that | - | ||||||||||||||||||
2035 | ** uses an index, and this is either the first OR-connected term | - | ||||||||||||||||||
2036 | ** processed or the index is the same as that used by all previous | - | ||||||||||||||||||
2037 | ** terms, set pCov to the candidate covering index. Otherwise, set | - | ||||||||||||||||||
2038 | ** pCov to NULL to indicate that no candidate covering index will | - | ||||||||||||||||||
2039 | ** be available. | - | ||||||||||||||||||
2040 | */ | - | ||||||||||||||||||
2041 | pSubLoop = pSubWInfo->a[0].pWLoop; | - | ||||||||||||||||||
2042 | assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); | - | ||||||||||||||||||
2043 | if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
| 4467-13320 | ||||||||||||||||||
2044 | && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
| 1007-11515 | ||||||||||||||||||
2045 | && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
| 4-2797 | ||||||||||||||||||
2046 | ){ | - | ||||||||||||||||||
2047 | assert( pSubWInfo->a[0].iIdxCur==iCovCur ); | - | ||||||||||||||||||
2048 | pCov = pSubLoop->u.btree.pIndex; | - | ||||||||||||||||||
2049 | }else{ executed 2808 times by 1 test: end of block Executed by:
| 2808 | ||||||||||||||||||
2050 | pCov = 0; | - | ||||||||||||||||||
2051 | } executed 14979 times by 1 test: end of block Executed by:
| 14979 | ||||||||||||||||||
2052 | - | |||||||||||||||||||
2053 | /* Finish the loop through table entries that match term pOrTerm. */ | - | ||||||||||||||||||
2054 | sqlite3WhereEnd(pSubWInfo); | - | ||||||||||||||||||
2055 | } executed 17787 times by 1 test: end of block Executed by:
| 17787 | ||||||||||||||||||
2056 | } executed 17787 times by 1 test: end of block Executed by:
| 17787 | ||||||||||||||||||
2057 | } executed 17848 times by 1 test: end of block Executed by:
| 17848 | ||||||||||||||||||
2058 | ExplainQueryPlanPop(pParse); | - | ||||||||||||||||||
2059 | pLevel->u.pCovidx = pCov; | - | ||||||||||||||||||
2060 | if( pCov ) pLevel->iIdxCur = iCovCur; executed 202 times by 1 test: pLevel->iIdxCur = iCovCur; Executed by:
| 202-2164 | ||||||||||||||||||
2061 | if( pAndExpr ){
| 26-2340 | ||||||||||||||||||
2062 | pAndExpr->pLeft = 0; | - | ||||||||||||||||||
2063 | sqlite3ExprDelete(db, pAndExpr); | - | ||||||||||||||||||
2064 | } executed 26 times by 1 test: end of block Executed by:
| 26 | ||||||||||||||||||
2065 | sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); | - | ||||||||||||||||||
2066 | sqlite3VdbeGoto(v, pLevel->addrBrk); | - | ||||||||||||||||||
2067 | sqlite3VdbeResolveLabel(v, iLoopBody); | - | ||||||||||||||||||
2068 | - | |||||||||||||||||||
2069 | if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab); executed 120 times by 1 test: sqlite3DbFree(db,pOrTab); Executed by:
| 120-2246 | ||||||||||||||||||
2070 | if( !untestedTerms ) disableTerm(pLevel, pTerm); executed 2327 times by 1 test: disableTerm(pLevel, pTerm); Executed by:
| 39-2327 | ||||||||||||||||||
2071 | }else executed 2366 times by 1 test: end of block Executed by:
| 2366 | ||||||||||||||||||
2072 | #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ | - | ||||||||||||||||||
2073 | - | |||||||||||||||||||
2074 | { | - | ||||||||||||||||||
2075 | /* Case 6: There is no usable index. We must do a complete | - | ||||||||||||||||||
2076 | ** scan of the entire table. | - | ||||||||||||||||||
2077 | */ | - | ||||||||||||||||||
2078 | static const u8 aStep[] = { OP_Next, OP_Prev }; | - | ||||||||||||||||||
2079 | static const u8 aStart[] = { OP_Rewind, OP_Last }; | - | ||||||||||||||||||
2080 | assert( bRev==0 || bRev==1 ); | - | ||||||||||||||||||
2081 | if( pTabItem->fg.isRecursive ){
| 272-164802 | ||||||||||||||||||
2082 | /* Tables marked isRecursive have only a single row that is stored in | - | ||||||||||||||||||
2083 | ** a pseudo-cursor. No need to Rewind or Next such cursors. */ | - | ||||||||||||||||||
2084 | pLevel->op = OP_Noop; | - | ||||||||||||||||||
2085 | }else{ executed 272 times by 1 test: end of block Executed by:
| 272 | ||||||||||||||||||
2086 | codeCursorHint(pTabItem, pWInfo, pLevel, 0); | - | ||||||||||||||||||
2087 | pLevel->op = aStep[bRev]; | - | ||||||||||||||||||
2088 | pLevel->p1 = iCur; | - | ||||||||||||||||||
2089 | pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); | - | ||||||||||||||||||
2090 | VdbeCoverageIf(v, bRev==0); | - | ||||||||||||||||||
2091 | VdbeCoverageIf(v, bRev!=0); | - | ||||||||||||||||||
2092 | pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; | - | ||||||||||||||||||
2093 | } executed 164802 times by 435 tests: end of block Executed by:
| 164802 | ||||||||||||||||||
2094 | } | - | ||||||||||||||||||
2095 | - | |||||||||||||||||||
2096 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS | - | ||||||||||||||||||
2097 | pLevel->addrVisit = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
2098 | #endif | - | ||||||||||||||||||
2099 | - | |||||||||||||||||||
2100 | /* Insert code to test every subexpression that can be completely | - | ||||||||||||||||||
2101 | ** computed using the current set of tables. | - | ||||||||||||||||||
2102 | ** | - | ||||||||||||||||||
2103 | ** This loop may run between one and three times, depending on the | - | ||||||||||||||||||
2104 | ** constraints to be generated. The value of stack variable iLoop | - | ||||||||||||||||||
2105 | ** determines the constraints coded by each iteration, as follows: | - | ||||||||||||||||||
2106 | ** | - | ||||||||||||||||||
2107 | ** iLoop==1: Code only expressions that are entirely covered by pIdx. | - | ||||||||||||||||||
2108 | ** iLoop==2: Code remaining expressions that do not contain correlated | - | ||||||||||||||||||
2109 | ** sub-queries. | - | ||||||||||||||||||
2110 | ** iLoop==3: Code all remaining expressions. | - | ||||||||||||||||||
2111 | ** | - | ||||||||||||||||||
2112 | ** An effort is made to skip unnecessary iterations of the loop. | - | ||||||||||||||||||
2113 | */ | - | ||||||||||||||||||
2114 | iLoop = (pIdx ? 1 : 2);
| 21450-257046 | ||||||||||||||||||
2115 | do{ | - | ||||||||||||||||||
2116 | int iNext = 0; /* Next value for iLoop */ | - | ||||||||||||||||||
2117 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
| 285808-348383 | ||||||||||||||||||
2118 | Expr *pE; | - | ||||||||||||||||||
2119 | int skipLikeAddr = 0; | - | ||||||||||||||||||
2120 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
2121 | testcase( pTerm->wtFlags & TERM_CODED ); | - | ||||||||||||||||||
2122 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; executed 172476 times by 30 tests: continue; Executed by:
| 172476-175907 | ||||||||||||||||||
2123 | if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
| 53673-122234 | ||||||||||||||||||
2124 | testcase( pWInfo->untestedTerms==0 | - | ||||||||||||||||||
2125 | && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); | - | ||||||||||||||||||
2126 | pWInfo->untestedTerms = 1; | - | ||||||||||||||||||
2127 | continue; executed 53673 times by 1 test: continue; Executed by:
| 53673 | ||||||||||||||||||
2128 | } | - | ||||||||||||||||||
2129 | pE = pTerm->pExpr; | - | ||||||||||||||||||
2130 | assert( pE!=0 ); | - | ||||||||||||||||||
2131 | if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
| 47-122044 | ||||||||||||||||||
2132 | continue; executed 47 times by 1 test: continue; Executed by:
| 47 | ||||||||||||||||||
2133 | } | - | ||||||||||||||||||
2134 | - | |||||||||||||||||||
2135 | if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
| 3039-109110 | ||||||||||||||||||
2136 | iNext = 2; | - | ||||||||||||||||||
2137 | continue; executed 10038 times by 1 test: continue; Executed by:
| 10038 | ||||||||||||||||||
2138 | } | - | ||||||||||||||||||
2139 | if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
| 77-112072 | ||||||||||||||||||
2140 | if( iNext==0 ) iNext = 3; executed 69 times by 1 test: iNext = 3; Executed by:
| 8-69 | ||||||||||||||||||
2141 | continue; executed 77 times by 1 test: continue; Executed by:
| 77 | ||||||||||||||||||
2142 | } | - | ||||||||||||||||||
2143 | - | |||||||||||||||||||
2144 | if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){
| 225-111847 | ||||||||||||||||||
2145 | /* If the TERM_LIKECOND flag is set, that means that the range search | - | ||||||||||||||||||
2146 | ** is sufficient to guarantee that the LIKE operator is true, so we | - | ||||||||||||||||||
2147 | ** can skip the call to the like(A,B) function. But this only works | - | ||||||||||||||||||
2148 | ** for strings. So do not skip the call to the function on the pass | - | ||||||||||||||||||
2149 | ** that compares BLOBs. */ | - | ||||||||||||||||||
2150 | #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS | - | ||||||||||||||||||
2151 | continue; | - | ||||||||||||||||||
2152 | #else | - | ||||||||||||||||||
2153 | u32 x = pLevel->iLikeRepCntr; | - | ||||||||||||||||||
2154 | if( x>0 ){
| 0-225 | ||||||||||||||||||
2155 | skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); | - | ||||||||||||||||||
2156 | } executed 225 times by 1 test: end of block Executed by:
| 225 | ||||||||||||||||||
2157 | VdbeCoverage(v); | - | ||||||||||||||||||
2158 | #endif | - | ||||||||||||||||||
2159 | } executed 225 times by 1 test: end of block Executed by:
| 225 | ||||||||||||||||||
2160 | #ifdef WHERETRACE_ENABLED /* 0xffff */ | - | ||||||||||||||||||
2161 | if( sqlite3WhereTrace ){ | - | ||||||||||||||||||
2162 | VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d", | - | ||||||||||||||||||
2163 | pWC->nTerm-j, pTerm, iLoop)); | - | ||||||||||||||||||
2164 | } | - | ||||||||||||||||||
2165 | #endif | - | ||||||||||||||||||
2166 | sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); | - | ||||||||||||||||||
2167 | if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); executed 225 times by 1 test: sqlite3VdbeJumpHere(v, skipLikeAddr); Executed by:
| 225-111847 | ||||||||||||||||||
2168 | pTerm->wtFlags |= TERM_CODED; | - | ||||||||||||||||||
2169 | } executed 112072 times by 366 tests: end of block Executed by:
| 112072 | ||||||||||||||||||
2170 | iLoop = iNext; | - | ||||||||||||||||||
2171 | }while( iLoop>0 ); executed 285808 times by 435 tests: end of block Executed by:
| 7312-285808 | ||||||||||||||||||
2172 | - | |||||||||||||||||||
2173 | /* Insert code to test for implied constraints based on transitivity | - | ||||||||||||||||||
2174 | ** of the "==" operator. | - | ||||||||||||||||||
2175 | ** | - | ||||||||||||||||||
2176 | ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" | - | ||||||||||||||||||
2177 | ** and we are coding the t1 loop and the t2 loop has not yet coded, | - | ||||||||||||||||||
2178 | ** then we cannot use the "t1.a=t2.b" constraint, but we can code | - | ||||||||||||||||||
2179 | ** the implied "t1.a=123" constraint. | - | ||||||||||||||||||
2180 | */ | - | ||||||||||||||||||
2181 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
| 278496-329064 | ||||||||||||||||||
2182 | Expr *pE, sEAlt; | - | ||||||||||||||||||
2183 | WhereTerm *pAlt; | - | ||||||||||||||||||
2184 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; executed 275381 times by 368 tests: continue; Executed by:
| 53683-275381 | ||||||||||||||||||
2185 | if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; executed 2681 times by 1 test: continue; Executed by:
| 2681-51002 | ||||||||||||||||||
2186 | if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; executed 46966 times by 1 test: continue; Executed by:
| 4036-46966 | ||||||||||||||||||
2187 | if( pTerm->leftCursor!=iCur ) continue; executed 2411 times by 1 test: continue; Executed by:
| 1625-2411 | ||||||||||||||||||
2188 | if( pLevel->iLeftJoin ) continue; executed 1 time by 1 test: continue; Executed by:
| 1-1624 | ||||||||||||||||||
2189 | pE = pTerm->pExpr; | - | ||||||||||||||||||
2190 | assert( !ExprHasProperty(pE, EP_FromJoin) ); | - | ||||||||||||||||||
2191 | assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); | - | ||||||||||||||||||
2192 | pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady, | - | ||||||||||||||||||
2193 | WO_EQ|WO_IN|WO_IS, 0); | - | ||||||||||||||||||
2194 | if( pAlt==0 ) continue; executed 1599 times by 1 test: continue; Executed by:
| 25-1599 | ||||||||||||||||||
2195 | if( pAlt->wtFlags & (TERM_CODED) ) continue; executed 21 times by 1 test: continue; Executed by:
| 4-21 | ||||||||||||||||||
2196 | if( (pAlt->eOperator & WO_IN)
| 0-4 | ||||||||||||||||||
2197 | && (pAlt->pExpr->flags & EP_xIsSelect)
| 2 | ||||||||||||||||||
2198 | && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
| 0-2 | ||||||||||||||||||
2199 | ){ | - | ||||||||||||||||||
2200 | continue; executed 2 times by 1 test: continue; Executed by:
| 2 | ||||||||||||||||||
2201 | } | - | ||||||||||||||||||
2202 | testcase( pAlt->eOperator & WO_EQ ); | - | ||||||||||||||||||
2203 | testcase( pAlt->eOperator & WO_IS ); | - | ||||||||||||||||||
2204 | testcase( pAlt->eOperator & WO_IN ); | - | ||||||||||||||||||
2205 | VdbeModuleComment((v, "begin transitive constraint")); | - | ||||||||||||||||||
2206 | sEAlt = *pAlt->pExpr; | - | ||||||||||||||||||
2207 | sEAlt.pLeft = pE->pLeft; | - | ||||||||||||||||||
2208 | sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); | - | ||||||||||||||||||
2209 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||
2210 | - | |||||||||||||||||||
2211 | /* For a LEFT OUTER JOIN, generate code that will record the fact that | - | ||||||||||||||||||
2212 | ** at least one row of the right table has matched the left table. | - | ||||||||||||||||||
2213 | */ | - | ||||||||||||||||||
2214 | if( pLevel->iLeftJoin ){
| 425-278071 | ||||||||||||||||||
2215 | pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); | - | ||||||||||||||||||
2216 | sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); | - | ||||||||||||||||||
2217 | VdbeComment((v, "record LEFT JOIN hit")); | - | ||||||||||||||||||
2218 | for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
| 425-1514 | ||||||||||||||||||
2219 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); | - | ||||||||||||||||||
2220 | testcase( pTerm->wtFlags & TERM_CODED ); | - | ||||||||||||||||||
2221 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; executed 1347 times by 1 test: continue; Executed by:
| 167-1347 | ||||||||||||||||||
2222 | if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
| 45-122 | ||||||||||||||||||
2223 | assert( pWInfo->untestedTerms ); | - | ||||||||||||||||||
2224 | continue; executed 122 times by 1 test: continue; Executed by:
| 122 | ||||||||||||||||||
2225 | } | - | ||||||||||||||||||
2226 | assert( pTerm->pExpr ); | - | ||||||||||||||||||
2227 | sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); | - | ||||||||||||||||||
2228 | pTerm->wtFlags |= TERM_CODED; | - | ||||||||||||||||||
2229 | } executed 45 times by 1 test: end of block Executed by:
| 45 | ||||||||||||||||||
2230 | } executed 425 times by 1 test: end of block Executed by:
| 425 | ||||||||||||||||||
2231 | - | |||||||||||||||||||
2232 | return pLevel->notReady; executed 278496 times by 435 tests: return pLevel->notReady; Executed by:
| 278496 | ||||||||||||||||||
2233 | } | - | ||||||||||||||||||
Source code | Switch to Preprocessed file |