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

Merge latest trunk changes with this branch.

FossilOrigin-Name: 2a1af0f29e4c387721ec1fb3a2b55e8605b8401d
This commit is contained in:
dan
2015-06-26 19:33:04 +00:00
14 changed files with 229 additions and 133 deletions

View File

@@ -1,5 +1,5 @@
C Fix\ssome\scases\sin\sthe\sfts5\scode\swhere\sa\scorrupt\sdatabase\scould\scause\sa\sbuffer\soverread.
D 2015-06-26T18:50:29.818
C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
D 2015-06-26T19:33:04.560
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -250,7 +250,7 @@ F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk d585680c45db1f68ec5ef88199fb10694d117e17
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -263,13 +263,13 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 48e14b8aea28dc58baafe3cfcb8889c086b7744a
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
F src/analyze.c f89727c36f997bd2bf6c5e546c2f51dc94e6f2a4
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 40e98c10725c2cec5429068e21c17924f4bf06cc
F src/btree.c c113f73fc4048038529cc30ed7147b24c34c2c5d
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h fdd1aff02fb2a63812bd95716e7f579fc3759107
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
@@ -279,7 +279,7 @@ F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
F src/expr.c 32c836d9fa22c25371039febf074849dcefb3de9
F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1
@@ -317,7 +317,7 @@ F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 9bc918a009285f96ec6dac62dd764c7063552455
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
F src/pcache.c d8b19632706dd6b81b03d0c5fd1e6bab8c13d0b9
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
F src/pcache1.c 8e3799b33c41d517d86444d4abefc80d4f02adca
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
@@ -327,7 +327,7 @@ F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 9baeda79f93cfd180d471273a2f9c82c682a37a2
F src/select.c 009c6138be8788449d4f911f380d99e8608040e2
F src/shell.c 8af3cced094aebb5f57a8ad739b9dafc7867eed7
F src/sqlite.h.in 76d2f5637eb795b6300d9dd3c3ec3632ffafd721
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
@@ -390,13 +390,13 @@ F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 3af2d06e2b36012631dc3331957df52febdf8678
F src/vdbe.h 90048aea1910f9df93e6044592bd4a466dc9c5e7
F src/vdbeInt.h 20295e482121d13437f69985f77db211cdc8bac1
F src/vdbe.c b425feab69fb29b3cf4d40c5c8ea585bce883307
F src/vdbe.h 7a75045d879118b9d3af7e8b3c108f2f27c51473
F src/vdbeInt.h 8b54e01ad0463590e7cffabce0bc36da9ee4f816
F src/vdbeapi.c 6a0d7757987018ff6b1b81bc5293219cd26bb299
F src/vdbeaux.c 4c82d6f686f72ea7d266d26d528a171b728626f7
F src/vdbeaux.c 13261b7597c7f189232f84a1e175a3268ea2c32b
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c 4e947cd322bb531e3f7f6f58f0f536d182b38ef8
F src/vdbemem.c ae38a0d35ae71cf604381a887c170466ba518090
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e
@@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 954231d29d60460d423ecb132bbfb725b0ea375a
R f24cf4dc2b8231a9cc4f2e0f89642df3
P 360c57bbb8bad6cc84af140f61e0282fa06462b4 eaddbf296aee98ffca82adade1b0d2fbefd09d7b
R 46e30302e9c721b7ade798b428e70680
U dan
Z eeb5dd5cce2b08a289c0b394982d9461
Z 99ffda12a690ac2d5944e0d64e334d3f

View File

@@ -1 +1 @@
360c57bbb8bad6cc84af140f61e0282fa06462b4
2a1af0f29e4c387721ec1fb3a2b55e8605b8401d

View File

