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:
34
manifest
34
manifest
@@ -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
|
||||
|
@@ -1 +1 @@
|
||||
360c57bbb8bad6cc84af140f61e0282fa06462b4
|
||||
2a1af0f29e4c387721ec1fb3a2b55e8605b8401d
|
@@ -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" \
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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 ){
|
||||
|
22
src/pcache.c
22
src/pcache.c
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
231
src/vdbe.c
231
src/vdbe.c
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user