Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5d4bd81a2 | |||
| 37b8ba56dc | |||
| 39dde1aa17 |
@@ -1,5 +1,5 @@
|
||||
C New\stest-control\sthat\sreturns\sthe\snumber\sof\scalls\sto\nsqlite3BtreeMovetoUnpacked()\son\sthe\smain\sdatabase\sand\sthen\sresets\sthe\ncounter.\s\sThis\sonly\sworks\sfor\sSQLITE_DEBUG\sbuilds.
|
||||
D 2020-08-31T18:49:04.199
|
||||
C Minor\schanges\s-\sfix\sa\scompiler\swarning\sand\sadd\san\sassert().
|
||||
D 2020-09-01T00:09:45.771
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -499,7 +499,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 7e081d33aab4a9d761c39dccf3c3872c35501565d2ed9db66301918d23bc7901
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 436af4968c6954d304fce9efa12719367bd8f37b19b93b71d6ad607e85adbb47
|
||||
F src/main.c e913d3c2a1743c065fee9a00debb50d5f95b289401435c49a981609f390ae537
|
||||
F src/main.c 1e63a47af5315b1b4a743eb26185f656b56157cf41176349c5f94114bd09ba44
|
||||
F src/malloc.c 22d5bdd9fe88ae4fad1b91a1b9735104b82853ffef868f1f05517d60dc1875f5
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -607,9 +607,9 @@ F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
|
||||
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
|
||||
F src/vdbe.c c5da1456c9de0993055be9c10ebc5f5eb2be75d28cb01c8abc2f083923835a2d
|
||||
F src/vdbe.c bc2a53bf3a0ea9b303106139e8a8b3765c27c3a2f57068ef8116bfc215ca9b36
|
||||
F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
|
||||
F src/vdbeInt.h 762abffb7709f19c2cb74af1bba73a900f762e64f80d69c31c9ae89ed1066b60
|
||||
F src/vdbeInt.h 43341faf09fb620acc962be62ae339e7b77715207862e2b2e596f7f2f39e3828
|
||||
F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
|
||||
F src/vdbeaux.c b39d2e0e7126cd4629874dd7b67162b9f0d200b620d2b4c16d400949a2f1094b
|
||||
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
|
||||
@@ -624,7 +624,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
|
||||
F src/where.c 23f47e845e304a41d0b221bf67bd170014ae08b673076813fcd945dda1a3d4af
|
||||
F src/whereInt.h eb8c2847fb464728533777efec1682b3c074224293b2da73513c61a609efbeab
|
||||
F src/wherecode.c 110fa357bf453e0d30bf5ebb2cc86ea34a3631c39b857f30c228fd325cb53ae7
|
||||
F src/wherecode.c 28b243fe624a0f111c7680eb0fe6e9c23b6b0a5b35f9a0f75e87ae1534b7615a
|
||||
F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
|
||||
F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
@@ -1879,7 +1879,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 62f7d2a61259f296ffdcb3b3ee1a13925c4563ac8ed669f8a8a63fc7bc3a0a37
|
||||
R 36c4a7f200dd414f60f8ce85e07a7d72
|
||||
P 689ede95644fb45ecaeae539d4e3163819f5de2c50e76bf6860f3a0c184d6e57
|
||||
R a1cb332ff51a57074a0e0041bc85403c
|
||||
U drh
|
||||
Z c26168864fbe1f1e12628f6c3cbbb874
|
||||
Z 3090de8c3b9d02274474dc76197de746
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
dca5b91926431768babac28a6faf7674a5014db95caba727995b470e92b3182a
|
||||
07222dce106d22257fa5dc8ec46296ae47b7fc8345fd4d7aa0a4b15ddd40f3cb
|
||||
@@ -4248,6 +4248,7 @@ int sqlite3_test_control(int op, ...){
|
||||
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;
|
||||
}
|
||||
|
||||
+134
-58
@@ -137,6 +137,54 @@ static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
|
||||
}
|
||||
#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
|
||||
@@ -4286,18 +4334,12 @@ case OP_SeekGT: { /* jump, in3, group */
|
||||
/* 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.
|
||||
** 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;
|
||||
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
|
||||
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
||||
assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT );
|
||||
assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT );
|
||||
assert( pOp[1].p1==pOp[0].p1 );
|
||||
assert( pOp[1].p2==pOp[0].p2 );
|
||||
assert( pOp[1].p3==pOp[0].p3 );
|
||||
assert( pOp[1].p4.i==pOp[0].p4.i );
|
||||
eqOnly = 1 + (pOp[1].opcode==OP_SeekHit);
|
||||
assert( seekFollowedByPairedIdxCompare(pOp) );
|
||||
}
|
||||
|
||||
nField = pOp->p4.i;
|
||||
@@ -4377,8 +4419,8 @@ seek_not_found:
|
||||
if( res ){
|
||||
goto jump_to_p2;
|
||||
}else if( eqOnly ){
|
||||
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
||||
pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
|
||||
assert( pOp[eqOnly].opcode==OP_IdxLT || pOp[eqOnly].opcode==OP_IdxGT );
|
||||
pOp += eqOnly; /* Skip the OP_IdxLt or OP_IdxGT that follows */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4389,16 +4431,16 @@ seek_not_found:
|
||||
** 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 a boolean value,
|
||||
** either 0 or 1.
|
||||
** 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==1 );
|
||||
pC->seekHit = pOp->p2 & 1;
|
||||
assert( pOp->p2>=0 && pOp->p2<=3 );
|
||||
pC->seekHit = pOp->p2 & 3;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4452,33 +4494,6 @@ case OP_IfNotOpen: { /* jump */
|
||||
**
|
||||
** See also: Found, NotExists, NoConflict, IfNoHope
|
||||
*/
|
||||
/* Opcode: IfNoHope P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
** Register P3 is the first of P4 registers that form an unpacked
|
||||
** record.
|
||||
**
|
||||
** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
|
||||
** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
|
||||
** check to see if there is any entry in P1 that matches the
|
||||
** prefix identified by P3 and P4. If no entry matches the prefix,
|
||||
** jump to P2. Otherwise fall through.
|
||||
**
|
||||
** This opcode behaves like OP_NotFound if the seekHit
|
||||
** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
** See also: NotFound, SeekHit
|
||||
*/
|
||||
/* Opcode: NoConflict P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
@@ -4502,15 +4517,6 @@ case OP_IfNotOpen: { /* jump */
|
||||
**
|
||||
** See also: NotFound, Found, NotExists
|
||||
*/
|
||||
case OP_IfNoHope: { /* jump, in3 */
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
if( pC->seekHit ) break;
|
||||
/* Fall through into OP_NotFound */
|
||||
/* no break */ deliberate_fall_through
|
||||
}
|
||||
case OP_NoConflict: /* jump, in3 */
|
||||
case OP_NotFound: /* jump, in3 */
|
||||
case OP_Found: { /* jump, in3 */
|
||||
@@ -4527,6 +4533,7 @@ case OP_Found: { /* jump, in3 */
|
||||
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];
|
||||
@@ -5865,14 +5872,15 @@ case OP_FinishSeek: {
|
||||
** 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 */
|
||||
case OP_IdxGT: /* jump */
|
||||
case OP_IdxLT: /* jump */
|
||||
case OP_IdxGE: { /* jump */
|
||||
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 );
|
||||
@@ -5887,7 +5895,8 @@ case OP_IdxGE: { /* jump */
|
||||
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
|
||||
r.default_rc = -1;
|
||||
}else{
|
||||
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
|
||||
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT
|
||||
|| pOp->opcode==OP_IfNoHope );
|
||||
r.default_rc = 0;
|
||||
}
|
||||
r.aMem = &aMem[pOp->p3];
|
||||
@@ -5904,7 +5913,8 @@ case OP_IdxGE: { /* jump */
|
||||
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 );
|
||||
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 );
|
||||
@@ -5916,6 +5926,72 @@ case OP_IdxGE: { /* jump */
|
||||
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
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ struct VdbeCursor {
|
||||
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 */
|
||||
Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
|
||||
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 */
|
||||
|
||||
+4
-1
@@ -1870,6 +1870,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
|
||||
/* 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);
|
||||
@@ -1902,7 +1905,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
|
||||
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
|
||||
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 2);
|
||||
}
|
||||
|
||||
/* Seek the table cursor, if required */
|
||||
|
||||
Reference in New Issue
Block a user