@@ -122,9 +122,7 @@ END {
for(i=0; i<n_op; i++){
name = order[i];
if( op[name]>=0 ) continue;
if( name=="OP_Function" \
|| name=="OP_AggStep" \
|| name=="OP_Transaction" \
if( name=="OP_Transaction" \
|| name=="OP_AutoCommit" \
|| name=="OP_Savepoint" \
|| name=="OP_Checkpoint" \

View File

@@ -943,7 +943,7 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
#else
UNUSED_PARAMETER( iParam );
#endif
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4, regOut);
sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 1 + IsStat34);
}
@@ -1098,7 +1098,7 @@ static void analyzeOneTable(
#endif
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4);
sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4+1, regStat4);
sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 2+IsStat34);
@@ -1194,7 +1194,7 @@ static void analyzeOneTable(
}
#endif
assert( regChng==(regStat4+1) );
sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
sqlite3VdbeAddOp3(v, OP_Function0, 1, regStat4, regTemp);
sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 2+IsStat34);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);

View File

@@ -359,7 +359,7 @@ static void codeAttach(
assert( v || db->mallocFailed );
if( v ){
sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
sqlite3VdbeAddOp3(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3);
assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);

View File

@@ -1442,7 +1442,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
top = get2byte(&data[hdr+5]);
assert( top<=pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
if( gap>top ){
if( top==0 && pPage->pBt->usableSize==65536 ){
top = 65536;

View File

@@ -2925,7 +2925,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nFarg);
if( nFarg && constMask==0 ){

View File

@@ -28,7 +28,6 @@ struct PCache {
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module */
PgHdr *pPage1; /* Reference to page 1 */
};
/********************************** Linked List Management ********************/
@@ -106,9 +105,6 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
*/
static void pcacheUnpin(PgHdr *p){
if( p->pCache->bPurgeable ){
if( p->pgno==1 ){
p->pCache->pPage1 = 0;
}
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
}
}
@@ -201,7 +197,6 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
}
pCache->pCache = pNew;
pCache->pPage1 = 0;
pCache->szPage = szPage;
}
return SQLITE_OK;
@@ -359,9 +354,6 @@ PgHdr *sqlite3PcacheFetchFinish(
pCache->nRef++;
}
pPgHdr->nRef++;
if( pgno==1 ){
pCache->pPage1 = pPgHdr;
}
return pPgHdr;
}
@@ -402,9 +394,6 @@ void sqlite3PcacheDrop(PgHdr *p){
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
}
p->pCache->nRef--;
if( p->pgno==1 ){
p->pCache->pPage1 = 0;
}
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
}
@@ -495,9 +484,14 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
sqlite3PcacheMakeClean(p);
}
}
if( pgno==0 && pCache->pPage1 ){
memset(pCache->pPage1->pData, 0, pCache->szPage);
pgno = 1;
if( pgno==0 && pCache->nRef ){
sqlite3_pcache_page *pPage1;
pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0);
if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because
** pCache->nRef>0 */
memset(pPage1->pBuf, 0, pCache->szPage);
pgno = 1;
}
}
sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
}

View File

@@ -4686,7 +4686,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem,
(void*)pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);

View File

