Merge in the latest changes from trunk.
FossilOrigin-Name: 66c4aaadda433c9d479a25c27cdff84560088402
This commit is contained in:
commit
69ac85420c
34
manifest
34
manifest
@ -1,12 +1,12 @@
|
||||
C Fix\sa\sproblem\sin\sfts4merge3.test.
|
||||
D 2012-03-28T13:55:29.023
|
||||
C Merge\sin\sthe\slatest\schanges\sfrom\strunk.
|
||||
D 2012-03-28T16:44:13.607
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 7849a871b6cdb20fd51baee6bbe5965a03326be4
|
||||
F Makefile.vxworks 3b7fe7a0571fdadc61363ebc1b23732d2d6363ca
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION bb4c2a86abe53ea3c1d6ea515b69a426040e2414
|
||||
F VERSION f9313d88cb77df8617059a88eb382291321ef6bc
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
|
||||
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
|
||||
@ -134,11 +134,11 @@ F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112
|
||||
F src/expr.c 00675123e0beec98f999aa4594d2cbe1fec33c1b
|
||||
F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
|
||||
F src/expr.c 1c351f385950a40b0283328eb925641a3aa50a84
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
|
||||
F src/func.c e75f41c421f00762ab9da7dc8fb90af3972cf99f
|
||||
F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6
|
||||
F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
|
||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
@ -181,11 +181,11 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c 44ccdcb5d2a1c48622c179b2d72167b716388581
|
||||
F src/shell.c aa28f117033ba3e44b5eaaf2ad572222bcdfd66e
|
||||
F src/select.c f6f141cb1ea13f1e6564d3e162700e4937baa2a1
|
||||
F src/shell.c 3179db5d4ff33d62d59a024dbfd2a116390ef7b0
|
||||
F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h e65429a6f19b41720561b9434b2192574a91cfa2
|
||||
F src/sqliteInt.h 3756ece33f1e7f8fe2adf8e523566825c809316e
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -241,7 +241,7 @@ F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3
|
||||
F src/vacuum.c bfd53f9bd20a8fdb70b0fa8e77182b866875c0d8
|
||||
F src/vdbe.c 32720e873ed0a23e6ee928b676cd995864b984d6
|
||||
F src/vdbe.c 8913926230bfc9d183fcd44e3d023c6d393b6548
|
||||
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
||||
F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82
|
||||
F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91
|
||||
@ -254,7 +254,7 @@ F src/vtab.c ab90fb600a3f5e4b7c48d22a4cdb2d6b23239847
|
||||
F src/wal.c 7bb3ad807afc7973406c805d5157ec7a2f65e146
|
||||
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 6baab5dfcf4472552c0346d04f6fd2f4f8539c78
|
||||
F src/where.c 44d78f5811594065ebbb5354da7f9e6b8b1306d6
|
||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
@ -503,7 +503,7 @@ F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
||||
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test 7ca2225996f6c4e12efbd4fe34ce8a805adecfb2
|
||||
F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca
|
||||
F test/func.test 9809b7622d721904a8cc33c1ffb87f46d506ed01
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
|
||||
@ -632,7 +632,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||
F test/pager1.test cf8f40cf77b5c4f762b1e8492390d61b46a81623
|
||||
F test/pager1.test eb6d64d2e148dc4bfc6420605bee3717e2d5f10c
|
||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
|
||||
@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P e31076319363a46905836880765bae3bf204ed19
|
||||
R 8261f69797f0415c0a684d0e5b4da417
|
||||
U dan
|
||||
Z 6d2d05b1946beea93ba45e372e1569b3
|
||||
P 64fc8b30f8bc7ddc697b6042040e958787ff3118 0733c98c329bc9942460746e9bbaf4b4c94c1520
|
||||
R 7c6a56a142b783bc5a39759c4e6db58f
|
||||
U drh
|
||||
Z b8266c3b3b198b8b23ee6f1eee86b3bc
|
||||
|
@ -1 +1 @@
|
||||
64fc8b30f8bc7ddc697b6042040e958787ff3118
|
||||
66c4aaadda433c9d479a25c27cdff84560088402
|
@ -374,7 +374,7 @@ void sqlite3DeleteFrom(
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
|
||||
);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
||||
if( db->flags & SQLITE_CountRows ){
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
||||
|
40
src/expr.c
40
src/expr.c
@ -2032,15 +2032,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
#if 0 /* This code wold remove the entry from the cache if it existed */
|
||||
if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
|
||||
cacheEntryClear(pParse, p);
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iReg = iReg;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
|
||||
}
|
||||
#endif
|
||||
@ -2175,7 +2166,8 @@ int sqlite3ExprCodeGetColumn(
|
||||
Table *pTab, /* Description of the table we are reading from */
|
||||
int iColumn, /* Index of the table column */
|
||||
int iTable, /* The cursor pointing to the table */
|
||||
int iReg /* Store results here */
|
||||
int iReg, /* Store results here */
|
||||
u8 p5 /* P5 value for OP_Column */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
@ -2190,7 +2182,11 @@ int sqlite3ExprCodeGetColumn(
|
||||
}
|
||||
assert( v!=0 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
|
||||
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
|
||||
if( p5 ){
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
}else{
|
||||
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
|
||||
}
|
||||
return iReg;
|
||||
}
|
||||
|
||||
@ -2318,7 +2314,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
inReg = pExpr->iColumn + pParse->ckBase;
|
||||
}else{
|
||||
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
pExpr->iColumn, pExpr->iTable, target);
|
||||
pExpr->iColumn, pExpr->iTable, target,
|
||||
pExpr->op2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2595,6 +2592,25 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
|
||||
if( pFarg ){
|
||||
r1 = sqlite3GetTempRange(pParse, nFarg);
|
||||
|
||||
/* For length() and typeof() functions with a column argument,
|
||||
** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
|
||||
** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
|
||||
** loading.
|
||||
*/
|
||||
if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
|
||||
u8 op;
|
||||
assert( nFarg==1 );
|
||||
assert( pFarg->a[0].pExpr!=0 );
|
||||
op = pFarg->a[0].pExpr->op;
|
||||
if( op==TK_COLUMN || op==TK_AGG_COLUMN ){
|
||||
assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
|
||||
assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
|
||||
testcase( pDef->flags==SQLITE_FUNC_LENGTH );
|
||||
pFarg->a[0].pExpr->op2 = pDef->flags;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
|
||||
sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
|
||||
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
|
||||
|
10
src/func.c
10
src/func.c
@ -1542,8 +1542,8 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(max, -1, 1, 1, minmaxFunc ),
|
||||
FUNCTION(max, 0, 1, 1, 0 ),
|
||||
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
|
||||
FUNCTION(typeof, 1, 0, 0, typeofFunc ),
|
||||
FUNCTION(length, 1, 0, 0, lengthFunc ),
|
||||
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
||||
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
||||
FUNCTION(substr, 2, 0, 0, substrFunc ),
|
||||
FUNCTION(substr, 3, 0, 0, substrFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
@ -1555,11 +1555,9 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
||||
FUNCTION(coalesce, 1, 0, 0, 0 ),
|
||||
FUNCTION(coalesce, 0, 0, 0, 0 ),
|
||||
/* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */
|
||||
{-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0},
|
||||
FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
|
||||
FUNCTION(hex, 1, 0, 0, hexFunc ),
|
||||
/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
|
||||
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0},
|
||||
FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
|
||||
FUNCTION(random, 0, 0, 0, randomFunc ),
|
||||
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
||||
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
||||
|
@ -4228,7 +4228,7 @@ int sqlite3Select(
|
||||
int r2;
|
||||
|
||||
r2 = sqlite3ExprCodeGetColumn(pParse,
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1);
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
|
||||
if( r1!=r2 ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
|
||||
}
|
||||
|
13
src/shell.c
13
src/shell.c
@ -1077,6 +1077,9 @@ static int display_stats(
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
|
||||
fprintf(pArg->out, "Page cache misses: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
|
||||
fprintf(pArg->out, "Page cache writes: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
@ -1287,7 +1290,6 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
char *zTableInfo = 0;
|
||||
char *zTmp = 0;
|
||||
int nRow = 0;
|
||||
int kk;
|
||||
|
||||
zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
|
||||
zTableInfo = appendText(zTableInfo, zTable, '"');
|
||||
@ -1300,12 +1302,9 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
}
|
||||
|
||||
zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
|
||||
if( !isalpha(zTable[0]) ){
|
||||
kk = 0;
|
||||
}else{
|
||||
for(kk=1; isalnum(zTable[kk]); kk++){}
|
||||
}
|
||||
zTmp = appendText(zTmp, zTable, zTable[kk] ? '"' : 0);
|
||||
/* Always quote the table name, even if it appears to be pure ascii,
|
||||
** in case it is a keyword. Ex: INSERT INTO "table" ... */
|
||||
zTmp = appendText(zTmp, zTable, '"');
|
||||
if( zTmp ){
|
||||
zSelect = appendText(zSelect, zTmp, '\'');
|
||||
}
|
||||
|
@ -1009,14 +1009,18 @@ struct FuncDestructor {
|
||||
};
|
||||
|
||||
/*
|
||||
** Possible values for FuncDef.flags
|
||||
** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
|
||||
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
|
||||
** are assert() statements in the code to verify this.
|
||||
*/
|
||||
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
|
||||
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
|
||||
#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
|
||||
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
|
||||
#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */
|
||||
#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */
|
||||
#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */
|
||||
#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
|
||||
#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */
|
||||
#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */
|
||||
|
||||
/*
|
||||
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
||||
@ -1044,7 +1048,10 @@ struct FuncDestructor {
|
||||
** parameter.
|
||||
*/
|
||||
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
||||
{nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
|
||||
{nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
|
||||
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
|
||||
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
|
||||
{nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
|
||||
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
|
||||
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
|
||||
{nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
|
||||
@ -1667,6 +1674,7 @@ struct Expr {
|
||||
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
u8 flags2; /* Second set of flags. EP2_... */
|
||||
u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
|
||||
/* If TK_COLUMN, the value of p5 for OP_Column */
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. */
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
@ -1689,7 +1697,7 @@ struct Expr {
|
||||
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_Hint 0x1000 /* Optimizer hint. Not required for correctness */
|
||||
#define EP_Hint 0x1000 /* Not used */
|
||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||
@ -2276,7 +2284,7 @@ struct AuthContext {
|
||||
};
|
||||
|
||||
/*
|
||||
** Bitfield flags for P5 value in OP_Insert and OP_Delete
|
||||
** Bitfield flags for P5 value in various opcodes.
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
|
||||
#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
|
||||
@ -2284,6 +2292,8 @@ struct AuthContext {
|
||||
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
|
||||
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
|
||||
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
|
||||
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
|
||||
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
||||
|
||||
/*
|
||||
* Each trigger present in the database schema is stored as an instance of
|
||||
@ -2767,7 +2777,7 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
||||
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
void sqlite3ExprCodeCopy(Parse*, int, int, int);
|
||||
|
42
src/vdbe.c
42
src/vdbe.c
@ -2127,6 +2127,11 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
|
||||
** then the cache of the cursor is reset prior to extracting the column.
|
||||
** The first OP_Column against a pseudo-table after the value of the content
|
||||
** register has changed should have this bit set.
|
||||
**
|
||||
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
|
||||
** the result is guaranteed to only be used as the argument of a length()
|
||||
** or typeof() function, respectively. The loading of large blobs can be
|
||||
** skipped for length() and all content loading can be skipped for typeof().
|
||||
*/
|
||||
case OP_Column: {
|
||||
u32 payloadSize; /* Number of bytes in the record */
|
||||
@ -2267,7 +2272,7 @@ case OP_Column: {
|
||||
pC->aRow = 0;
|
||||
}
|
||||
}
|
||||
/* The following assert is true in all cases accept when
|
||||
/* 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);
|
||||
@ -2342,11 +2347,11 @@ case OP_Column: {
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
/* If i is less that nField, then there are less fields in this
|
||||
/* 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 a NULL
|
||||
** instead of deserializing a value from the record.
|
||||
** 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;
|
||||
}
|
||||
@ -2376,17 +2381,32 @@ case OP_Column: {
|
||||
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{
|
||||
len = sqlite3VdbeSerialTypeLen(aType[p2]);
|
||||
sqlite3VdbeMemMove(&sMem, pDest);
|
||||
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto op_column_out;
|
||||
/* 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;
|
||||
}
|
||||
zData = sMem.z;
|
||||
sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
|
||||
sqlite3VdbeSerialGet((u8*)zData, t, pDest);
|
||||
}
|
||||
pDest->enc = encoding;
|
||||
}else{
|
||||
|
@ -4383,7 +4383,7 @@ static Bitmask codeOneLoopStart(
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
int r;
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
||||
regRowid);
|
||||
regRowid, 0);
|
||||
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
|
||||
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
||||
}
|
||||
|
@ -1247,4 +1247,48 @@ do_test func-28.1 {
|
||||
}
|
||||
} {1 {unknown function: nosuchfunc()}}
|
||||
|
||||
# Verify that the length() and typeof() functions do not actually load
|
||||
# the content of their argument.
|
||||
#
|
||||
do_test func-29.1 {
|
||||
db eval {
|
||||
CREATE TABLE t29(id INTEGER PRIMARY KEY, x, y);
|
||||
INSERT INTO t29 VALUES(1, 2, 3), (2, NULL, 4), (3, 4.5, 5);
|
||||
INSERT INTO t29 VALUES(4, randomblob(1000000), 6);
|
||||
INSERT INTO t29 VALUES(5, "hello", 7);
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_status db CACHE_MISS 1
|
||||
db eval {SELECT typeof(x), length(x), typeof(y) FROM t29 ORDER BY id}
|
||||
} {integer 1 integer null {} integer real 3 integer blob 1000000 integer text 5 integer}
|
||||
do_test func-29.2 {
|
||||
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
|
||||
if {$x<5} {set x 1}
|
||||
set x
|
||||
} {1}
|
||||
do_test func-29.3 {
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_status db CACHE_MISS 1
|
||||
db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
|
||||
} {integer null real blob text}
|
||||
do_test func-29.4 {
|
||||
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
|
||||
if {$x>100} {set x many}
|
||||
set x
|
||||
} {many}
|
||||
do_test func-29.5 {
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_status db CACHE_MISS 1
|
||||
db eval {SELECT sum(length(x)) FROM t29}
|
||||
} {1000009}
|
||||
do_test func-29.6 {
|
||||
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
|
||||
if {$x<5} {set x 1}
|
||||
set x
|
||||
} {1}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -1768,7 +1768,7 @@ do_test pager1-18.2 {
|
||||
catchsql { SELECT count(*) FROM t1 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.3 {
|
||||
do_test pager1-18.3.1 {
|
||||
execsql {
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO t2 VALUES(a_string(5000));
|
||||
@ -1776,13 +1776,38 @@ do_test pager1-18.3 {
|
||||
set pgno [expr ([file size test.db] / 1024)-2]
|
||||
hexio_write test.db [expr ($pgno-1)*1024] 00000000
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT length(x) FROM t2 } db2
|
||||
# even though x is malformed, because typeof() does
|
||||
# not load the content of x, the error is not noticed.
|
||||
catchsql { SELECT typeof(x) FROM t2 } db2
|
||||
} {0 text}
|
||||
do_test pager1-18.3.2 {
|
||||
# in this case, the value of x is loaded and so the error is
|
||||
# detected
|
||||
catchsql { SELECT length(x||'') FROM t2 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.3.3 {
|
||||
execsql {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2 VALUES(randomblob(5000));
|
||||
}
|
||||
set pgno [expr ([file size test.db] / 1024)-2]
|
||||
hexio_write test.db [expr ($pgno-1)*1024] 00000000
|
||||
sqlite3 db2 test.db
|
||||
# even though x is malformed, because length() and typeof() do
|
||||
# not load the content of x, the error is not noticed.
|
||||
catchsql { SELECT length(x), typeof(x) FROM t2 } db2
|
||||
} {0 {5000 blob}}
|
||||
do_test pager1-18.3.4 {
|
||||
# in this case, the value of x is loaded and so the error is
|
||||
# detected
|
||||
catchsql { SELECT length(x||'') FROM t2 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.4 {
|
||||
hexio_write test.db [expr ($pgno-1)*1024] 90000000
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT length(x) FROM t2 } db2
|
||||
catchsql { SELECT length(x||'') FROM t2 } db2
|
||||
} {1 {database disk image is malformed}}
|
||||
db2 close
|
||||
do_test pager1-18.5 {
|
||||
|
Loading…
Reference in New Issue
Block a user