1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Add logic to do test coverage measurements on the VDBE code.

FossilOrigin-Name: ce184c7bb16988641d37c908d9b3042456d4be3d
This commit is contained in:
drh
2014-02-17 22:40:43 +00:00
parent 8be09304b7
commit 688852ab15
21 changed files with 349 additions and 178 deletions

View File

@@ -1,5 +1,5 @@
C Add\sa\stest\scase\sfor\sOP_SoftNull. C Add\slogic\sto\sdo\stest\scoverage\smeasurements\son\sthe\sVDBE\scode.
D 2014-02-17T15:40:19.609 D 2014-02-17T22:40:43.958
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -156,8 +156,8 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c d5348d0f86a5fc8fb3987727402f023953c021cf F src/alter.c 829d67a359b7c5d37120be994af2c0eac730070c
F src/analyze.c 3ec444402a5d9ac1018ac8c549f8e82ac23d4122 F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
@@ -166,26 +166,26 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200 F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200
F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
F src/build.c 13b9d82181d95af7b00ec8a8e1304bac096432d4 F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 57a09d3d576dd15cd54d945b7b0b478bac71f379 F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7
F src/expr.c 90bba0ca6ec97d6857458f08a8ad2820130e13cf F src/expr.c d1a8ccbf7e4dac6198674d33853e8ed01072eca4
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c b3da26dfcd53a68e1b7162a84e0bf70e54092647 F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c ddc56dc855069ddf530127a346ddc2e67f0396e6 F src/insert.c 5d5e1d78f74804739b424c92346bdc26c146dfa4
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 07225af6a00be0b7f34ac52e60f99cf5cbb2a475 F src/main.c e054917b1beb3081b0f23e8bdd3d6c0e12933dd3
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
@@ -210,18 +210,18 @@ F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/pragma.c 769d08f10b7848dbd1950d0723bfcb12fb22b7f3 F src/pragma.c 2635d6bf8b54003ebefd773df2f50258cece2bec
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c ebec4d3fad7fd5aa33cd69e2f50e9c109285dc73 F src/select.c 618b53bd4553bd7a9ef95069396f12a8f28489e7
F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h c5ba0868bddac9fdb0df4686ab43150fefb27da5 F src/sqliteInt.h 004bd50575a05eefba7228c2d0fee432a53200de
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -272,17 +272,17 @@ F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78 F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
F src/trigger.c a417d386e214f0abd2e0f756b834b4d9f4d3368a F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc
F src/update.c b126167ee39470b6148fa3f89182e7c855dc15d0 F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c e3ba6ad0111dbd4234fef5e119dbe30d0abb3cf1 F src/vdbe.c 392f03b25152eb44565a78b8b809743c97e5852b
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320
F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
F src/vdbeaux.c 9098973ff22c6fdfd68d061e11c2e64f65eea2d1 F src/vdbeaux.c 0e01d6fda149c689039caadb8c89b20abb58e21d
F src/vdbeblob.c 9542e116c1db5ed813977581d506c176e117c0ec F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50
F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
@@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c 7d9c988741c7d0e4a57774ae4b56e59675c4014a F src/where.c 7825dce3f92d7c7de9329505deefe176cbd5ba43
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 2914e4191121004a3f564b1fbf1c235dcc595503 P f29d194e03d6bcc78bf883b77e591dbccada02f0
R b009af851099e49da0fb1800028a0b8c R 3842d7f2fc20472907a26e6db9a0b24a
U drh U drh
Z ba859408f13b87421335d53499aa861e Z 8a746710251048df8d65813e18590ec6

View File

@@ -1 +1 @@
f29d194e03d6bcc78bf883b77e591dbccada02f0 ce184c7bb16988641d37c908d9b3042456d4be3d

View File

@@ -604,7 +604,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeUsesBtree(v, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);

View File

