Compare commits

..

18 Commits

Author SHA1 Message Date
drh 5cc1023e1c Reduce the size of VdbeCursor again, this time without a performance hit.
FossilOrigin-Name: 933939932c44bccb0958f203a5bd24e683c1cf38
2013-11-21 01:04:02 +00:00
drh 1fd522ff49 Unpack some fields, adding some space back to the VdbeCursor object,
in order to help the code to run a little faster.

FossilOrigin-Name: f8d5efcd7b92492b833b6cd1cb6bec006c6a0809
2013-11-21 00:10:35 +00:00
drh 14da87f8c5 Reduce the size of the VdbeCursor object from 144 to 120 bytes.
FossilOrigin-Name: 5f9d50688508affd0bc8e4d52e21dacfacdbb5ce
2013-11-20 21:51:33 +00:00
drh 380d685133 Improved comments on the OP_Column changes. Optimize out loading of overflow
pages for content with zero length.  Add test cases for the latter.

FossilOrigin-Name: 0e05679db7aa302a49e087a81f85203844b98cbe
2013-11-20 20:58:00 +00:00
drh c8606e416a Further performance tweaks to OP_Column.
FossilOrigin-Name: 0e3f5df695216a27602a53eed5d25231b055adc8
2013-11-20 19:28:03 +00:00
drh 399af1d2c2 Refactoring the OP_Column opcode for improved performance and
maintainability.

FossilOrigin-Name: 7c914e3997d2b28164a2fa7eb4398262b6ddb4b2
2013-11-20 17:25:55 +00:00
drh 79353dbd5f Simplifications to the VdbeCursor object.
FossilOrigin-Name: 5562cd343d8f69242e06a51a7f1aef7ee7d78eec
2013-11-20 02:53:58 +00:00
drh 83b301b0af Performance improvement for the OP_MustBeInt opcode in the VDBE.
FossilOrigin-Name: 96a65388e75fed96e2e73ef65726f6db88cc5ccd
2013-11-20 00:59:02 +00:00
drh 707f1c560a Fix a harmless MSVC compiler warning.
FossilOrigin-Name: 6cc023bb29be51847fbbfab95c24fc89993ccdba
2013-11-19 18:17:20 +00:00
drh c138dafe88 Minor performance improvement to sqlite3SerialTypeGet().
FossilOrigin-Name: 17e8524fc05aa1e6074c19a8ccccc5ab5883103a
2013-11-19 13:55:34 +00:00
drh 6bc69a2d4b Change Noop-comments in where.c into Module-comments, so that they are
omitting without SQLITE_ENABLE_MODULE_COMMENTS.

FossilOrigin-Name: 3e577f40183c56e60866d8382b044688a1b77eaf
2013-11-19 12:33:23 +00:00
drh 5c82f4df9f Avoid seeking on the main data table during the first loop of an UPDATE
if an index is sufficient to check the WHERE clause.

FossilOrigin-Name: 57158d9daf4d777411fffb1c1d20d89b291d9214
2013-11-19 02:34:11 +00:00
drh f37139f65b Fix an requirement mark in a test script so that it matches the
typo-corrected requirement.  No changes to code.

FossilOrigin-Name: 072412d5e3f92c9c6548f5c86d396d3f024df3f7
2013-11-19 00:31:25 +00:00
drh 64ff26f741 Add comments identifing where the skip-scan option is decided in the
query planner, to aid in tuning that decision.  No changes to code.

FossilOrigin-Name: e9df04cec48bb8b4ea26ec9024a22ea42b2338eb
2013-11-18 19:32:15 +00:00
drh 2365bac1e2 Fix documentation typos. No changes to code.
FossilOrigin-Name: 7caeb09c52bde4649b02b339f611c8e30f6d1c68
2013-11-18 18:48:50 +00:00
drh 2bea7cde6e Fix harmless compiler warnings from clang scan-build.
FossilOrigin-Name: 8d002740bffca2a76d2dfbc1a67293d34f9de9ba
2013-11-18 11:20:50 +00:00
dan c4650bb33d Fix a problem with the shell tool EXPLAIN indentation code and VDBE sub-programs.
FossilOrigin-Name: 9c8d6856253f8da06b2cb5dc6bd89b6952fa03ed
2013-11-18 08:41:06 +00:00
drh e73e067187 Enable the ONEPASS optimization for DELETE, for both rowid and WITHOUT
ROWID tables.

