From: drh Date: Thu, 2 Feb 2012 17:35:43 +0000 (+0000) Subject: For queries of the form "SELECT p, max(q) FROM t1", the value of column p X-Git-Tag: version-3.7.11~64^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a95789c0c21a39e8bd9972b92262c63a2ae820a;p=thirdparty%2Fsqlite.git For queries of the form "SELECT p, max(q) FROM t1", the value of column p returned is the one on the same row that holds the maximum value of q. FossilOrigin-Name: adb29232b659c5332b6841776372407fcc350b08 --- diff --git a/manifest b/manifest index a02f0e5e2c..c28861e94c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Data\sstructure\scleanup.\s\sRemove\sunused\sfields.\s\sRearrange\sother\sfiles\sfor\ntighter\spacking\sand\sreduced\smemory\susage. -D 2012-02-02T15:50:17.008 +C For\squeries\sof\sthe\sform\s"SELECT\sp,\smax(q)\sFROM\st1",\sthe\svalue\sof\scolumn\sp\nreturned\sis\sthe\sone\son\sthe\ssame\srow\sthat\sholds\sthe\smaximum\svalue\sof\sq. +D 2012-02-02T17:35:43.157 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -137,7 +137,7 @@ F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112 F src/expr.c 00675123e0beec98f999aa4594d2cbe1fec33c1b F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 -F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9 +F src/func.c f66c87956c9afc098e1b74612d3c2b38760a41dc F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 @@ -180,7 +180,7 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c b6eec9d11ec5df0d1fd11e8a0eed0fc2d2d96b25 +F src/select.c 232283a2e60d91cbd9a5ddf2f6f7ecf53d590075 F src/shell.c 60d147c2411dd2d79a5151cfb9a068de87c7babe F src/sqlite.h.in 371c30e4be94b9b0ea6400ed66663fcf8e891eb4 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 @@ -240,9 +240,9 @@ F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/util.c 9e07bd67dfafe9c75b1da78c87ba030cebbb5388 F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa -F src/vdbe.c 43ea77c83e7f35169328f13b20cc8140bd2cf473 +F src/vdbe.c 40b14dff04692b1ee421db40c67d4921ecf17a9d F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb -F src/vdbeInt.h 2e79ce66ff45a01411151957bb2899af680f1560 +F src/vdbeInt.h 0f986e86a4a0afbf52d0402071708f487d1cfc15 F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91 F src/vdbeaux.c 7683d772ad638faa4567142438c4594e47f173c4 F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb @@ -386,7 +386,7 @@ F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459 F test/e_insert.test 234242b71855af8e8a9b1e141c3533f6d43d8645 F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216 F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6 -F test/e_select.test 6f488c22851c1c280ed74e16a9a1430706a3a8cb +F test/e_select.test f0aa7a972a336e5e874700915b1f5abd7d63a7e2 F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92 F test/e_update.test dba988a4d079156549a40854074ba4890b0a4577 F test/e_uri.test 6f35b491f80dac005c8144f38b2dfb4d96483596 @@ -988,7 +988,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 25df2a7458d025bc00380b4a0893637639f9f0d4 -R d2ba4c243c1dae496337618e0657e24d +P 0bc594e861ae1142e8c6c83f39b095e1432856bf +R eff167ee91b10474f283fe35279e92e9 +T *branch * output-minmax-row +T *sym-output-minmax-row * +T -sym-trunk * U drh -Z ada6e2e4fcf7ab0bc8362d130037dce6 +Z cf65185cbe7093f978d4a185698ec6ea diff --git a/manifest.uuid b/manifest.uuid index 3536af2979..e33d5dd106 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0bc594e861ae1142e8c6c83f39b095e1432856bf \ No newline at end of file +adb29232b659c5332b6841776372407fcc350b08 \ No newline at end of file diff --git a/src/func.c b/src/func.c index 3a1879ca69..deddd5375b 100644 --- a/src/func.c +++ b/src/func.c @@ -28,6 +28,14 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ return context->pColl; } +/* +** Indicate that the accumulator load should be skipped on this +** iteration of the aggregate loop. +*/ +static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ + context->skipFlag = 1; +} + /* ** Implementation of the non-aggregate min() and max() functions */ @@ -1354,6 +1362,8 @@ static void minmaxStep( cmp = sqlite3MemCompare(pBest, pArg, pColl); if( (max && cmp<0) || (!max && cmp>0) ){ sqlite3VdbeMemCopy(pBest, pArg); + }else{ + sqlite3SkipAccumulatorLoad(context); } }else{ sqlite3VdbeMemCopy(pBest, pArg); diff --git a/src/select.c b/src/select.c index 6fcb37f70d..bbdc4e3c55 100644 --- a/src/select.c +++ b/src/select.c @@ -3596,6 +3596,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; + int regHit = 0; + int addrHitTest = 0; struct AggInfo_func *pF; struct AggInfo_col *pC; @@ -3631,7 +3633,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( !pColl ){ pColl = pParse->db->pDfltColl; } - sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + 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, (void*)pF->pFunc, P4_FUNCDEF); @@ -3654,12 +3657,18 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ** Another solution would be to change the OP_SCopy used to copy cached ** values to an OP_Copy. */ + if( regHit ){ + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); + } sqlite3ExprCacheClear(pParse); for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } pAggInfo->directMode = 0; sqlite3ExprCacheClear(pParse); + if( addrHitTest ){ + sqlite3VdbeJumpHere(v, addrHitTest); + } } /* diff --git a/src/vdbe.c b/src/vdbe.c index 111d5b52bb..9ce25942dd 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1331,19 +1331,26 @@ arithmetic_result_is_null: break; } -/* Opcode: CollSeq * * P4 +/* Opcode: CollSeq P1 * * P4 ** ** P4 is a pointer to a CollSeq struct. If the next call to a user function ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will ** be returned. This is used by the built-in min(), max() and nullif() ** functions. ** +** If P1 is not zero, then it is a register that a subsequent min() or +** max() aggregate will set to 1 if the current row is not the minimum or +** maximum. The P1 register is initialized to 0 by this instruction. +** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available ** publicly, only to user functions defined in func.c. */ case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); + if( pOp->p1 ){ + sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); + } break; } @@ -5356,6 +5363,7 @@ case OP_AggStep: { ctx.s.db = db; ctx.isError = 0; ctx.pColl = 0; + ctx.skipFlag = 0; if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); @@ -5367,6 +5375,11 @@ case OP_AggStep: { sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); rc = ctx.isError; } + if( ctx.skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); + } sqlite3VdbeMemRelease(&ctx.s); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index e201bcde79..f3f9f73a35 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -258,6 +258,7 @@ struct sqlite3_context { Mem *pMem; /* Memory cell used to store aggregate context */ int isError; /* Error code returned by the function. */ CollSeq *pColl; /* Collating sequence */ + int skipFlag; /* Skip skip accumulator loading if true */ }; /* diff --git a/test/e_select.test b/test/e_select.test index 39a74cc8d7..656bbd1b56 100644 --- a/test/e_select.test +++ b/test/e_select.test @@ -800,7 +800,7 @@ do_select_tests e_select-4.1 { 6 "SELECT count(*), * FROM z1" {6 63 born -26} 7 "SELECT max(a), * FROM z1" {63 63 born -26} - 8 "SELECT *, min(a) FROM z1" {63 born -26 -5} + 8 "SELECT *, min(a) FROM z1" {{} 67 quartets -5} 9 "SELECT *,* FROM z1,z2 LIMIT 1" { 51.65 -59.58 belfries {} 21 51.65 -59.58 belfries {} 21