@@ -1077,6 +1077,7 @@ static void analyzeOneTable(
** **
*/ */
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto); addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto);
@@ -1098,6 +1099,7 @@ static void analyzeOneTable(
aGotoChng[i] = aGotoChng[i] =
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
VdbeCoverage(v);
} }
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng); sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto); aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);
@@ -1144,7 +1146,7 @@ static void analyzeOneTable(
sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp); sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 2+IsStat34); sqlite3VdbeChangeP5(v, 2+IsStat34);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
/* Add the entry to the stat1 table. */ /* Add the entry to the stat1 table. */
callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
@@ -1171,10 +1173,12 @@ static void analyzeOneTable(
addrNext = sqlite3VdbeCurrentAddr(v); addrNext = sqlite3VdbeCurrentAddr(v);
callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
VdbeCoverage(v);
callStatGet(v, regStat4, STAT_GET_NEQ, regEq); callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NLT, regLt);
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
VdbeCoverage(v);
#ifdef SQLITE_ENABLE_STAT3 #ifdef SQLITE_ENABLE_STAT3
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
pIdx->aiColumn[0], regSample); pIdx->aiColumn[0], regSample);
@@ -1205,7 +1209,7 @@ static void analyzeOneTable(
if( pOnlyIdx==0 && needTableCnt ){ if( pOnlyIdx==0 && needTableCnt ){
VdbeComment((v, "%s", pTab->zName)); VdbeComment((v, "%s", pTab->zName));
sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);

View File

@@ -948,7 +948,7 @@ void sqlite3StartTable(
reg3 = ++pParse->nMem; reg3 = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeUsesBtree(v, iDb);
j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
1 : SQLITE_MAX_FILE_FORMAT; 1 : SQLITE_MAX_FILE_FORMAT;
sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
@@ -2675,27 +2675,27 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
/* Open the table. Loop through all rows of the table, inserting index /* Open the table. Loop through all rows of the table, inserting index
** records into the sorter. */ ** records into the sorter. */
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
regRecord = sqlite3GetTempReg(pParse); regRecord = sqlite3GetTempReg(pParse);
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
sqlite3VdbeResolveLabel(v, iPartIdxLabel); sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
(char *)pKey, P4_KEYINFO); (char *)pKey, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
assert( pKey!=0 || db->mallocFailed || pParse->nErr ); assert( pKey!=0 || db->mallocFailed || pParse->nErr );
if( pIndex->onError!=OE_None && pKey!=0 ){ if( pIndex->onError!=OE_None && pKey!=0 ){
int j2 = sqlite3VdbeCurrentAddr(v) + 3; int j2 = sqlite3VdbeCurrentAddr(v) + 3;
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
addr2 = sqlite3VdbeCurrentAddr(v); addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
pKey->nField - pIndex->nKeyCol); pKey->nField - pIndex->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
}else{ }else{
addr2 = sqlite3VdbeCurrentAddr(v); addr2 = sqlite3VdbeCurrentAddr(v);
@@ -2704,7 +2704,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_Close, iTab); sqlite3VdbeAddOp1(v, OP_Close, iTab);

View File

@@ -481,13 +481,15 @@ void sqlite3DeleteFrom(
if( aToOpen[iDataCur-iTabCur] ){ if( aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 ); assert( pPk!=0 );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
VdbeCoverage(v);
} }
}else if( pPk ){ }else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
assert( nKey==0 ); /* OP_Found will use a composite key */ assert( nKey==0 ); /* OP_Found will use a composite key */
}else{ }else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
VdbeCoverage(v);
assert( nKey==1 ); assert( nKey==1 );
} }
@@ -511,7 +513,7 @@ void sqlite3DeleteFrom(
if( okOnePass ){ if( okOnePass ){
sqlite3VdbeResolveLabel(v, addrBypass); sqlite3VdbeResolveLabel(v, addrBypass);
}else if( pPk ){ }else if( pPk ){
sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop);
@@ -609,7 +611,10 @@ void sqlite3GenerateRowDelete(
** not attempt to delete it or fire any DELETE triggers. */ ** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v); iLabel = sqlite3VdbeMakeLabel(v);
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
if( !bNoSeek ) sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); if( !bNoSeek ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverage(v);
}
/* If there are any triggers to fire, allocate a range of registers to /* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */ ** use for the old.* references in the triggers. */
@@ -651,6 +656,7 @@ void sqlite3GenerateRowDelete(
*/ */
if( addrStart<sqlite3VdbeCurrentAddr(v) ){ if( addrStart<sqlite3VdbeCurrentAddr(v) ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverage(v);
} }
/* Do FK processing. This call checks that any FK constraints that /* Do FK processing. This call checks that any FK constraints that

View File

@@ -1383,7 +1383,7 @@ void sqlite3ExprCodeIsNullJump(
int iDest /* Jump here if the value is null */ int iDest /* Jump here if the value is null */
){ ){
if( sqlite3ExprCanBeNull(pExpr) ){ if( sqlite3ExprCanBeNull(pExpr) ){
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); VdbeCoverage(v);
} }
} }
@@ -1486,7 +1486,9 @@ static int isCandidateForInOpt(Select *p){
*/ */
int sqlite3CodeOnce(Parse *pParse){ int sqlite3CodeOnce(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); int addr = sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
VdbeCoverage(v);
return addr;
} }
/* /*
@@ -1837,6 +1839,7 @@ int sqlite3CodeSubselect(
if( isRowid ){ if( isRowid ){
sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{ }else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
@@ -1960,10 +1963,11 @@ static void sqlite3ExprCodeIN(
if( destIfNull==destIfFalse ){ if( destIfNull==destIfFalse ){
/* Shortcut for the common case where the false and NULL outcomes are /* Shortcut for the common case where the false and NULL outcomes are
** the same. */ ** the same. */
sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
}else{ }else{
int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
} }
@@ -1971,8 +1975,9 @@ static void sqlite3ExprCodeIN(
if( eType==IN_INDEX_ROWID ){ if( eType==IN_INDEX_ROWID ){
/* In this case, the RHS is the ROWID of table b-tree /* In this case, the RHS is the ROWID of table b-tree
*/ */
sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
VdbeCoverage(v);
}else{ }else{
/* In this case, the RHS is an index b-tree. /* In this case, the RHS is an index b-tree.
*/ */
@@ -1993,7 +1998,7 @@ static void sqlite3ExprCodeIN(
** for this particular IN operator. ** for this particular IN operator.
*/ */
sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
VdbeCoverage(v);
}else{ }else{
/* In this branch, the RHS of the IN might contain a NULL and /* In this branch, the RHS of the IN might contain a NULL and
** the presence of a NULL on the RHS makes a difference in the ** the presence of a NULL on the RHS makes a difference in the
@@ -2006,6 +2011,7 @@ static void sqlite3ExprCodeIN(
** over all of the code that follows. ** over all of the code that follows.
*/ */
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
VdbeCoverage(v);
/* Here we begin generating code that runs if the LHS is not /* Here we begin generating code that runs if the LHS is not
** contained within the RHS. Generate additional code that ** contained within the RHS. Generate additional code that
@@ -2013,8 +2019,9 @@ static void sqlite3ExprCodeIN(
** jump to destIfNull. If there are no NULLs in the RHS then ** jump to destIfNull. If there are no NULLs in the RHS then
** jump to destIfFalse. ** jump to destIfFalse.
*/ */
j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); VdbeCoverage(v);
j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
sqlite3VdbeJumpHere(v, j3); sqlite3VdbeJumpHere(v, j3);
sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
@@ -2023,7 +2030,7 @@ static void sqlite3ExprCodeIN(
/* Jump to the appropriate target depending on whether or not /* Jump to the appropriate target depending on whether or not
** the RHS contains a NULL ** the RHS contains a NULL
*/ */
sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
/* The OP_Found at the top of this branch jumps here when true, /* The OP_Found at the top of this branch jumps here when true,
@@ -2560,7 +2567,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2); r1, r2, inReg, SQLITE_STOREP2); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -2574,6 +2581,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
op = (op==TK_IS) ? TK_EQ : TK_NE; op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -2663,7 +2671,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3VdbeAddOp2(v, OP_Integer, 1, target); sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
testcase( regFree1==0 ); testcase( regFree1==0 );
addr = sqlite3VdbeAddOp1(v, op, r1); addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
break; break;
@@ -2715,6 +2723,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
for(i=1; i<nFarg; i++){ for(i=1; i<nFarg; i++){
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
VdbeCoverage(v);
sqlite3ExprCacheRemove(pParse, target, 1); sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse); sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
@@ -2853,12 +2862,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
r4 = sqlite3GetTempReg(pParse); r4 = sqlite3GetTempReg(pParse);
codeCompare(pParse, pLeft, pRight, OP_Ge, codeCompare(pParse, pLeft, pRight, OP_Ge,
r1, r2, r3, SQLITE_STOREP2); r1, r2, r3, SQLITE_STOREP2);
VdbeCoverage(v);
pLItem++; pLItem++;
pRight = pLItem->pExpr; pRight = pLItem->pExpr;
sqlite3ReleaseTempReg(pParse, regFree2); sqlite3ReleaseTempReg(pParse, regFree2);
r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
testcase( regFree2==0 ); testcase( regFree2==0 );
codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r3);
sqlite3ReleaseTempReg(pParse, r4); sqlite3ReleaseTempReg(pParse, r4);
@@ -3025,6 +3036,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( pExpr->affinity==OE_Ignore ){ if( pExpr->affinity==OE_Ignore ){
sqlite3VdbeAddOp4( sqlite3VdbeAddOp4(
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
VdbeCoverage(v);
}else{ }else{
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
pExpr->affinity, pExpr->u.zToken, 0, 0); pExpr->affinity, pExpr->u.zToken, 0, 0);
@@ -3613,7 +3625,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull); r1, r2, dest, jumpIfNull); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -3626,7 +3638,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE; op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ); r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -3638,7 +3650,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_ISNULL ); testcase( op==TK_ISNULL );
testcase( op==TK_NOTNULL ); testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
sqlite3VdbeAddOp2(v, op, r1, dest); sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
break; break;
} }
@@ -3665,6 +3677,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
}else{ }else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
} }
@@ -3766,7 +3779,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull); r1, r2, dest, jumpIfNull); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -3779,7 +3792,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ); r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( regFree2==0 ); testcase( regFree2==0 );
break; break;
@@ -3789,7 +3802,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_ISNULL ); testcase( op==TK_ISNULL );
testcase( op==TK_NOTNULL ); testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
sqlite3VdbeAddOp2(v, op, r1, dest); sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
break; break;
} }
@@ -3818,6 +3831,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
}else{ }else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
VdbeCoverage(v);
testcase( regFree1==0 ); testcase( regFree1==0 );
testcase( jumpIfNull==0 ); testcase( jumpIfNull==0 );
} }

View File

@@ -340,10 +340,11 @@ static void fkLookupParent(
** search for a matching row in the parent table. */ ** search for a matching row in the parent table. */
if( nIncr<0 ){ if( nIncr<0 ){
sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
VdbeCoverage(v);
} }
for(i=0; i<pFKey->nCol; i++){ for(i=0; i<pFKey->nCol; i++){
int iReg = aiCol[i] + regData + 1; int iReg = aiCol[i] + regData + 1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
} }
if( isIgnore==0 ){ if( isIgnore==0 ){
@@ -360,17 +361,18 @@ static void fkLookupParent(
** will have INTEGER affinity applied to it, which may not be correct. */ ** will have INTEGER affinity applied to it, which may not be correct. */
sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
VdbeCoverage(v);
/* If the parent table is the same as the child table, and we are about /* If the parent table is the same as the child table, and we are about
** to increment the constraint-counter (i.e. this is an INSERT operation), ** to increment the constraint-counter (i.e. this is an INSERT operation),
** then check if the row being inserted matches itself. If so, do not ** then check if the row being inserted matches itself. If so, do not
** increment the constraint-counter. */ ** increment the constraint-counter. */
if( pTab==pFKey->pFrom && nIncr==1 ){ if( pTab==pFKey->pFrom && nIncr==1 ){
sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v);
} }
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
sqlite3VdbeJumpHere(v, iMustBeInt); sqlite3VdbeJumpHere(v, iMustBeInt);
@@ -406,7 +408,7 @@ static void fkLookupParent(
/* The parent key is a composite key that includes the IPK column */ /* The parent key is a composite key that includes the IPK column */
iParent = regData; iParent = regData;
} }
sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
} }
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
@@ -414,7 +416,7 @@ static void fkLookupParent(
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
sqlite3IndexAffinityStr(v,pIdx), nCol); sqlite3IndexAffinityStr(v,pIdx), nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol); sqlite3ReleaseTempRange(pParse, regTemp, nCol);
@@ -552,6 +554,7 @@ static void fkScanChildren(
if( nIncr<0 ){ if( nIncr<0 ){
iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
VdbeCoverage(v);
} }
/* Create an Expr object representing an SQL expression like: /* Create an Expr object representing an SQL expression like:
@@ -714,7 +717,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
} }
if( !p ) return; if( !p ) return;
iSkip = sqlite3VdbeMakeLabel(v); iSkip = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
} }
pParse->disableTriggers = 1; pParse->disableTriggers = 1;
@@ -732,6 +735,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
*/ */
if( (db->flags & SQLITE_DeferFKs)==0 ){ if( (db->flags & SQLITE_DeferFKs)==0 ){
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
OE_Abort, 0, P4_STATIC, P5_ConstraintFK); OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
} }
@@ -891,7 +895,7 @@ void sqlite3FkCheck(
int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
for(i=0; i<pFKey->nCol; i++){ for(i=0; i<pFKey->nCol; i++){
int iReg = pFKey->aCol[i].iFrom + regOld + 1; int iReg = pFKey->aCol[i].iFrom + regOld + 1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
} }
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
} }

View File

@@ -262,14 +262,14 @@ void sqlite3AutoincrementBegin(Parse *pParse){
sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
addr = sqlite3VdbeCurrentAddr(v); addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9);
sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); sqlite3VdbeAddOp2(v, OP_Integer, 0, memId);
sqlite3VdbeAddOp0(v, OP_Close); sqlite3VdbeAddOp0(v, OP_Close);
} }
@@ -311,11 +311,11 @@ void sqlite3AutoincrementEnd(Parse *pParse){
iRec = sqlite3GetTempReg(pParse); iRec = sqlite3GetTempReg(pParse);
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
j2 = sqlite3VdbeAddOp0(v, OP_Rewind); j2 = sqlite3VdbeAddOp0(v, OP_Rewind); VdbeCoverage(v);
j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec);
j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Next, 0, j3); sqlite3VdbeAddOp2(v, OP_Next, 0, j3); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j2);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
j5 = sqlite3VdbeAddOp0(v, OP_Goto); j5 = sqlite3VdbeAddOp0(v, OP_Goto);
@@ -692,7 +692,7 @@ void sqlite3Insert(
regRec = sqlite3GetTempReg(pParse); regRec = sqlite3GetTempReg(pParse);
regTempRowid = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
@@ -777,7 +777,7 @@ void sqlite3Insert(
** end loop ** end loop
** D: ... ** D: ...
*/ */
addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v);
addrCont = sqlite3VdbeCurrentAddr(v); addrCont = sqlite3VdbeCurrentAddr(v);
}else if( pSelect ){ }else if( pSelect ){
/* This block codes the top of loop only. The complete loop is the /* This block codes the top of loop only. The complete loop is the
@@ -789,6 +789,7 @@ void sqlite3Insert(
** D: ... ** D: ...
*/ */
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
} }
/* Run the BEFORE and INSTEAD OF triggers, if there are any /* Run the BEFORE and INSTEAD OF triggers, if there are any
@@ -814,10 +815,10 @@ void sqlite3Insert(
assert( pSelect==0 ); /* Otherwise useTempTable is true */ assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols);
} }
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
} }
/* Cannot have triggers on a virtual table. If it were possible, /* Cannot have triggers on a virtual table. If it were possible,
@@ -892,14 +893,14 @@ void sqlite3Insert(
if( !appendFlag ){ if( !appendFlag ){
int j1; int j1;
if( !IsVirtual(pTab) ){ if( !IsVirtual(pTab) ){
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
}else{ }else{
j1 = sqlite3VdbeCurrentAddr(v); j1 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v);
} }
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
} }
}else if( IsVirtual(pTab) || withoutRowid ){ }else if( IsVirtual(pTab) || withoutRowid ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
@@ -990,7 +991,7 @@ void sqlite3Insert(
*/ */
sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeResolveLabel(v, endOfLoop);
if( useTempTable ){ if( useTempTable ){
sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeJumpHere(v, addrInsTop);
sqlite3VdbeAddOp1(v, OP_Close, srcTab); sqlite3VdbeAddOp1(v, OP_Close, srcTab);
}else if( pSelect ){ }else if( pSelect ){
@@ -1212,15 +1213,17 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
regNewData+1+i, zMsg, P4_DYNAMIC); regNewData+1+i, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
break; break;
} }
case OE_Ignore: { case OE_Ignore: {
sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
VdbeCoverage(v);
break; break;
} }
default: { default: {
assert( onError==OE_Replace ); assert( onError==OE_Replace );
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v);
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
break; break;
@@ -1272,6 +1275,7 @@ void sqlite3GenerateConstraintChecks(
** it might have changed. Skip the conflict logic below if the rowid ** it might have changed. Skip the conflict logic below if the rowid
** is unchanged. */ ** is unchanged. */
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
VdbeCoverage(v);
} }
/* If the response to a rowid conflict is REPLACE but the response /* If the response to a rowid conflict is REPLACE but the response
@@ -1291,6 +1295,7 @@ void sqlite3GenerateConstraintChecks(
/* Check to see if the new rowid already exists in the table. Skip /* Check to see if the new rowid already exists in the table. Skip
** the following conflict logic if it does not. */ ** the following conflict logic if it does not. */
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
VdbeCoverage(v);
/* Generate code that deals with a rowid collision */ /* Generate code that deals with a rowid collision */
switch( onError ){ switch( onError ){
@@ -1430,7 +1435,7 @@ void sqlite3GenerateConstraintChecks(
/* Check to see if the new index entry will be unique */ /* Check to see if the new index entry will be unique */
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */ /* Generate code to handle collisions */
regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
@@ -1441,6 +1446,7 @@ void sqlite3GenerateConstraintChecks(
** is different from old-rowid */ ** is different from old-rowid */
if( isUpdate ){ if( isUpdate ){
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
VdbeCoverage(v);
} }
}else{ }else{
int x; int x;
@@ -1475,7 +1481,7 @@ void sqlite3GenerateConstraintChecks(
} }
sqlite3VdbeAddOp4(v, op, sqlite3VdbeAddOp4(v, op,
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
); ); VdbeCoverage(v);
} }
} }
} }
@@ -1557,6 +1563,7 @@ void sqlite3CompleteInsertion(
bAffinityDone = 1; bAffinityDone = 1;
if( pIdx->pPartIdxWhere ){ if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
} }
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
pik_flags = 0; pik_flags = 0;
@@ -1940,16 +1947,17 @@ static int xferOptimization(
** **
** (3) onError is something other than OE_Abort and OE_Rollback. ** (3) onError is something other than OE_Abort and OE_Rollback.
*/ */
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v);
emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
} }
if( HasRowid(pSrc) ){ if( HasRowid(pSrc) ){
sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){ if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, onError, pDest); sqlite3RowidConstraint(pParse, onError, pDest);
sqlite3VdbeJumpHere(v, addr2); sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, regAutoinc, regRowid); autoIncStep(pParse, regAutoinc, regRowid);
@@ -1963,7 +1971,7 @@ static int xferOptimization(
sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
}else{ }else{
@@ -1982,10 +1990,10 @@ static int xferOptimization(
sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName)); VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);

