Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch in-early-out-fail Excluding Merge-Ins
This is equivalent to a diff from dca5b91926 to 07222dce10
2020-09-01
| ||
00:26 | Fix a harmless compiler warning. (check-in: 3ca0b7d54d user: drh tags: trunk) | |
00:09 | Minor changes - fix a compiler warning and add an assert(). (Closed-Leaf check-in: 07222dce10 user: drh tags: in-early-out-fail) | |
2020-08-31
| ||
19:58 | Merge the SEEK_COUNT instrumentation enhancement from trunk. (check-in: 689ede9564 user: drh tags: in-early-out-fail) | |
18:49 | New test-control that returns the number of calls to sqlite3BtreeMovetoUnpacked() on the main database and then resets the counter. This only works for SQLITE_DEBUG builds. (check-in: dca5b91926 user: drh tags: trunk) | |
12:29 | Fix the documentation for the OP_IdxGT family of opcodes to show that the P5 operand is not used. (check-in: 62f7d2a612 user: drh tags: trunk) | |
Changes to src/main.c.
︙ | ︙ | |||
4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 | ** This test-control queries the seek-counter on the "main" database ** file. The seek-counter is written into *pnSeek and is then reset. ** The seek-count is only available if compiled with SQLITE_DEBUG. */ case SQLITE_TESTCTRL_SEEK_COUNT: { sqlite3 *db = va_arg(ap, sqlite3*); u64 *pn = va_arg(ap, sqlite3_uint64*); *pn = sqlite3BtreeSeekCount(db->aDb->pBt); break; } } va_end(ap); | > | 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 | ** This test-control queries the seek-counter on the "main" database ** file. The seek-counter is written into *pnSeek and is then reset. ** The seek-count is only available if compiled with SQLITE_DEBUG. */ case SQLITE_TESTCTRL_SEEK_COUNT: { sqlite3 *db = va_arg(ap, sqlite3*); u64 *pn = va_arg(ap, sqlite3_uint64*); (void)db; /* Silence a harmless warning */ *pn = sqlite3BtreeSeekCount(db->aDb->pBt); break; } } va_end(ap); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
133 134 135 136 137 138 139 140 141 142 143 144 145 146 | */ static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ static int n = 0; n++; } #endif /* ** Invoke the VDBE coverage callback, if that callback is defined. This ** feature is used for test suite validation only and does not appear an ** production builds. ** ** M is the type of branch. I is the direction taken for this instance of ** the branch. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | */ static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ static int n = 0; n++; } #endif #ifdef SQLITE_DEBUG /* This is a validation routine that occurs only inside of assert() ** statements. Its purpose is to verify that the generated bytecode ** is correct. It only runs on debugging builds. ** ** Verify that the pOp opcode is an OP_SeekGE or OP_SeekLE that is ** followed by a corresponding OP_IdxGT or OP_IdxLT, possibly with ** an intervening OP_SeekHit. Return 1 if the constraint is true. ** Return 0 if something unexpected is seen. */ static int seekFollowedByPairedIdxCompare(VdbeOp *pOp){ VdbeOp *pNext; /* Find the subsequent opcode. We are allowed to skip over a single ** OP_SeekHit against the same cursor with a P2 value of 1. */ pNext = pOp + 1; if( pNext->opcode==OP_SeekHit ){ if( pNext->p2!=1 ) return 0; if( pNext->p1!=pOp->p1 ) return 0; pNext++; } /* This routine verifies that the opcodes are correct for a ** BTREE_SEEK_EQ lookup. So the two opcodes involved must be either: ** ** * OP_SeekGE followed by OP_IdxGT ** * OP_SeekLE followed by OP_IdxLT */ if( pOp->opcode==OP_SeekGE ){ if( pNext->opcode!=OP_IdxGT ) return 0; }else if( pOp->opcode==OP_SeekLE ){ if( pNext->opcode!=OP_IdxLT ) return 0; }else{ return 0; } /* The OP_SeekXX and OP_IdxXX must have the same arguments. */ if( pOp->p1!=pNext->p1 ) return 0; if( pOp->p2!=pNext->p2 ) return 0; if( pOp->p3!=pNext->p3 ) return 0; if( pOp->p4.i!=pNext->p4.i ) return 0; return 1; } #endif /* SQLITE_DEBUG */ /* ** Invoke the VDBE coverage callback, if that callback is defined. This ** feature is used for test suite validation only and does not appear an ** production builds. ** ** M is the type of branch. I is the direction taken for this instance of ** the branch. |
︙ | ︙ | |||
4282 4283 4284 4285 4286 4287 4288 | if( rc!=SQLITE_OK ){ goto abort_due_to_error; } }else{ /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively, | | > | < < < < | < < < | 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 | if( rc!=SQLITE_OK ){ goto abort_due_to_error; } }else{ /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively, ** with the same key. There might be a single OP_SeekHit opcode in ** between the OP_SeekXX and OP_IdxXX. */ if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){ eqOnly = 1 + (pOp[1].opcode==OP_SeekHit); assert( seekFollowedByPairedIdxCompare(pOp) ); } nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); assert( nField>0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)nField; |
︙ | ︙ | |||
4373 4374 4375 4376 4377 4378 4379 | } seek_not_found: assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ goto jump_to_p2; }else if( eqOnly ){ | | | | | | | | 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 | } seek_not_found: assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ goto jump_to_p2; }else if( eqOnly ){ assert( pOp[eqOnly].opcode==OP_IdxLT || pOp[eqOnly].opcode==OP_IdxGT ); pOp += eqOnly; /* Skip the OP_IdxLt or OP_IdxGT that follows */ } break; } /* Opcode: SeekHit P1 P2 * * * ** Synopsis: seekHit=P2 ** ** Set the seekHit flag on cursor P1 to the value in P2. ** The seekHit flag is used by the IfNoHope opcode. ** ** P1 must be a valid b-tree cursor. P2 must be an integer ** between 0 and 3. */ case OP_SeekHit: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pOp->p2>=0 && pOp->p2<=3 ); pC->seekHit = pOp->p2 & 3; break; } /* Opcode: IfNotOpen P1 P2 * * * ** Synopsis: if( !csr[P1] ) goto P2 ** ** If cursor P1 is not open, jump to instruction P2. Otherwise, fall through. |
︙ | ︙ | |||
4448 4449 4450 4451 4452 4453 4454 | ** ** This operation leaves the cursor in a state where it cannot be ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** ** See also: Found, NotExists, NoConflict, IfNoHope */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 | ** ** This operation leaves the cursor in a state where it cannot be ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** ** See also: Found, NotExists, NoConflict, IfNoHope */ /* Opcode: NoConflict P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If P4==0 then register P3 holds a blob constructed by MakeRecord. If ** P4>0 then register P3 is the first of P4 registers that form an unpacked ** record. ** |
︙ | ︙ | |||
4498 4499 4500 4501 4502 4503 4504 | ** ** This operation leaves the cursor in a state where it cannot be ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** ** See also: NotFound, Found, NotExists */ | < < < < < < < < < > | 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 | ** ** This operation leaves the cursor in a state where it cannot be ** advanced in either direction. In other words, the Next and Prev ** opcodes do not work after this operation. ** ** See also: NotFound, Found, NotExists */ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; int takeJump; int ii; VdbeCursor *pC; int res; UnpackedRecord *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; #endif vdbe_op_notfound: /* OP_IfNoHope jumps here, sometimes */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p4type==P4_INT32 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif |
︙ | ︙ | |||
5861 5862 5863 5864 5865 5866 5867 | ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. ** ** If the P1 index entry is less than or equal to the key value then jump ** to P2. Otherwise fall through to the next instruction. */ | | | | | > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 | ** key that omits the PRIMARY KEY or ROWID. Compare this key value against ** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ** ROWID on the P1 index. ** ** If the P1 index entry is less than or equal to the key value then jump ** to P2. Otherwise fall through to the next instruction. */ case OP_IdxLE: /* jump, group */ case OP_IdxGT: /* jump, group */ case OP_IdxLT: /* jump, group */ case OP_IdxGE: { /* jump, group */ VdbeCursor *pC; int res; UnpackedRecord r; vdbe_op_idxne: /* Virtual OP_IdxNE opcode. See OP_IfNoHope */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->isOrdered ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0); assert( pC->deferredMoveto==0 ); assert( pOp->p4type==P4_INT32 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; if( pOp->opcode<OP_IdxLT ){ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); r.default_rc = -1; }else{ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT || pOp->opcode==OP_IfNoHope ); r.default_rc = 0; } r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG { int i; for(i=0; i<r.nField; i++){ assert( memIsValid(&r.aMem[i]) ); REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]); } } #endif res = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); if( (pOp->opcode&1)==(OP_IdxLT&1) ){ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT || pOp->opcode==OP_IfNoHope ); res = -res; }else{ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); res++; } VdbeBranchTaken(res>0,2); if( rc ) goto abort_due_to_error; if( res>0 ) goto jump_to_p2; break; } /* Opcode: IfNoHope P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** Register P3 is the first of P4 registers that form an unpacked ** record. P1 is number of an index-btree cursor. P2 is a jump ** destination. So, in other words, the operands to this opcode ** are the same as the operands to OP_NotFound and OP_IdxGT. ** ** The behavior of this opcode depends on the current seekFlag setting. ** (See the OP_SeekHit.) ** ** <ul> ** <li> seekHit==0 → OP_NotFound ** <li> seekHit==1 → OP_IdxGT or OP_IdxLT ** <li> seekHit==2 → OP_Noop ** </ul> ** ** Actually, when seekHit==1, this routine behaves as if it were an ** OP_IdxNE opcode. It has all the same parameters as OP_IdxGT and ** OP_IdxLT, but the jump is taken if the key is not equal to the index ** record, rather than if the key is greater than or less than the ** index record, respectively. ** ** This opcode is used in IN clause processing for a multi-column key. ** If an IN clause is attached to an element of the key other than the ** left-most element, and if there are no matches on the most recent ** seek over the whole key, then it might be that one of the key element ** to the left is prohibiting a match, and hence there is "no hope" of ** any match regardless of how many IN clause elements are checked. ** In such a case, we abandon the IN clause search early, using this ** opcode. The opcode name comes from the fact that the ** jump is taken if there is "no hope" of achieving a match. ** ** This opcode is an optimization. It can always behave as OP_Noop ** and the correct result will still be obtained, though perhaps not ** quite as quickly. ** ** See also: NotFound, SeekHit, IdxGT */ case OP_IfNoHope: { /* jump, in3, group */ VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); if( pC->seekHit>=2 ){ /* There has been one or more successful OP_IdxXX opcodes ("successful" ** in the sense that the jump was not taken because the key and index ** matched). So a match is possible. We do not want to abort. Fall ** through to the next opcode without doing anything. */ break; }else if( pC->seekHit==1 ){ /* The initial OP_SeekXX opcode was successful (in that it found a ** candidate row) but all subsequent OP_IdxXX opcodes failed. The ** index should have been left pointing at the candidate row. In this ** case, this opcode works like a "OP_IdxNE" opcode - similar to ** OP_IdxGT but instead of jumping if the index entry is greater than ** the key, it jumps if the index entry is not equal to the key. */ goto vdbe_op_idxne; } /* The initial OP_SeekXX opcode took its jump, meaning that it found ** no candidate rows. Treat this opcode as if it were an OP_NotFound */ goto vdbe_op_notfound; } /* Opcode: Destroy P1 P2 P3 * * ** ** Delete an entire database table or index whose root page in the database ** file is given by P1. ** ** The table being destroyed is in the main database file if P3==0. If |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
82 83 84 85 86 87 88 | #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ | | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ unsigned seekHit:2; /* See the OP_SeekHit and OP_IfNoHope opcodes */ Btree *pBtx; /* Separate file holding temporary table */ i64 seqCount; /* Sequence counter */ u32 *aAltMap; /* Mapping from table to index column numbers */ /* Cached OP_Column parse information is only valid if cacheStatus matches ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 | sqlite3DbFree(db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ if( regBignull ){ /* Except, skip the end-of-range check while doing the NULL-scan */ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); VdbeComment((v, "If NULL-scan 2nd pass")); VdbeCoverage(v); } op = aEndOp[bRev*2 + endEq]; | > > > | 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 | sqlite3DbFree(db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); } if( regBignull ){ /* Except, skip the end-of-range check while doing the NULL-scan */ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); VdbeComment((v, "If NULL-scan 2nd pass")); VdbeCoverage(v); } op = aEndOp[bRev*2 + endEq]; |
︙ | ︙ | |||
1898 1899 1900 1901 1902 1903 1904 | testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ | | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 | testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 2); } /* Seek the table cursor, if required */ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0; if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ |
︙ | ︙ |