FossilOrigin-Name: 44a07afdd9b3ae2460bc963383295deb0915f899
2013-11-18 03:11:54 +00:00
17 changed files with 340 additions and 354 deletions
+6 -3
View File
@@ -333,6 +333,9 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
v = (v & mask1) | ( (*ptr++) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
@@ -345,7 +348,7 @@ int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
u64 b;
int shift;
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *v, 1);
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1);
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2);
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
@@ -357,7 +360,7 @@ int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
if( (c & 0x80)==0 ) break;
}
*v = b;
return p - pStart;
return (int)(p - pStart);
}
/*
@@ -368,7 +371,7 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
u32 a;
#ifndef fts3GetVarint32
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *pi, 1);
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
#else
a = (*p++);
assert( a & 0x80 );
+20 -20
View File
@@ -1,5 +1,5 @@
C Make\ssure\sone-pass\sDELETE\sfor\sWITHOUT\sROWID\stables\scorrectly\spositions\sthe\nPRIMARY\sKEY\scursor.\s\sMake\sthe\ssame\sfix\sfor\sUPDATE.
D 2013-11-17T02:42:02.540
C Reduce\sthe\ssize\sof\sVdbeCursor\sagain,\sthis\stime\swithout\sa\sperformance\shit.
D 2013-11-21T01:04:02.826
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c dceaa5079833caa2e7945433e1eb93bb22f623a3
F ext/fts3/fts3.c 1e667eacb3fe4b4ad6f863920da4286f071f6e07
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
@@ -174,10 +174,10 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c d88e4fbfeca5a8cf48b7d358b9a68d5e81f314b7
F src/expr.c 1a295d8b0a2ba08919ad9300ebf7b67988ff4030
F src/delete.c 909936019ccb8d0f4a10d0d10ad607c38ee62cbe
F src/expr.c d81090a3f3bb0845fa6c6795d221ec23ef107737
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
F src/func.c 96caa9dfd1febf9a4b720de4c43ccfb392a52b73
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
@@ -220,8 +220,8 @@ F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c 6fcceeb653a0020b14491975d567c989e794d408
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 253cb683e4a05b0b56b0f9c816f3c4a4e5575ebb
F src/shell.c b98e74123d6c2e20369607c1da2d23c71db633d9
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
F src/shell.c 849ee96c952d20e504d417e42a06acc5ca94ef17
F src/sqlite.h.in a5dc058a909d9f14470bad9329d9e9303020ea4e
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 03b91c6bceccd7718473f3d790abcb8d5c2b1bf1
@@ -276,16 +276,16 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
F src/update.c cc3d826923f7b61566dedbb3cfce5f13964f35a4
F src/update.c c05a0ee658f1a149e0960dfd110f3b8bd846bcb0
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 5573893423aec2d64871e8d504fadbcdaad39fed
F src/vdbe.c c375ba0385f747e58d98686f5f4f0439c6297b35
F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
F src/vdbeInt.h 62eb680327011f3a4b0336642b0ca9d6ecc6eb91
F src/vdbeInt.h 0ac03c790b8ea4568b747550ba9bbf92a8e8feb2
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/vdbeaux.c dd0f6ab9dc159911facfc0a7a2164af44779bdda
F src/vdbeblob.c d883398f7260725147dbf5b40c2b61332aee47f9
F src/vdbeaux.c bbf06ccbb159611d55e32783c6e9fdec75b120d0
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
F src/vdbemem.c cc529bbf4f13e4e181bdb446bf6e6962ab030b4b
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
@@ -293,7 +293,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
F src/where.c de64e326bb2a07e5591900b11a93d743df2a6919
F src/where.c aa72ba871fa835a513cae1c7432dc1d785eb23e4
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -313,7 +313,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
F test/analyze9.test 1b9b7e9a096d1536f03d9ad7b72f638ef5669347
F test/analyze9.test 339e87723cd4dc158dc5e9095acd8df9e87faf79
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
@@ -437,7 +437,7 @@ F test/e_createtable.test 3b453432cd14a12732ee9467597d2274ca37ce36
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_expr.test d5cdda0e4ffb17760858ed4c7c4ece07efc40f71
F test/e_expr.test 7d7feeadb555b49476e9ca4a145fcf7c0a81ce34
F test/e_fkey.test d83a04478bb9c02d2c513518548a69f818869f41
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
@@ -573,7 +573,7 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
F test/fts4unicode.test e28ba1a14181e709dcdf47455f207adf14c7cfe0
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test c7e80a44eebac8604397eb2ad83d0d5d9d541237
F test/func.test 00667bbeac044d007f6f021af1b9f6150f0c7ff8
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
@@ -1140,7 +1140,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P a11243f840d35aaed8ee3b9901c3950bc584a417
R f429117cda51c1a8c08160d9a3f515e6
P f8d5efcd7b92492b833b6cd1cb6bec006c6a0809
R 842b8e02c5c12ba51889f25ba6cef74b
U drh
Z 2718e457b564d6fbe8d10873d690a300
Z a21060677c94bf6a3d8120f6bac96f14
+1 -1
View File
@@ -1 +1 @@
6bd5750b7d5da221b0689f6df6be5ed0dce61bec
933939932c44bccb0958f203a5bd24e683c1cf38
+4 -5
View File
@@ -244,10 +244,10 @@ void sqlite3DeleteFrom(
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
Index *pPk; /* The PRIMARY KEY index on the table */
int iPk; /* First of nPk registerss holding PRIMARY KEY value */
i16 nPk = 1; /* Number of components of the PRIMARY KEY */
int iKey; /* Memory cell holding row key of to be deleted */
i16 nKey; /* Number of memory cells of row key */
int iPk; /* First of nPk registers holding PRIMARY KEY value */
i16 nPk = 1; /* Number of columns in the PRIMARY KEY */
int iKey; /* Memory cell holding key of row to be deleted */
i16 nKey; /* Number of memory cells in the row key */
int iEphCur = 0; /* Ephemeral table holding all primary key values */
int iRowSet = 0; /* Register for rowset of rows to delete */
int addrBypass = 0; /* Address of jump over the delete logic */
@@ -420,7 +420,6 @@ void sqlite3DeleteFrom(
pPk->aiColumn[i], iPk+i);
}
iKey = iPk;
nKey = nPk;
}else{
iKey = pParse->nMem + 1;
iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
+1 -1
View File
@@ -1193,7 +1193,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* Consider functions to be constant if all their arguments are constant
** and pWalker->u.i==2 */
case TK_FUNCTION:
if( pWalker->u.i==2 ) return 0;
if( pWalker->u.i==2 ) return WRC_Continue;
/* Fall through */
case TK_ID:
case TK_COLUMN:
+2
View File
@@ -548,6 +548,7 @@ static void fkScanChildren(
assert( pIdx==0 || pIdx->pTable==pTab );
assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
assert( pIdx!=0 || pFKey->nCol==1 );
assert( pIdx!=0 || HasRowid(pTab) );
if( nIncr<0 ){
iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
@@ -600,6 +601,7 @@ static void fkScanChildren(
}else{
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
for(i=0; i<pPk->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
+18 -7
View File
@@ -466,6 +466,7 @@ struct callback_data {
FILE *pLog; /* Write log output here */
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
int iIndent; /* Index of current op in aiIndent[] */
};
/*
@@ -771,10 +772,10 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
w = strlen30(azArg[i]);
}
if( i==1 && p->aiIndent && p->pStmt ){
int iOp = sqlite3_column_int(p->pStmt, 0);
if( iOp<p->nIndent ){
fprintf(p->out, "%*.s", p->aiIndent[iOp], "");
if( p->iIndent<p->nIndent ){
fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
}
p->iIndent++;
}
if( w<0 ){
fprintf(p->out,"%*.*s%s",-w,-w,
@@ -1184,7 +1185,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp;
int iOp; /* Index of operation in p->aiIndent[] */
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", 0 };
@@ -1199,8 +1200,16 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
int i;
int iAddr = sqlite3_column_int(pSql, 0);
const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
/* Set p2 to the P2 field of the current opcode. Then, assuming that
** p2 is an instruction address, set variable p2op to the index of that
** instruction in the aiIndent[] array. p2 and p2op may be different if
** the current instruction is part of a sub-program generated by an
** SQL trigger or foreign key. */
int p2 = sqlite3_column_int(pSql, 3);
int p2op = (p2 + (iOp-iAddr));
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
@@ -1213,13 +1222,14 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) ){
for(i=p2; i<iOp; i++) p->aiIndent[i] += 2;
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2<p->nIndent && abYield[p2] ){
for(i=p2+1; i<iOp; i++) p->aiIndent[i] += 2;
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
}
p->iIndent = 0;
sqlite3_free(abYield);
sqlite3_reset(pSql);
}
@@ -1231,6 +1241,7 @@ static void explain_data_delete(struct callback_data *p){
sqlite3_free(p->aiIndent);
p->aiIndent = 0;
p->nIndent = 0;
p->iIndent = 0;
}
/*
+6 -7
View File
@@ -365,7 +365,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** <ul>
** <li> The application must insure that the 1st parameter to sqlite3_exec()
** is a valid and open [database connection].
** <li> The application must not close [database connection] specified by
** <li> The application must not close the [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -442,7 +442,7 @@ int sqlite3_exec(
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will be expand
** One may expect the number of extended result codes will increase
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
@@ -1380,7 +1380,7 @@ int sqlite3_db_config(sqlite3*, int op, ...);
** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. (For example,
** The xInit method initializes the memory allocator. For example,
** it might allocate any require mutexes or initialize internal data
** structures. The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -3106,7 +3106,6 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** the
** </li>
** </ol>
*/
@@ -3836,7 +3835,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
** ^(If a memory allocation error occurs during the evaluation of any
@@ -4914,8 +4913,8 @@ int sqlite3_release_memory(int);
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
** [sqlite3_release_memory()] interface, this interface is effect even
** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
** [sqlite3_release_memory()] interface, this interface is in effect even
** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
** omitted.
**
** See also: [sqlite3_release_memory()]
+5
View File
@@ -263,6 +263,11 @@ void sqlite3Update(
assert( chngPk==0 || chngPk==1 );
chngKey = chngRowid + chngPk;
/* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask
*/
pTabList->a[0].colUsed = 0;
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
/* There is one entry in the aRegIdx[] array for each index on the table
+211 -267
View File
@@ -212,9 +212,8 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
nByte =
ROUND8(sizeof(VdbeCursor)) +
(isBtreeCursor?sqlite3BtreeCursorSize():0) +
2*nField*sizeof(u32);
ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
(isBtreeCursor?sqlite3BtreeCursorSize():0);
assert( iCur<p->nCursor );
if( p->apCsr[iCur] ){
@@ -226,12 +225,9 @@ static VdbeCursor *allocateCursor(
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
if( nField ){
pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))];
}
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)];
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->pCursor);
}
}
@@ -1662,17 +1658,19 @@ case OP_AddImm: { /* in1 */
*/
case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
if( (pIn1->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
pc = pOp->p2 - 1;
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
if( (pIn1->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
pc = pOp->p2 - 1;
break;
}
}
}else{
MemSetTypeFlag(pIn1, MEM_Int);
}
MemSetTypeFlag(pIn1, MEM_Int);
break;
}
@@ -2251,151 +2249,103 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** skipped for length() and all content loading can be skipped for typeof().
*/
case OP_Column: {
u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
int p1; /* P1 value of the opcode */
int p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
char *zRec; /* Pointer to complete record-data */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
int nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
const u8 *zData; /* Part of the record being decoded */
const u8 *zHdr; /* Next unparsed byte of the header */
const u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u32 szField; /* Number of bytes in the content of a field */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
p1 = pOp->p1;
p2 = pOp->p2;
pC = 0;
memset(&sMem, 0, sizeof(sMem));
assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
zRec = 0;
/* This block sets the variable payloadSize to be the total number of
** bytes in the record.
**
** zRec is set to be the complete text of the record if it is available.
** The complete record text is always available for pseudo-tables
** If the record is stored in a cursor, the complete record text
** might be available in the pC->aRow cache. Or it might not be.
** If the data is unavailable, zRec is set to NULL.
**
** We also compute the number of columns in the record. For cursors,
** the number of columns is stored in the VdbeCursor.nField element.
*/
pC = p->apCsr[p1];
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( p2<pC->nField );
aType = pC->aType;
aOffset = aType + pC->nField;
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pC->pVtabCursor==0 );
assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
#endif
pCrsr = pC->pCursor;
if( pCrsr!=0 ){
/* The record is stored in a B-Tree */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */
assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */
/* If the cursor cache is stale, bring it up-to-date */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
if( pC->nullRow ){
payloadSize = 0;
}else if( pC->cacheStatus==p->cacheCtr ){
payloadSize = pC->payloadSize;
zRec = (char*)pC->aRow;
}else if( pC->isIndex ){
assert( sqlite3BtreeCursorIsValid(pCrsr) );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
** payload size, so it is impossible for payloadSize64 to be
** larger than 32 bits. */
assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
payloadSize = (u32)payloadSize64;
if( pCrsr==0 ){
assert( pC->pseudoTableReg>0 );
pReg = &aMem[pC->pseudoTableReg];
if( pC->multiPseudo ){
sqlite3VdbeMemShallowCopy(pDest, pReg+p2, MEM_Ephem);
Deephemeralize(pDest);
goto op_column_out;
}
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = avail = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
MemSetTypeFlag(pDest, MEM_Null);
goto op_column_out;
}
}else{
assert( sqlite3BtreeCursorIsValid(pCrsr) );
VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &payloadSize);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
assert( pCrsr );
if( pC->isTable==0 ){
assert( sqlite3BtreeCursorIsValid(pCrsr) );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
** payload size, so it is impossible for payloadSize64 to be
** larger than 32 bits. */
assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail);
pC->payloadSize = (u32)payloadSize64;
}else{
assert( sqlite3BtreeCursorIsValid(pCrsr) );
VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail);
}
assert( avail<=65536 ); /* Maximum page size is 64KiB */
if( pC->payloadSize <= (u32)avail ){
pC->szRow = pC->payloadSize;
}else{
pC->szRow = avail;
}
if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
}else{
assert( pC->pseudoTableReg>0 );
pReg = &aMem[pC->pseudoTableReg];
if( pC->multiPseudo ){
sqlite3VdbeMemShallowCopy(pDest, pReg+p2, MEM_Ephem);
Deephemeralize(pDest);
goto op_column_out;
}
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
payloadSize = pReg->n;
zRec = pReg->z;
pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
assert( payloadSize==0 || zRec!=0 );
}
/* If payloadSize is 0, then just store a NULL. This can happen because of
** nullRow or because of a corrupt database. */
if( payloadSize==0 ){
MemSetTypeFlag(pDest, MEM_Null);
goto op_column_out;
}
assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
if( payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
nField = pC->nField;
assert( p2<nField );
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
aType = pC->aType;
if( pC->cacheStatus==p->cacheCtr ){
aOffset = pC->aOffset;
}else{
assert(aType);
avail = 0;
pC->aOffset = aOffset = &aType[nField];
pC->payloadSize = payloadSize;
pC->cacheStatus = p->cacheCtr;
/* Figure out how many bytes are in the header */
if( zRec ){
zData = zRec;
}else{
if( pC->isIndex ){
zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail);
}else{
zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail);
}
/* If KeyFetch()/DataFetch() managed to get the entire payload,
** save the payload in the pC->aRow cache. That will save us from
** having to make additional calls to fetch the content portion of
** the record.
*/
assert( avail>=0 );
if( payloadSize <= (u32)avail ){
zRec = zData;
pC->aRow = (u8*)zData;
}else{
pC->aRow = 0;
}
pC->iHdrOffset = getVarint32(pC->aRow, offset);
pC->nHdrParsed = 0;
aOffset[0] = offset;
if( avail<offset ){
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
}
/* The following assert is true in all cases except when
** the database file has been corrupted externally.
** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */
szHdr = getVarint32((u8*)zData, offset);
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
@@ -2406,155 +2356,148 @@ case OP_Column: {
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
if( offset > 98307 ){
if( offset > 98307 || offset > pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
goto op_column_error;
}
}
/* Compute in len the number of bytes of data we need to read in order
** to get nField type values. offset is an upper bound on this. But
** nField might be significantly less than the true number of columns
** in the table, and in that case, 5*nField+3 might be smaller than offset.
** We want to minimize len in order to limit the size of the memory
** allocation, especially if a corrupt database file has caused offset
** to be oversized. Offset is limited to 98307 above. But 98307 might
** still exceed Robson memory allocation limits on some configurations.
** On systems that cannot tolerate large memory allocations, nField*5+3
** will likely be much smaller since nField will likely be less than
** 20 or so. This insures that Robson memory allocation limits are
** not exceeded even for corrupt database files.
/* Make sure at least the first p2+1 entries of the header have been
** parsed and valid information is in aOffset[] and aType[].
*/
if( pC->nHdrParsed<=p2 ){
/* If there is more header available for parsing in the record, try
** to extract additional fields up through the p2+1-th field
*/
len = nField*5 + 3;
if( len > (int)offset ) len = (int)offset;
/* The KeyFetch() or DataFetch() above are fast and will get the entire
** record header in most cases. But they will fail to get the complete
** record header if the record header does not fit on a single page
** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
** acquire the complete header text.
*/
if( !zRec && avail<len ){
sMem.flags = 0;
sMem.db = 0;
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, len, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
if( pC->iHdrOffset<aOffset[0] ){
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
memset(&sMem, 0, sizeof(sMem));
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0],
!pC->isTable, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
zData = (u8*)sMem.z;
}else{
zData = pC->aRow;
}
zData = sMem.z;
}
zEndHdr = (u8 *)&zData[len];
zIdx = (u8 *)&zData[szHdr];
/* Scan the header and use it to fill in the aType[] and aOffset[]
** arrays. aType[i] will contain the type integer for the i-th
** column and aOffset[i] will contain the offset from the beginning
** of the record to the start of the data for the i-th column
*/
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
aOffset[i] = offset;
if( zIdx[0]<0x80 ){
t = zIdx[0];
zIdx++;
/* Fill in aType[i] and aOffset[i] values through the p2-th field. */
i = pC->nHdrParsed;
offset = aOffset[i];
zHdr = zData + pC->iHdrOffset;
zEndHdr = zData + aOffset[0];
assert( i<=p2 && zHdr<zEndHdr );
do{
if( zHdr[0]<0x80 ){
t = zHdr[0];
zHdr++;
}else{
zIdx += sqlite3GetVarint32(zIdx, &t);
zHdr += sqlite3GetVarint32(zHdr, &t);
}
aType[i] = t;
szField = sqlite3VdbeSerialTypeLen(t);
offset += szField;
if( offset<szField ){ /* True if offset overflows */
zIdx = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
zHdr = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
}else{
/* If i is less that nField, then there are fewer fields in this
** record than SetNumColumns indicated there are columns in the
** table. Set the offset for any extra columns not present in
** the record to 0. This tells code below to store the default value
** for the column instead of deserializing a value from the record.
*/
aOffset[i] = 0;
i++;
aOffset[i] = offset;
}while( i<=p2 && zHdr<zEndHdr );
pC->nHdrParsed = i;
pC->iHdrOffset = (u32)(zHdr - zData);
if( pC->aRow==0 ){
sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
}
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
** record, or if the end of the last field appears to be before the end
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
if( (zHdr > zEndHdr)
|| (offset > pC->payloadSize)
|| (zHdr==zEndHdr && offset!=pC->payloadSize)
){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
}
sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
** record, or if the end of the last field appears to be before the end
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
/* If after trying to extra new entries from the header, nHdrParsed is
** still not up to p2, that means that the record has fewer than p2
** columns. So the result will be either the default value or a NULL.
*/
if( (zIdx > zEndHdr) || (offset > payloadSize)
|| (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
if( pC->nHdrParsed<=p2 ){
if( pOp->p4type==P4_MEM ){
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
MemSetTypeFlag(pDest, MEM_Null);
}
goto op_column_out;
}
}
/* Get the column information. If aOffset[p2] is non-zero, then
** deserialize the value from the record. If aOffset[p2] is zero,
** then there are not enough fields in the record to satisfy the
** request. In this case, set the value NULL or to P4 if P4 is
** a pointer to a Mem object.
/* Extract the content for the p2+1-th column. Control can only
** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
** all valid.
*/
if( aOffset[p2] ){
assert( rc==SQLITE_OK );
if( zRec ){
/* This is the common case where the whole row fits on a single page */
VdbeMemRelease(pDest);
sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
}else{
/* This branch happens only when the row overflows onto multiple pages */
t = aType[p2];
if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
){
/* Content is irrelevant for the typeof() function and for
** the length(X) function if X is a blob. So we might as well use
** bogus content rather than reading content from disk. NULL works
** for text and blob and whatever is in the payloadSize64 variable
** will work for everything else. */
zData = t<12 ? (char*)&payloadSize64 : 0;
}else{
len = sqlite3VdbeSerialTypeLen(t);
sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,
&sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
zData = sMem.z;
}
sqlite3VdbeSerialGet((u8*)zData, t, pDest);
}
pDest->enc = encoding;
assert( p2<pC->nHdrParsed );
assert( rc==SQLITE_OK );
if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
** page - where the content is not on an overflow page */
VdbeMemRelease(pDest);
sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
}else{
if( pOp->p4type==P4_MEM ){
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
/* This branch happens only when content is on overflow pages */
t = aType[p2];
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
|| (len = sqlite3VdbeSerialTypeLen(t))==0
){
/* Content is irrelevant for the typeof() function and for
** the length(X) function if X is a blob. So we might as well use
** bogus content rather than reading content from disk. NULL works
** for text and blob and whatever is in the payloadSize64 variable
** will work for everything else. Content is also irrelevant if
** the content length is 0. */
zData = t<=13 ? (u8*)&payloadSize64 : 0;
sMem.zMalloc = 0;
}else{
MemSetTypeFlag(pDest, MEM_Null);
memset(&sMem, 0, sizeof(sMem));
sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
&sMem);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
zData = (u8*)sMem.z;
}
sqlite3VdbeSerialGet(zData, t, pDest);
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
** dynamically allocated space over to the pDest structure.
** This prevents a memory copy. */
if( sMem.zMalloc ){
assert( sMem.z==sMem.zMalloc );
assert( !(pDest->flags & MEM_Dyn) );
assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
pDest->flags &= ~(MEM_Ephem|MEM_Static);
pDest->flags |= MEM_Term;
pDest->z = sMem.z;
pDest->zMalloc = sMem.zMalloc;
}
}
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
** dynamically allocated space over to the pDest structure.
** This prevents a memory copy.
*/
if( sMem.zMalloc ){
assert( sMem.z==sMem.zMalloc );
assert( !(pDest->flags & MEM_Dyn) );
assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
pDest->flags &= ~(MEM_Ephem|MEM_Static);
pDest->flags |= MEM_Term;
pDest->z = sMem.z;
pDest->zMalloc = sMem.zMalloc;
}
rc = sqlite3VdbeMemMakeWriteable(pDest);
pDest->enc = encoding;
op_column_out:
rc = sqlite3VdbeMemMakeWriteable(pDest);
op_column_error:
UPDATE_MAX_BLOBSIZE(pDest);
REGISTER_TRACE(pOp->p3, pDest);
break;
@@ -3310,6 +3253,8 @@ case OP_OpenWrite: {
nField = pOp->p4.i;
}
assert( pOp->p1>=0 );
assert( nField>=0 );
testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
@@ -3323,12 +3268,11 @@ case OP_OpenWrite: {
** sqlite3BtreeCursor() may return is SQLITE_OK. */
assert( rc==SQLITE_OK );
/* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO;
pCur->isIndex = !pCur->isTable;
break;
}
@@ -3370,6 +3314,7 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
@@ -3402,7 +3347,6 @@ case OP_OpenEphemeral: {
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
pCx->isIndex = !pCx->isTable;
break;
}
@@ -3415,12 +3359,13 @@ case OP_OpenEphemeral: {
case OP_SorterOpen: {
VdbeCursor *pCx;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->pKeyInfo = pOp->p4.pKeyInfo;
assert( pCx->pKeyInfo->db==db );
assert( pCx->pKeyInfo->enc==ENC(db) );
pCx->isSorter = 1;
rc = sqlite3VdbeSorterInit(db, pCx);
break;
}
@@ -3446,12 +3391,12 @@ case OP_OpenPseudo: {
VdbeCursor *pCx;
assert( pOp->p1>=0 );
assert( pOp->p3>=0 );
pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTableReg = pOp->p2;
pCx->isTable = 1;
pCx->isIndex = 0;
pCx->multiPseudo = pOp->p5;
break;
}
@@ -4267,7 +4212,7 @@ case OP_SorterData: {
pOut = &aMem[pOp->p2];
pC = p->apCsr[pOp->p1];
assert( pC->isSorter );
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
break;
}
@@ -4307,9 +4252,9 @@ case OP_RowData: {
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC->isSorter==0 );
assert( isSorter(pC)==0 );
assert( pC->isTable || pOp->opcode!=OP_RowData );
assert( pC->isIndex || pOp->opcode==OP_RowData );
assert( pC->isTable==0 || pOp->opcode==OP_RowData );
assert( pC!=0 );
assert( pC->nullRow==0 );
assert( pC->pseudoTableReg==0 );
@@ -4326,7 +4271,7 @@ case OP_RowData: {
rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
if( pC->isIndex ){
if( pC->isTable==0 ){
assert( !pC->isTable );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
@@ -4346,7 +4291,7 @@ case OP_RowData: {
}
pOut->n = n;
MemSetTypeFlag(pOut, MEM_Blob);
if( pC->isIndex ){
if( pC->isTable==0 ){
rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
}else{
rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
@@ -4419,6 +4364,7 @@ case OP_NullRow: {
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
pC->cacheStatus = CACHE_STALE;
assert( pC->pCursor || pC->pVtabCursor );
if( pC->pCursor ){
sqlite3BtreeClearCursor(pC->pCursor);
@@ -4494,7 +4440,7 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->isSorter==(pOp->opcode==OP_SorterSort) );
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
res = 1;
if( isSorter(pC) ){
rc = sqlite3VdbeSorterRewind(db, pC, &res);
@@ -4502,7 +4448,6 @@ case OP_Rewind: { /* jump */
pCrsr = pC->pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0 ?1:0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
pC->rowidIsValid = 0;
@@ -4559,7 +4504,7 @@ case OP_Next: { /* jump */
if( pC==0 ){
break; /* See ticket #2273 */
}
assert( pC->isSorter==(pOp->opcode==OP_SorterNext) );
assert( isSorter(pC)==(pOp->opcode==OP_SorterNext) );
if( isSorter(pC) ){
assert( pOp->opcode==OP_SorterNext );
rc = sqlite3VdbeSorterNext(db, pC, &res);
@@ -4607,7 +4552,7 @@ case OP_IdxInsert: { /* in2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->isSorter==(pOp->opcode==OP_SorterInsert) );
assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
pCrsr = pC->pCursor;
@@ -5858,7 +5803,6 @@ case OP_VOpen: {
pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
pCur->pModule = pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
pModule->xClose(pVtabCursor);
+24 -23
View File
@@ -36,7 +36,7 @@ typedef struct VdbeOp Op;
/*
** Boolean values
*/
typedef unsigned char Bool;
typedef unsigned Bool;
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;
@@ -53,6 +53,9 @@ typedef struct AuxData AuxData;
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
**
** Cursors can also point to virtual tables, sorters, or "pseudo-tables".
** A pseudo-table is a single-row table implemented by registers.
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
@@ -61,30 +64,24 @@ struct VdbeCursor {
BtCursor *pCursor; /* The cursor structure of the backend */
Btree *pBt; /* Separate file holding temporary table */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
int seekResult; /* Result of previous sqlite3BtreeMoveto() */
int pseudoTableReg; /* Register holding pseudotable content. */
int nField; /* Number of fields in the header */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
Bool isSorter; /* True if a new-style sorter */
Bool multiPseudo; /* Multi-register pseudo-cursor */
i16 nField; /* Number of fields in the header */
u16 nHdrParsed; /* Number of header fields parsed so far */
i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
u8 nullRow; /* True if pointing to a row with no data */
u8 rowidIsValid; /* True if lastRowid is valid */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
Bool isTable:1; /* True if a table requiring integer keys */
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
Bool multiPseudo:1; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
i64 lastRowid; /* Rowid being deleted by OP_Delete */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists */
int seekResult;
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
@@ -95,10 +92,14 @@ struct VdbeCursor {
** be NULL.
*/
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
int payloadSize; /* Total number of bytes in the record */
u32 *aType; /* Type values for all entries in the record */
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
u32 payloadSize; /* Total number of bytes in the record */
u32 szRow; /* Byte available in aRow */
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
const u8 *aRow; /* Data for the current row, if all on one page */
u32 aType[1]; /* Type values for all entries in the record */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
** aType[] and nField+1 array slots for aOffset[] */
};
typedef struct VdbeCursor VdbeCursor;
+4 -7
View File
@@ -1674,7 +1674,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pCx->pModule;
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
p->inVtabMethod = 1;
pModule->xClose(pVtabCursor);
p->inVtabMethod = 0;
@@ -2658,7 +2658,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
#endif
p->deferredMoveto = 0;
p->cacheStatus = CACHE_STALE;
}else if( ALWAYS(p->pCursor) ){
}else if( p->pCursor ){
int hasMoved;
int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
if( rc ) return rc;
@@ -2966,15 +2966,12 @@ u32 sqlite3VdbeSerialGet(
return 0;
}
default: {
static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
u32 len = (serial_type-12)/2;
pMem->z = (char *)buf;
pMem->n = len;
pMem->xDel = 0;
if( serial_type&0x01 ){
pMem->flags = MEM_Str | MEM_Ephem;
}else{
pMem->flags = MEM_Blob | MEM_Ephem;
}
pMem->flags = aFlag[serial_type&1];
return len;
}
}
+4 -3
View File
@@ -64,7 +64,8 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
rc = sqlite3_step(p->pStmt);
if( rc==SQLITE_ROW ){
u32 type = v->apCsr[0]->aType[p->iCol];
VdbeCursor *pC = v->apCsr[0];
u32 type = pC->aType[p->iCol];
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -73,9 +74,9 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
}else{
p->iOffset = v->apCsr[0]->aOffset[p->iCol];
p->iOffset = pC->aType[p->iCol + pC->nField];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = v->apCsr[0]->pCursor;
p->pCsr = pC->pCursor;
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
+11 -6
View File
@@ -2756,7 +2756,7 @@ static Bitmask codeOneLoopStart(
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeNoopComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -3461,7 +3461,7 @@ static Bitmask codeOneLoopStart(
if( pAlt->wtFlags & (TERM_CODED) ) continue;
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IN );
VdbeNoopComment((v, "begin transitive constraint"));
VdbeModuleComment((v, "begin transitive constraint"));
pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
if( pEAlt ){
*pEAlt = *pAlt->pExpr;
@@ -3918,10 +3918,15 @@ static int whereLoopAddBtreeIndex(
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
/* Consider using a skip-scan if there are no WHERE clause constraints
** available for the left-most terms of the index, and if the average
** number of repeats in the left-most terms is at least 50.
*/
if( pTerm==0
&& saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
&& pProbe->aiRowEst[saved_nEq+1]>50
&& pProbe->aiRowEst[saved_nEq+1]>50 /* TUNING: Minimum for skip-scan */
){
LogEst nIter;
pNew->u.btree.nEq++;
@@ -5731,7 +5736,7 @@ WhereInfo *sqlite3WhereBegin(
}
/* Done. */
VdbeNoopComment((v, "Begin WHERE-core"));
VdbeModuleComment((v, "Begin WHERE-core"));
return pWInfo;
/* Jump here if malloc fails */
@@ -5758,7 +5763,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
VdbeNoopComment((v, "End WHERE-core"));
VdbeModuleComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
@@ -5804,7 +5809,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
sqlite3VdbeJumpHere(v, addr);
}
VdbeNoopComment((v, "End WHERE-loop%d: %s", i,
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
+2 -1
View File
@@ -805,8 +805,9 @@ do_test 16.1 {
ANALYZE;
}
set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
puts -nonewline " (nByte=$nByte nByte2=$nByte2)"
expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1050}
expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1100}
} {1}
#-------------------------------------------------------------------------
+3 -3
View File
@@ -1081,9 +1081,9 @@ ifcapable !icu {
# EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for
# the regexp() user function.
#
# EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named
# "regexp" is added at run-time, that function will be called in order
# to implement the REGEXP operator.
# EVIDENCE-OF: R-65524-61849 If an application-defined SQL function
# named "regexp" is added at run-time, then the "X REGEXP Y" operator
# will be implemented as a call to "regexp(Y,X)".
#
proc regexpfunc {args} {
eval lappend ::regexpargs $args
+18
View File
@@ -1319,6 +1319,24 @@ do_test func-29.6 {
set x
} {1}
# The OP_Column opcode has an optimization that avoids loading content
# for fields with content-length=0 when the content offset is on an overflow
# page. Make sure the optimization works.
#
do_execsql_test func-29.10 {
CREATE TABLE t29b(a,b,c,d,e,f,g,h,i);
INSERT INTO t29b
VALUES(1, hex(randomblob(2000)), null, 0, 1, '', zeroblob(0),'x',x'01');
SELECT typeof(c), typeof(d), typeof(e), typeof(f),
typeof(g), typeof(h), typeof(i) FROM t29b;
} {null integer integer text blob text blob}
do_execsql_test func-29.11 {
SELECT length(f), length(g), length(h), length(i) FROM t29b;
} {0 0 1 1}
do_execsql_test func-29.12 {
SELECT quote(f), quote(g), quote(h), quote(i) FROM t29b;
} {'' X'' 'x' X'01'}
# EVIDENCE-OF: R-29701-50711 The unicode(X) function returns the numeric
# unicode code point corresponding to the first character of the string
# X.