View File

@@ -3307,6 +3307,21 @@ int sqlite3_test_control(int op, ...){
break; break;
} }
/* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr);
**
** Set the VDBE coverage callback function to xCallback with context
** pointer ptr.
*/
case SQLITE_TESTCTRL_VDBE_COVERAGE: {
#ifdef SQLITE_VDBE_COVERAGE
typedef void (*branch_callback)(void*,int,u8,u8);
sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
#endif
break;
}
} }
va_end(ap); va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */ #endif /* SQLITE_OMIT_BUILTIN_TEST */

View File

@@ -824,6 +824,7 @@ void sqlite3Pragma(
** size of historical compatibility. ** size of historical compatibility.
*/ */
case PragTyp_DEFAULT_CACHE_SIZE: { case PragTyp_DEFAULT_CACHE_SIZE: {
static const int iLn = __LINE__+2;
static const VdbeOpList getCacheSize[] = { static const VdbeOpList getCacheSize[] = {
{ OP_Transaction, 0, 0, 0}, /* 0 */ { OP_Transaction, 0, 0, 0}, /* 0 */
{ OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
@@ -841,7 +842,7 @@ void sqlite3Pragma(
sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
pParse->nMem += 2; pParse->nMem += 2;
addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn);
sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb);
sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
@@ -1086,6 +1087,7 @@ void sqlite3Pragma(
** file. Before writing to meta[6], check that meta[3] indicates ** file. Before writing to meta[6], check that meta[3] indicates
** that this really is an auto-vacuum capable database. ** that this really is an auto-vacuum capable database.
*/ */
static const int iLn = __LINE__+2;
static const VdbeOpList setMeta6[] = { static const VdbeOpList setMeta6[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */ { OP_Transaction, 0, 1, 0}, /* 0 */
{ OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
@@ -1095,7 +1097,7 @@ void sqlite3Pragma(
{ OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
}; };
int iAddr; int iAddr;
iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr, iDb);
sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb);
sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
@@ -1121,10 +1123,10 @@ void sqlite3Pragma(
} }
sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_ResultRow, 1); sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
break; break;
} }
@@ -1695,7 +1697,7 @@ void sqlite3Pragma(
assert( pParse->nErr>0 || pFK==0 ); assert( pParse->nErr>0 || pFK==0 );
if( pFK ) break; if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i; if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb); pParent = sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0; pIdx = 0;
@@ -1711,25 +1713,26 @@ void sqlite3Pragma(
if( iKey!=pTab->iPKey ){ if( iKey!=pTab->iPKey ){
sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
sqlite3ColumnDefault(v, pTab, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
} }
sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
}else{ }else{
for(j=0; j<pFK->nCol; j++){ for(j=0; j<pFK->nCol; j++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
} }
if( pParent ){ if( pParent ){
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3IndexAffinityStr(v,pIdx), pFK->nCol);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
VdbeCoverage(v);
} }
} }
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
@@ -1740,7 +1743,7 @@ void sqlite3Pragma(
sqlite3VdbeResolveLabel(v, addrOk); sqlite3VdbeResolveLabel(v, addrOk);
sqlite3DbFree(db, aiCols); sqlite3DbFree(db, aiCols);
} }
sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrTop); sqlite3VdbeJumpHere(v, addrTop);
} }
} }
@@ -1787,6 +1790,7 @@ void sqlite3Pragma(
** messages have been generated, output OK. Otherwise output the ** messages have been generated, output OK. Otherwise output the
** error message ** error message
*/ */
static const int iLn = __LINE__+2;
static const VdbeOpList endCode[] = { static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */ { OP_AddImm, 1, 0, 0}, /* 0 */
{ OP_IfNeg, 1, 0, 0}, /* 1 */ { OP_IfNeg, 1, 0, 0}, /* 1 */
@@ -1835,6 +1839,7 @@ void sqlite3Pragma(
sqlite3CodeVerifySchema(pParse, i); sqlite3CodeVerifySchema(pParse, i);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
@@ -1866,7 +1871,7 @@ void sqlite3Pragma(
/* Do the b-tree integrity checks */ /* Do the b-tree integrity checks */
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
sqlite3VdbeChangeP5(v, (u8)i); sqlite3VdbeChangeP5(v, (u8)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC); P4_DYNAMIC);
@@ -1888,6 +1893,7 @@ void sqlite3Pragma(
if( pTab->pIndex==0 ) continue; if( pTab->pIndex==0 ) continue;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
@@ -1898,7 +1904,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
} }
pParse->nMem = MAX(pParse->nMem, 8+j); pParse->nMem = MAX(pParse->nMem, 8+j);
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4; int jmp2, jmp3, jmp4;
@@ -1908,7 +1914,7 @@ void sqlite3Pragma(
pPrior = pIdx; pPrior = pIdx;
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1, jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1,
pIdx->nColumn); pIdx->nColumn); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
@@ -1918,13 +1924,13 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeAddOp0(v, OP_Halt);
sqlite3VdbeJumpHere(v, jmp4); sqlite3VdbeJumpHere(v, jmp4);
sqlite3VdbeJumpHere(v, jmp2); sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeResolveLabel(v, jmp3); sqlite3VdbeResolveLabel(v, jmp3);
} }
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1); sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT #ifndef SQLITE_OMIT_BTREECOUNT
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0,
@@ -1932,10 +1938,10 @@ void sqlite3Pragma(
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pPk==pIdx ) continue; if( pPk==pIdx ) continue;
addr = sqlite3VdbeCurrentAddr(v); addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT);
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
@@ -1944,7 +1950,7 @@ void sqlite3Pragma(
#endif /* SQLITE_OMIT_BTREECOUNT */ #endif /* SQLITE_OMIT_BTREECOUNT */
} }
} }
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
sqlite3VdbeChangeP2(v, addr, -mxErr); sqlite3VdbeChangeP2(v, addr, -mxErr);
sqlite3VdbeJumpHere(v, addr+1); sqlite3VdbeJumpHere(v, addr+1);
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
@@ -2082,7 +2088,7 @@ void sqlite3Pragma(
{ OP_Integer, 0, 1, 0}, /* 1 */ { OP_Integer, 0, 1, 0}, /* 1 */
{ OP_SetCookie, 0, 0, 1}, /* 2 */ { OP_SetCookie, 0, 0, 1}, /* 2 */
}; };
int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight));
sqlite3VdbeChangeP1(v, addr+2, iDb); sqlite3VdbeChangeP1(v, addr+2, iDb);
@@ -2094,7 +2100,7 @@ void sqlite3Pragma(
{ OP_ReadCookie, 0, 1, 0}, /* 1 */ { OP_ReadCookie, 0, 1, 0}, /* 1 */
{ OP_ResultRow, 1, 1, 0} { OP_ResultRow, 1, 1, 0}
}; };
int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0);
sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb);
sqlite3VdbeChangeP3(v, addr+1, iCookie); sqlite3VdbeChangeP3(v, addr+1, iCookie);