@@ -1546,10 +1546,10 @@ case OP_CollSeq: {
break;
}
/* Opcode: Function P1 P2 P3 P4 P5
/* Opcode: Function0 P1 P2 P3 P4 P5
** Synopsis: r[P3]=func(r[P2@P5])
**
** Invoke a user function (P4 is a pointer to a Function structure that
** Invoke a user function (P4 is a pointer to a FuncDef object that
** defines the function) with P5 arguments taken from register P2 and
** successors. The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
@@ -1561,59 +1561,100 @@ case OP_CollSeq: {
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
** See also: AggStep and AggFinal
** See also: Function, AggStep, AggFinal
*/
case OP_Function: {
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
/* Opcode: Function P1 P2 P3 P4 P5
** Synopsis: r[P3]=func(r[P2@P5])
**
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
** contains a pointer to the function to be run) with P5 arguments taken
** from register P2 and successors. The result of the function is stored
** in register P3. Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
** SQL functions are initially coded as OP_Function0 with P4 pointing
** to a FuncDef object. But on first evaluation, the P4 operand is
** automatically converted into an sqlite3_context object and the operation
** changed to this OP_Function opcode. In this way, the initialization of
** the sqlite3_context object occurs only once, rather than once for each
** evaluation of the function.
**
** See also: Function0, AggStep, AggFinal
*/
case OP_Function0: {
int n;
n = pOp->p5;
apVal = p->apArg;
assert( apVal || n==0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
ctx.pOut = &aMem[pOp->p3];
memAboutToChange(p, ctx.pOut);
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){
assert( memIsValid(pArg) );
apVal[i] = pArg;
Deephemeralize(pArg);
REGISTER_TRACE(pOp->p2+i, pArg);
}
sqlite3_context *pCtx;
assert( pOp->p4type==P4_FUNCDEF );
ctx.pFunc = pOp->p4.pFunc;
ctx.iOp = (int)(pOp - aOp);
ctx.pVdbe = p;
MemSetTypeFlag(ctx.pOut, MEM_Null);
ctx.fErrorOrAux = 0;
n = pOp->p5;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
if( pCtx==0 ) goto no_mem;
pCtx->pOut = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
pOp->opcode = OP_Function;
/* Fall through into OP_Function */
}
case OP_Function: {
int i;
sqlite3_context *pCtx;
assert( pOp->p4type==P4_FUNCCTX );
pCtx = pOp->p4.pCtx;
/* If this function is inside of a trigger, the register array in aMem[]
** might change from one evaluation to the next. The next block of code
** checks to see if the register array has changed, and if so it
** reinitializes the relavant parts of the sqlite3_context object */
pOut = &aMem[pOp->p3];
if( pCtx->pOut != pOut ){
pCtx->pOut = pOut;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
memAboutToChange(p, pCtx->pOut);
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
}
#endif
MemSetTypeFlag(pCtx->pOut, MEM_Null);
pCtx->fErrorOrAux = 0;
db->lastRowid = lastRowid;
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
(*pCtx->pFunc->xFunc)(pCtx, pCtx->argc, pCtx->argv); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */
/* If the function returned an error, throw an exception */
if( ctx.fErrorOrAux ){
if( ctx.isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(ctx.pOut));
rc = ctx.isError;
if( pCtx->fErrorOrAux ){
if( pCtx->isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(p, (int)(pOp - aOp), pOp->p1);
sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1);
}
/* Copy the result of the function into register P3 */
sqlite3VdbeChangeEncoding(ctx.pOut, encoding);
if( sqlite3VdbeMemTooBig(ctx.pOut) ){
goto too_big;
if( pOut->flags & (MEM_Str|MEM_Blob) ){
sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
}
REGISTER_TRACE(pOp->p3, ctx.pOut);
UPDATE_MAX_BLOBSIZE(ctx.pOut);
REGISTER_TRACE(pOp->p3, pCtx->pOut);
UPDATE_MAX_BLOBSIZE(pCtx->pOut);
break;
}
@@ -5697,57 +5738,101 @@ case OP_JumpZeroIncr: { /* jump, in1 */
break;
}
/* Opcode: AggStep * P2 P3 P4 P5
/* Opcode: AggStep0 * P2 P3 P4 P5
** Synopsis: accum=r[P3] step(r[P2@P5])
**
** Execute the step function for an aggregate. The
** function has P5 arguments. P4 is a pointer to the FuncDef
** structure that specifies the function. Use register
** P3 as the accumulator.
** structure that specifies the function. Register P3 is the
** accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
*/
case OP_AggStep: {
/* Opcode: AggStep * P2 P3 P4 P5
** Synopsis: accum=r[P3] step(r[P2@P5])
**
** Execute the step function for an aggregate. The
** function has P5 arguments. P4 is a pointer to an sqlite3_context
** object that is used to run the function. Register P3 is
** as the accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
**
** This opcode is initially coded as OP_AggStep0. On first evaluation,
** the FuncDef stored in P4 is converted into an sqlite3_context and
** the opcode is changed. In this way, the initialization of the
** sqlite3_context only happens once, instead of on each call to the
** step function.
*/
case OP_AggStep0: {
int n;
int i;
Mem *pMem;
Mem *pRec;
Mem t;
sqlite3_context ctx;
sqlite3_value **apVal;
sqlite3_context *pCtx;
assert( pOp->p4type==P4_FUNCDEF );
n = pOp->p5;
assert( n>=0 );
pRec = &aMem[pOp->p2];
apVal = p->apArg;
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
assert( memIsValid(pRec) );
apVal[i] = pRec;
memAboutToChange(p, pRec);
}
ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
ctx.pMem = pMem = &aMem[pOp->p3];
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
if( pCtx==0 ) goto no_mem;
pCtx->pMem = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
pOp->opcode = OP_AggStep;
/* Fall through into OP_AggStep */
}
case OP_AggStep: {
int i;
sqlite3_context *pCtx;
Mem *pMem;
Mem t;
assert( pOp->p4type==P4_FUNCCTX );
pCtx = pOp->p4.pCtx;
pMem = &aMem[pOp->p3];
/* If this function is inside of a trigger, the register array in aMem[]
** might change from one evaluation to the next. The next block of code
** checks to see if the register array has changed, and if so it
** reinitializes the relavant parts of the sqlite3_context object */
if( pCtx->pMem != pMem ){
pCtx->pMem = pMem;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
}
#endif
pMem->n++;
sqlite3VdbeMemInit(&t, db, MEM_Null);
ctx.pOut = &t;
ctx.isError = 0;
ctx.pVdbe = p;
ctx.iOp = (int)(pOp - aOp);
ctx.skipFlag = 0;
(ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( ctx.isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
rc = ctx.isError;
pCtx->pOut = &t;
pCtx->fErrorOrAux = 0;
pCtx->skipFlag = 0;
(pCtx->pFunc->xStep)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
if( pCtx->fErrorOrAux ){
if( pCtx->isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
rc = pCtx->isError;
}
sqlite3VdbeMemRelease(&t);
}else{
assert( t.flags==MEM_Null );
}
if( ctx.skipFlag ){
if( pCtx->skipFlag ){
assert( pOp[-1].opcode==OP_CollSeq );
i = pOp[-1].p1;
if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
}
sqlite3VdbeMemRelease(&t);
break;
}

View File

@@ -46,13 +46,14 @@ struct VdbeOp {
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
union { /* fourth parameter */
union p4union { /* fourth parameter */
int i; /* Integer value if p4type==P4_INT32 */
void *p; /* Generic pointer */
char *z; /* Pointer to data for string (char array) types */
i64 *pI64; /* Used when p4type is P4_INT64 */
double *pReal; /* Used when p4type is P4_REAL */
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
Mem *pMem; /* Used when p4type is P4_MEM */
VTable *pVtab; /* Used when p4type is P4_VTAB */
@@ -119,6 +120,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
#define P4_FUNCCTX (-20) /* P4 is a pointer to an sqlite3_context object */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1

View File

@@ -279,14 +279,16 @@ struct AuxData {
** (Mem) which are only defined there.
*/
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
/*

View File

@@ -489,11 +489,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
/* NOTE: Be sure to update mkopcodeh.awk when adding or removing
** cases from this switch! */
switch( opcode ){
case OP_Function:
case OP_AggStep: {
if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
break;
}
case OP_Transaction: {
if( pOp->p2!=0 ) p->readOnly = 0;
/* fall thru */
@@ -737,6 +732,10 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( p4 ){
assert( db );
switch( p4type ){
case P4_FUNCCTX: {
freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc);
/* Fall through into the next case */
}
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
@@ -1121,6 +1120,13 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
#ifdef SQLITE_DEBUG
case P4_FUNCCTX: {
FuncDef *pDef = pOp->p4.pCtx->pFunc;
sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
#endif
case P4_INT64: {
sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64);
break;

View File

@@ -1694,17 +1694,26 @@ void sqlite3ValueFree(sqlite3_value *v){
}
/*
** Return the number of bytes in the sqlite3_value object assuming
** that it uses the encoding "enc"
** The sqlite3ValueBytes() routine returns the number of bytes in the
** sqlite3_value object assuming that it uses the encoding "enc".
** The valueBytes() routine is a helper function.
*/
static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){
return valueToText(pVal, enc)!=0 ? pVal->n : 0;
}
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
Mem *p = (Mem*)pVal;
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 );
if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
return p->n;
}
if( (p->flags & MEM_Blob)!=0 ){
if( p->flags & MEM_Zero ){
return p->n + p->u.nZero;
}else{
return p->n;
}
}
return 0;
if( p->flags & MEM_Null ) return 0;
return valueBytes(pVal, enc);
}