View File

@@ -455,7 +455,7 @@ static void pushOntoSorter(
}else{ }else{
iLimit = pSelect->iLimit; iLimit = pSelect->iLimit;
} }
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
addr2 = sqlite3VdbeAddOp0(v, OP_Goto); addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
@@ -476,7 +476,7 @@ static void codeOffset(
if( iOffset>0 && iContinue!=0 ){ if( iOffset>0 && iContinue!=0 ){
int addr; int addr;
sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1); sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
VdbeComment((v, "skip OFFSET records")); VdbeComment((v, "skip OFFSET records"));
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
@@ -504,7 +504,7 @@ static void codeDistinct(
v = pParse->pVdbe; v = pParse->pVdbe;
r1 = sqlite3GetTempReg(pParse); r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
@@ -644,8 +644,10 @@ static void selectInnerLoop(
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
if( i<nResultCol-1 ){ if( i<nResultCol-1 ){
sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i); sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
VdbeCoverage(v);
}else{ }else{
sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i); sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
VdbeCoverage(v);
} }
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
@@ -712,7 +714,7 @@ static void selectInnerLoop(
** current row to the index and proceed with writing it to the ** current row to the index and proceed with writing it to the
** output table as well. */ ** output table as well. */
int addr = sqlite3VdbeCurrentAddr(v) + 4; int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
assert( pOrderBy==0 ); assert( pOrderBy==0 );
} }
@@ -823,6 +825,7 @@ static void selectInnerLoop(
** added to the queue. Only add this new value if it has never before ** added to the queue. Only add this new value if it has never before
** been added */ ** been added */
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0); addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
} }
@@ -861,7 +864,7 @@ static void selectInnerLoop(
** the output for us. ** the output for us.
*/ */
if( pOrderBy==0 && p->iLimit ){ if( pOrderBy==0 && p->iLimit ){
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
} }
} }
@@ -1080,12 +1083,13 @@ static void generateSortTail(
int ptab2 = pParse->nTab++; int ptab2 = pParse->nTab++;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue); codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow); sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
}else{ }else{
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue); codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
} }
@@ -1143,9 +1147,9 @@ static void generateSortTail(
*/ */
sqlite3VdbeResolveLabel(v, addrContinue); sqlite3VdbeResolveLabel(v, addrContinue);
if( p->selFlags & SF_UseSorter ){ if( p->selFlags & SF_UseSorter ){
sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
} }
sqlite3VdbeResolveLabel(v, addrBreak); sqlite3VdbeResolveLabel(v, addrBreak);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){ if( eDest==SRT_Output || eDest==SRT_Coroutine ){
@@ -1693,22 +1697,22 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
} }
}else{ }else{
sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3ExprCode(pParse, p->pLimit, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
VdbeComment((v, "LIMIT counter")); VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
} }
if( p->pOffset ){ if( p->pOffset ){
p->iOffset = iOffset = ++pParse->nMem; p->iOffset = iOffset = ++pParse->nMem;
pParse->nMem++; /* Allocate an extra register for limit+offset */ pParse->nMem++; /* Allocate an extra register for limit+offset */
sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3ExprCode(pParse, p->pOffset, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter")); VdbeComment((v, "OFFSET counter"));
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
VdbeComment((v, "LIMIT+OFFSET")); VdbeComment((v, "LIMIT+OFFSET"));
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeJumpHere(v, addr1);
} }
@@ -1897,7 +1901,7 @@ static void generateWithRecursiveQuery(
if( rc ) goto end_of_recursive_query; if( rc ) goto end_of_recursive_query;
/* Find the next row in the Queue and output that row */ /* Find the next row in the Queue and output that row */
addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);
/* Transfer the next row in Queue over to Current */ /* Transfer the next row in Queue over to Current */
sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */ sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */
@@ -1913,7 +1917,10 @@ static void generateWithRecursiveQuery(
codeOffset(v, regOffset, addrCont); codeOffset(v, regOffset, addrCont);
selectInnerLoop(pParse, p, p->pEList, iCurrent, selectInnerLoop(pParse, p, p->pEList, iCurrent,
0, 0, pDest, addrCont, addrBreak); 0, 0, pDest, addrCont, addrBreak);
if( regLimit ) sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); if( regLimit ){
sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
VdbeCoverage(v);
}
sqlite3VdbeResolveLabel(v, addrCont); sqlite3VdbeResolveLabel(v, addrCont);
/* Execute the recursive SELECT taking the single row in Current as /* Execute the recursive SELECT taking the single row in Current as
@@ -2073,7 +2080,7 @@ static int multiSelect(
p->iLimit = pPrior->iLimit; p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset; p->iOffset = pPrior->iOffset;
if( p->iLimit ){ if( p->iLimit ){
addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
VdbeComment((v, "Jump ahead if LIMIT reached")); VdbeComment((v, "Jump ahead if LIMIT reached"));
} }
explainSetInteger(iSub2, pParse->iNextSelectId); explainSetInteger(iSub2, pParse->iNextSelectId);
@@ -2180,12 +2187,12 @@ static int multiSelect(
iBreak = sqlite3VdbeMakeLabel(v); iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak); computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
iStart = sqlite3VdbeCurrentAddr(v); iStart = sqlite3VdbeCurrentAddr(v);
selectInnerLoop(pParse, p, p->pEList, unionTab, selectInnerLoop(pParse, p, p->pEList, unionTab,
0, 0, &dest, iCont, iBreak); 0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
} }
@@ -2255,15 +2262,15 @@ static int multiSelect(
iBreak = sqlite3VdbeMakeLabel(v); iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak); computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse); r1 = sqlite3GetTempReg(pParse);
iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
selectInnerLoop(pParse, p, p->pEList, tab1, selectInnerLoop(pParse, p, p->pEList, tab1,
0, 0, &dest, iCont, iBreak); 0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
@@ -2370,10 +2377,10 @@ static int generateOutputSubroutine(
*/ */
if( regPrev ){ if( regPrev ){
int j1, j2; int j1, j2;
j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
@@ -2474,7 +2481,7 @@ static int generateOutputSubroutine(
/* Jump to the end of the loop if the LIMIT is reached. /* Jump to the end of the loop if the LIMIT is reached.
*/ */
if( p->iLimit ){ if( p->iLimit ){
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
} }
/* Generate the subroutine return /* Generate the subroutine return
@@ -2790,6 +2797,7 @@ static int multiSelectOrderBy(
VdbeNoopComment((v, "eof-A subroutine")); VdbeNoopComment((v, "eof-A subroutine"));
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
p->nSelectRow += pPrior->nSelectRow; p->nSelectRow += pPrior->nSelectRow;
} }
@@ -2803,7 +2811,7 @@ static int multiSelectOrderBy(
}else{ }else{
VdbeNoopComment((v, "eof-B subroutine")); VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
} }
@@ -2811,7 +2819,7 @@ static int multiSelectOrderBy(
*/ */
VdbeNoopComment((v, "A-lt-B subroutine")); VdbeNoopComment((v, "A-lt-B subroutine"));
addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
/* Generate code to handle the case of A==B /* Generate code to handle the case of A==B
@@ -2824,7 +2832,7 @@ static int multiSelectOrderBy(
}else{ }else{
VdbeNoopComment((v, "A-eq-B subroutine")); VdbeNoopComment((v, "A-eq-B subroutine"));
addrAeqB = addrAeqB =
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
} }
@@ -2835,14 +2843,14 @@ static int multiSelectOrderBy(
if( op==TK_ALL || op==TK_UNION ){ if( op==TK_ALL || op==TK_UNION ){
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
} }
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
/* This code runs once to initialize everything. /* This code runs once to initialize everything.
*/ */
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
/* Implement the main merge loop /* Implement the main merge loop
*/ */
@@ -2851,7 +2859,7 @@ static int multiSelectOrderBy(
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
(char*)pKeyMerge, P4_KEYINFO); (char*)pKeyMerge, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
/* Jump to the this point in order to terminate the query. /* Jump to the this point in order to terminate the query.
*/ */
@@ -4391,7 +4399,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
** values to an OP_Copy. ** values to an OP_Copy.
*/ */
if( regHit ){ if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
} }
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
@@ -4925,7 +4933,7 @@ int sqlite3Select(
sortOut = sqlite3GetTempReg(pParse); sortOut = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1; sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
} }
@@ -4952,7 +4960,7 @@ int sqlite3Select(
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
j1 = sqlite3VdbeCurrentAddr(v); j1 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v);
/* Generate code that runs whenever the GROUP BY changes. /* Generate code that runs whenever the GROUP BY changes.
** Changes in the GROUP BY are detected by the previous code ** Changes in the GROUP BY are detected by the previous code
@@ -4966,7 +4974,7 @@ int sqlite3Select(
sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output one row")); VdbeComment((v, "output one row"));
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
VdbeComment((v, "check abort flag")); VdbeComment((v, "check abort flag"));
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
VdbeComment((v, "reset accumulator")); VdbeComment((v, "reset accumulator"));
@@ -4983,6 +4991,7 @@ int sqlite3Select(
*/ */
if( groupBySort ){ if( groupBySort ){
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
VdbeCoverage(v);
}else{ }else{
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx); sqlite3VdbeChangeToNoop(v, addrSortingIdx);
@@ -5010,7 +5019,7 @@ int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
sqlite3VdbeResolveLabel(v, addrOutputRow); sqlite3VdbeResolveLabel(v, addrOutputRow);
addrOutputRow = sqlite3VdbeCurrentAddr(v); addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
VdbeComment((v, "Groupby result generator entry point")); VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo); finalizeAggFunctions(pParse, &sAggInfo);

View File

@@ -6117,7 +6117,8 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_LAST 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_LAST 21
/* /*
** CAPI3REF: SQLite Runtime Status ** CAPI3REF: SQLite Runtime Status

View File

@@ -2657,6 +2657,13 @@ struct Sqlite3Config {
void(*xSqllog)(void*,sqlite3*,const char*, int); void(*xSqllog)(void*,sqlite3*,const char*, int);
void *pSqllogArg; void *pSqllogArg;
#endif #endif
#ifdef SQLITE_VDBE_COVERAGE
/* The following callback (if not NULL) is invoked on every VDBE branch
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
*/
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
}; };
/* /*

View File

@@ -566,6 +566,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
assert( pTable!=0 ); assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){ if( (v = sqlite3GetVdbe(pParse))!=0 ){
int base; int base;
static const int iLn = __LINE__+2;
static const VdbeOpList dropTrigger[] = { static const VdbeOpList dropTrigger[] = {
{ OP_Rewind, 0, ADDR(9), 0}, { OP_Rewind, 0, ADDR(9), 0},
{ OP_String8, 0, 1, 0}, /* 1 */ { OP_String8, 0, 1, 0}, /* 1 */
@@ -580,7 +581,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3OpenMasterTable(pParse, iDb); sqlite3OpenMasterTable(pParse, iDb);
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn);
sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT); sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
sqlite3ChangeCookie(pParse, iDb); sqlite3ChangeCookie(pParse, iDb);

View File

@@ -434,18 +434,23 @@ void sqlite3Update(
if( aToOpen[iDataCur-iBaseCur] ){ if( aToOpen[iDataCur-iBaseCur] ){
assert( pPk!=0 ); assert( pPk!=0 );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
VdbeCoverage(v);
} }
labelContinue = labelBreak; labelContinue = labelBreak;
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverage(v);
}else if( pPk ){ }else if( pPk ){
labelContinue = sqlite3VdbeMakeLabel(v); labelContinue = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
VdbeCoverage(v);
}else{ }else{
labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak,
regOldRowid); regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
} }
/* If the record number will change, set register regNewRowid to /* If the record number will change, set register regNewRowid to
@@ -455,7 +460,7 @@ void sqlite3Update(
assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
if( chngRowid ){ if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
} }
/* Compute the old pre-UPDATE content of the row being changed, if that /* Compute the old pre-UPDATE content of the row being changed, if that
@@ -536,8 +541,10 @@ void sqlite3Update(
*/ */
if( pPk ){ if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
VdbeCoverage(v);
}else{ }else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
} }
/* If it did not delete it, the row-trigger may still have modified /* If it did not delete it, the row-trigger may still have modified
@@ -570,8 +577,10 @@ void sqlite3Update(
if( bReplace || chngKey ){ if( bReplace || chngKey ){
if( pPk ){ if( pPk ){
j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
VdbeCoverage(v);
}else{ }else{
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
VdbeCoverage(v);
} }
} }
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
@@ -616,7 +625,7 @@ void sqlite3Update(
/* Nothing to do at end-of-loop for a single-pass */ /* Nothing to do at end-of-loop for a single-pass */
}else if( pPk ){ }else if( pPk ){
sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue);
} }
@@ -745,7 +754,7 @@ static void updateVirtualTable(
/* Generate code to scan the ephemeral table and call VUpdate. */ /* Generate code to scan the ephemeral table and call VUpdate. */
iReg = ++pParse->nMem; iReg = ++pParse->nMem;
pParse->nMem += pTab->nCol+1; pParse->nMem += pTab->nCol+1;
addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg);
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
for(i=0; i<pTab->nCol; i++){ for(i=0; i<pTab->nCol; i++){
@@ -755,7 +764,7 @@ static void updateVirtualTable(
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
sqlite3MayAbort(pParse); sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);

View File

@@ -107,6 +107,18 @@ int sqlite3_found_count = 0;
# define UPDATE_MAX_BLOBSIZE(P) # define UPDATE_MAX_BLOBSIZE(P)
#endif #endif
/*
** Invoke the VDBE coverage callback, if defined
*/
#if !defined(SQLITE_VDBE_COVERAGE)
# define VdbeBranchTaken(I,M)
#else
# define VdbeBranchTaken(I,M) \
if( sqlite3GlobalConfig.xVdbeBranch!=0 ){ \
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, \
pOp->iSrcLine,(I),(M)); }
#endif
/* /*
** Convert the given register into a string if it isn't one ** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails. ** already. Return non-zero if a malloc() fails.
@@ -1638,6 +1650,7 @@ case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Int)==0 ){ if( (pIn1->flags & MEM_Int)==0 ){
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
if( (pIn1->flags & MEM_Int)==0 ){ if( (pIn1->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){ if( pOp->p2==0 ){
rc = SQLITE_MISMATCH; rc = SQLITE_MISMATCH;
@@ -1891,12 +1904,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** then the result is always NULL. ** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/ */
if( pOp->p5 & SQLITE_JUMPIFNULL ){ if( pOp->p5 & SQLITE_STOREP2 ){
pc = pOp->p2-1;
}else if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2]; pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Null); MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
}else{
VdbeBranchTaken((pOp->p5 & SQLITE_JUMPIFNULL)?2:3,4);
if( pOp->p5 & SQLITE_JUMPIFNULL ){
pc = pOp->p2-1;
}
} }
break; break;
} }
@@ -1929,10 +1945,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
MemSetTypeFlag(pOut, MEM_Int); MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = res; pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
}else if( res ){ }else{
VdbeBranchTaken(res!=0, 4);
if( res ){
pc = pOp->p2-1; pc = pOp->p2-1;
} }
}
/* Undo any changes made by applyAffinity() to the input registers. */ /* Undo any changes made by applyAffinity() to the input registers. */
pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
@@ -2029,11 +2047,11 @@ case OP_Compare: {
*/ */
case OP_Jump: { /* jump */ case OP_Jump: { /* jump */
if( iCompare<0 ){ if( iCompare<0 ){
pc = pOp->p1 - 1; pc = pOp->p1 - 1; VdbeBranchTaken(0,3);
}else if( iCompare==0 ){ }else if( iCompare==0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1; VdbeBranchTaken(1,3);
}else{ }else{
pc = pOp->p3 - 1; pc = pOp->p3 - 1; VdbeBranchTaken(2,3);
} }
break; break;
} }
@@ -2137,6 +2155,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
*/ */
case OP_Once: { /* jump */ case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag ); assert( pOp->p1<p->nOnceFlag );
VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
if( p->aOnceFlag[pOp->p1] ){ if( p->aOnceFlag[pOp->p1] ){
pc = pOp->p2-1; pc = pOp->p2-1;
}else{ }else{
@@ -2171,6 +2190,7 @@ case OP_IfNot: { /* jump, in1 */
#endif #endif
if( pOp->opcode==OP_IfNot ) c = !c; if( pOp->opcode==OP_IfNot ) c = !c;
} }
VdbeBranchTaken(c!=0, 2);
if( c ){ if( c ){
pc = pOp->p2-1; pc = pOp->p2-1;
} }
@@ -2184,6 +2204,7 @@ case OP_IfNot: { /* jump, in1 */
*/ */
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){ if( (pIn1->flags & MEM_Null)!=0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -2197,6 +2218,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
*/ */
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
if( (pIn1->flags & MEM_Null)==0 ){ if( (pIn1->flags & MEM_Null)==0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -3474,7 +3496,7 @@ case OP_SeekGT: { /* jump, in3 */
if( (pIn3->flags & MEM_Real)==0 ){ if( (pIn3->flags & MEM_Real)==0 ){
/* If the P3 value cannot be converted into any kind of a number, /* If the P3 value cannot be converted into any kind of a number,
** then the seek is not possible, so jump to P2 */ ** then the seek is not possible, so jump to P2 */
pc = pOp->p2 - 1; pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
break; break;
} }
@@ -3569,6 +3591,7 @@ case OP_SeekGT: { /* jump, in3 */
} }
} }
assert( pOp->p2>0 ); assert( pOp->p2>0 );
VdbeBranchTaken(res!=0,2);
if( res ){ if( res ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -3702,7 +3725,7 @@ case OP_Found: { /* jump, in3 */
** conflict */ ** conflict */
for(ii=0; ii<r.nField; ii++){ for(ii=0; ii<r.nField; ii++){
if( r.aMem[ii].flags & MEM_Null ){ if( r.aMem[ii].flags & MEM_Null ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
break; break;
} }
} }
@@ -3720,8 +3743,10 @@ case OP_Found: { /* jump, in3 */
pC->deferredMoveto = 0; pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;
if( pOp->opcode==OP_Found ){ if( pOp->opcode==OP_Found ){
VdbeBranchTaken(alreadyExists!=0,2);
if( alreadyExists ) pc = pOp->p2 - 1; if( alreadyExists ) pc = pOp->p2 - 1;
}else{ }else{
VdbeBranchTaken(alreadyExists==0,2);
if( !alreadyExists ) pc = pOp->p2 - 1; if( !alreadyExists ) pc = pOp->p2 - 1;
} }
break; break;
@@ -3764,6 +3789,7 @@ case OP_NotExists: { /* jump, in3 */
pC->nullRow = 0; pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;
pC->deferredMoveto = 0; pC->deferredMoveto = 0;
VdbeBranchTaken(res!=0,2);
if( res!=0 ){ if( res!=0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
assert( pC->rowidIsValid==0 ); assert( pC->rowidIsValid==0 );
@@ -4138,6 +4164,7 @@ case OP_SorterCompare: {
pIn3 = &aMem[pOp->p3]; pIn3 = &aMem[pOp->p3];
nIgnore = pOp->p4.i; nIgnore = pOp->p4.i;
rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res); rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
VdbeBranchTaken(res!=0,2);
if( res ){ if( res ){
pc = pOp->p2-1; pc = pOp->p2-1;
} }
@@ -4337,8 +4364,9 @@ case OP_Last: { /* jump */
pC->deferredMoveto = 0; pC->deferredMoveto = 0;
pC->rowidIsValid = 0; pC->rowidIsValid = 0;
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;
if( pOp->p2>0 && res ){ if( pOp->p2>0 ){
pc = pOp->p2 - 1; VdbeBranchTaken(res!=0,2);
if( res ) pc = pOp->p2 - 1;
} }
break; break;
} }
@@ -4395,6 +4423,7 @@ case OP_Rewind: { /* jump */
} }
pC->nullRow = (u8)res; pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp ); assert( pOp->p2>0 && pOp->p2<p->nOp );
VdbeBranchTaken(res!=0,2);
if( res ){ if( res ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -4485,6 +4514,7 @@ case OP_Next: /* jump */
rc = pOp->p4.xAdvance(pC->pCursor, &res); rc = pOp->p4.xAdvance(pC->pCursor, &res);
next_tail: next_tail:
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;
VdbeBranchTaken(res==0,2);
if( res==0 ){ if( res==0 ){
pC->nullRow = 0; pC->nullRow = 0;
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
@@ -4710,6 +4740,7 @@ case OP_IdxGE: { /* jump */
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
res++; res++;
} }
VdbeBranchTaken(res>0,2);
if( res>0 ){ if( res>0 ){
pc = pOp->p2 - 1 ; pc = pOp->p2 - 1 ;
} }
@@ -5071,9 +5102,11 @@ case OP_RowSetRead: { /* jump, in1, out3 */
/* The boolean index is empty */ /* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1); sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
VdbeBranchTaken(1,2);
}else{ }else{
/* A value was pulled from the index */ /* A value was pulled from the index */
sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
VdbeBranchTaken(0,2);
} }
goto check_for_interrupt; goto check_for_interrupt;
} }
@@ -5125,6 +5158,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
exists = sqlite3RowSetTest(pIn1->u.pRowSet, exists = sqlite3RowSetTest(pIn1->u.pRowSet,
(u8)(iSet>=0 ? iSet & 0xf : 0xff), (u8)(iSet>=0 ? iSet & 0xf : 0xff),
pIn3->u.i); pIn3->u.i);
VdbeBranchTaken(exists!=0,2);
if( exists ){ if( exists ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
break; break;
@@ -5317,8 +5351,10 @@ case OP_FkCounter: {
*/ */
case OP_FkIfZero: { /* jump */ case OP_FkIfZero: { /* jump */
if( pOp->p1 ){ if( pOp->p1 ){
VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2);
if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}else{ }else{
VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2);
if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
} }
break; break;
@@ -5367,6 +5403,7 @@ case OP_MemMax: { /* in2 */
case OP_IfPos: { /* jump, in1 */ case OP_IfPos: { /* jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int ); assert( pIn1->flags&MEM_Int );
VdbeBranchTaken( pIn1->u.i>0, 2);
if( pIn1->u.i>0 ){ if( pIn1->u.i>0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -5384,6 +5421,7 @@ case OP_IfPos: { /* jump, in1 */
case OP_IfNeg: { /* jump, in1 */ case OP_IfNeg: { /* jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int ); assert( pIn1->flags&MEM_Int );
VdbeBranchTaken(pIn1->u.i<0, 2);
if( pIn1->u.i<0 ){ if( pIn1->u.i<0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -5403,6 +5441,7 @@ case OP_IfZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int ); assert( pIn1->flags&MEM_Int );
pIn1->u.i += pOp->p3; pIn1->u.i += pOp->p3;
VdbeBranchTaken(pIn1->u.i==0, 2);
if( pIn1->u.i==0 ){ if( pIn1->u.i==0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -5674,6 +5713,7 @@ case OP_IncrVacuum: { /* jump */
assert( p->readOnly==0 ); assert( p->readOnly==0 );
pBt = db->aDb[pOp->p1].pBt; pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(pBt); rc = sqlite3BtreeIncrVacuum(pBt);
VdbeBranchTaken(rc==SQLITE_DONE,2);
if( rc==SQLITE_DONE ){ if( rc==SQLITE_DONE ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
rc = SQLITE_OK; rc = SQLITE_OK;
@@ -5880,7 +5920,7 @@ case OP_VFilter: { /* jump */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor); res = pModule->xEof(pVtabCursor);
} }
VdbeBranchTaken(res!=0,2);
if( res ){ if( res ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@@ -5985,7 +6025,7 @@ case OP_VNext: { /* jump */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor); res = pModule->xEof(pCur->pVtabCursor);
} }
VdbeBranchTaken(!res,2);
if( !res ){ if( !res ){
/* If there is data, jump to P2 */ /* If there is data, jump to P2 */
pc = pOp->p2 - 1; pc = pOp->p2 - 1;

View File

@@ -68,6 +68,9 @@ struct VdbeOp {
int cnt; /* Number of times this instruction was executed */ int cnt; /* Number of times this instruction was executed */
u64 cycles; /* Total time spent executing this instruction */ u64 cycles; /* Total time spent executing this instruction */
#endif #endif
#ifdef SQLITE_VDBE_COVERAGE
int iSrcLine; /* Source-code line that generated this opcode */
#endif
}; };
typedef struct VdbeOp VdbeOp; typedef struct VdbeOp VdbeOp;
@@ -167,7 +170,7 @@ int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
@@ -238,4 +241,14 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
# define VdbeModuleComment(X) # define VdbeModuleComment(X)
#endif #endif
/* Set the Opcode.iSrcline field of the previous opcode */
#ifdef SQLITE_VDBE_COVERAGE
void sqlite3VdbeSetLineNumber(Vdbe*,int);
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
#else
# define VdbeCoverage(v)
# define VdbeCoverageIf(v,x)
#endif
#endif #endif

View File

@@ -173,6 +173,9 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#ifdef VDBE_PROFILE #ifdef VDBE_PROFILE
pOp->cycles = 0; pOp->cycles = 0;
pOp->cnt = 0; pOp->cnt = 0;
#endif
#ifdef SQLITE_VDBE_COVERAGE
pOp->iSrcLine = 0;
#endif #endif
return i; return i;
} }
@@ -535,7 +538,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
** Add a whole list of operations to the operation stack. Return the ** Add a whole list of operations to the operation stack. Return the
** address of the first operation added. ** address of the first operation added.
*/ */
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
int addr; int addr;
assert( p->magic==VDBE_MAGIC_INIT ); assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){ if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
@@ -563,6 +566,11 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
pOut->zComment = 0; pOut->zComment = 0;
#endif #endif
#ifdef SQLITE_VDBE_COVERAGE
pOut->iSrcLine = iLineno+i;
#else
(void)iLineno;
#endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){ if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
@@ -851,6 +859,15 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
} }
#endif /* NDEBUG */ #endif /* NDEBUG */
#ifdef SQLITE_VDBE_COVERAGE
/*
** Set the value if the iSrcLine field for the previously coded instruction.
*/
void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
}
#endif /* SQLITE_VDBE_COVERAGE */
/* /*
** Return the opcode for a given address. If the address is -1, then ** Return the opcode for a given address. If the address is -1, then
** return the most recently inserted opcode. ** return the most recently inserted opcode.

View File

@@ -133,14 +133,13 @@ int sqlite3_blob_open(
** which closes the b-tree cursor and (possibly) commits the ** which closes the b-tree cursor and (possibly) commits the
** transaction. ** transaction.
*/ */
static const int iLn = __LINE__+4;
static const VdbeOpList openBlob[] = { static const VdbeOpList openBlob[] = {
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
/* One of the following two instructions is replaced by an OP_Noop. */ /* One of the following two instructions is replaced by an OP_Noop. */
{OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
{OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
{OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */
{OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */ {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */
{OP_Column, 0, 0, 1}, /* 6 */ {OP_Column, 0, 0, 1}, /* 6 */
@@ -265,7 +264,7 @@ int sqlite3_blob_open(
pTab->pSchema->schema_cookie, pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration); pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1); sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
/* Make sure a mutex is held on the table to be accessed */ /* Make sure a mutex is held on the table to be accessed */
sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeUsesBtree(v, iDb);

View File

@@ -1708,12 +1708,12 @@ static void constructAutomaticIndex(
VdbeComment((v, "for %s", pTable->zName)); VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */ /* Fill the automatic index with content */
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
regRecord = sqlite3GetTempReg(pParse); regRecord = sqlite3GetTempReg(pParse);
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0); sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop); sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempReg(pParse, regRecord);
@@ -2388,7 +2388,7 @@ static int codeEqualityTerm(
bRev = !bRev; bRev = !bRev;
} }
iTab = pX->iTable; iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); VdbeCoverage(v);
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
pLoop->wsFlags |= WHERE_IN_ABLE; pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){ if( pLevel->u.in.nIn==0 ){
@@ -2408,7 +2408,7 @@ static int codeEqualityTerm(
pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
} }
pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
sqlite3VdbeAddOp1(v, OP_IsNull, iReg); sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v);
}else{ }else{
pLevel->u.in.nIn = 0; pLevel->u.in.nIn = 0;
} }
@@ -2502,11 +2502,11 @@ static int codeAllEqualityTerms(
if( nSkip ){ if( nSkip ){
int iIdxCur = pLevel->iIdxCur; int iIdxCur = pLevel->iIdxCur;
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverage(v);
VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
j = sqlite3VdbeAddOp0(v, OP_Goto); j = sqlite3VdbeAddOp0(v, OP_Goto);
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
iIdxCur, 0, regBase, nSkip); iIdxCur, 0, regBase, nSkip); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, j); sqlite3VdbeJumpHere(v, j);
for(j=0; j<nSkip; j++){ for(j=0; j<nSkip; j++){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
@@ -2787,6 +2787,7 @@ static Bitmask codeOneLoopStart(
int regYield = pTabItem->regReturn; int regYield = pTabItem->regReturn;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeCoverage(v);
VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
pLevel->op = OP_Goto; pLevel->op = OP_Goto;
}else }else
@@ -2819,6 +2820,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
pLoop->u.vtab.idxStr, pLoop->u.vtab.idxStr,
pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC);
VdbeCoverage(v);
pLoop->u.vtab.needFree = 0; pLoop->u.vtab.needFree = 0;
for(j=0; j<nConstraint && j<16; j++){ for(j=0; j<nConstraint && j<16; j++){
if( (pLoop->u.vtab.omitMask>>j)&1 ){ if( (pLoop->u.vtab.omitMask>>j)&1 ){
@@ -2850,8 +2852,9 @@ static Bitmask codeOneLoopStart(
testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_VIRTUAL );
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
addrNxt = pLevel->addrNxt; addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
VdbeComment((v, "pk")); VdbeComment((v, "pk"));
@@ -2901,12 +2904,13 @@ static Bitmask codeOneLoopStart(
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
VdbeComment((v, "pk")); VdbeComment((v, "pk")); VdbeCoverage(v);
sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp); sqlite3ReleaseTempReg(pParse, rTemp);
disableTerm(pLevel, pStart); disableTerm(pLevel, pStart);
}else{ }else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
VdbeCoverage(v);
} }
if( pEnd ){ if( pEnd ){
Expr *pX; Expr *pX;
@@ -2934,6 +2938,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
} }
}else if( pLoop->wsFlags & WHERE_INDEXED ){ }else if( pLoop->wsFlags & WHERE_INDEXED ){
@@ -3107,6 +3112,13 @@ static Bitmask codeOneLoopStart(
testcase( op==OP_SeekLE ); testcase( op==OP_SeekLE );
testcase( op==OP_SeekLT ); testcase( op==OP_SeekLT );
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind);
VdbeCoverageIf(v, op==OP_Last);
VdbeCoverageIf(v, op==OP_SeekGT);
VdbeCoverageIf(v, op==OP_SeekGE);
VdbeCoverageIf(v, op==OP_SeekLE);
VdbeCoverageIf(v, op==OP_SeekLT);
/* Load the value for the inequality constraint at the end of the /* Load the value for the inequality constraint at the end of the
** range (if any). ** range (if any).
@@ -3144,6 +3156,7 @@ static Bitmask codeOneLoopStart(
testcase( op==OP_IdxLT ); testcase( op==OP_IdxLT );
testcase( op==OP_IdxLE ); testcase( op==OP_IdxLE );
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
} }
/* Seek the table cursor, if required */ /* Seek the table cursor, if required */
@@ -3164,7 +3177,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
} }
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
iRowidReg, pPk->nKeyCol); iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
} }
/* Record the instruction used to terminate the loop. Disable /* Record the instruction used to terminate the loop. Disable
@@ -3348,6 +3361,7 @@ static Bitmask codeOneLoopStart(
regRowid, 0); regRowid, 0);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet); sqlite3VdbeCurrentAddr(v)+2, r, iSet);
VdbeCoverage(v);
} }
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
@@ -3416,6 +3430,8 @@ static Bitmask codeOneLoopStart(
pLevel->op = aStep[bRev]; pLevel->op = aStep[bRev];
pLevel->p1 = iCur; pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
} }
} }
@@ -5785,6 +5801,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->op!=OP_Noop ){ if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5); sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
} }
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn; struct InLoop *pIn;
@@ -5793,6 +5810,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1); sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
} }
sqlite3DbFree(db, pLevel->u.in.aInLoop); sqlite3DbFree(db, pLevel->u.in.aInLoop);
@@ -5805,7 +5823,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
} }
if( pLevel->iLeftJoin ){ if( pLevel->iLeftJoin ){
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|| (pLoop->wsFlags & WHERE_INDEXED)!=0 ); || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){