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

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
This commit is contained in:
drh
2012-02-02 17:35:43 +00:00
parent a451017d62
commit 7a95789c0c
7 changed files with 50 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
C Data\sstructure\scleanup.\s\sRemove\sunused\sfields.\s\sRearrange\sother\sfiles\sfor\ntighter\spacking\sand\sreduced\smemory\susage. 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-02T15:50:17.008 D 2012-02-02T17:35:43.157
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34 F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -137,7 +137,7 @@ F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112
F src/expr.c 00675123e0beec98f999aa4594d2cbe1fec33c1b F src/expr.c 00675123e0beec98f999aa4594d2cbe1fec33c1b
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9 F src/func.c f66c87956c9afc098e1b74612d3c2b38760a41dc
F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
@@ -180,7 +180,7 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c b6eec9d11ec5df0d1fd11e8a0eed0fc2d2d96b25 F src/select.c 232283a2e60d91cbd9a5ddf2f6f7ecf53d590075
F src/shell.c 60d147c2411dd2d79a5151cfb9a068de87c7babe F src/shell.c 60d147c2411dd2d79a5151cfb9a068de87c7babe
F src/sqlite.h.in 371c30e4be94b9b0ea6400ed66663fcf8e891eb4 F src/sqlite.h.in 371c30e4be94b9b0ea6400ed66663fcf8e891eb4
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
@@ -240,9 +240,9 @@ F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
F src/util.c 9e07bd67dfafe9c75b1da78c87ba030cebbb5388 F src/util.c 9e07bd67dfafe9c75b1da78c87ba030cebbb5388
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
F src/vdbe.c 43ea77c83e7f35169328f13b20cc8140bd2cf473 F src/vdbe.c 40b14dff04692b1ee421db40c67d4921ecf17a9d
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
F src/vdbeInt.h 2e79ce66ff45a01411151957bb2899af680f1560 F src/vdbeInt.h 0f986e86a4a0afbf52d0402071708f487d1cfc15
F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91 F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91
F src/vdbeaux.c 7683d772ad638faa4567142438c4594e47f173c4 F src/vdbeaux.c 7683d772ad638faa4567142438c4594e47f173c4
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
@@ -386,7 +386,7 @@ F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 234242b71855af8e8a9b1e141c3533f6d43d8645 F test/e_insert.test 234242b71855af8e8a9b1e141c3533f6d43d8645
F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216 F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6 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_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
F test/e_update.test dba988a4d079156549a40854074ba4890b0a4577 F test/e_update.test dba988a4d079156549a40854074ba4890b0a4577
F test/e_uri.test 6f35b491f80dac005c8144f38b2dfb4d96483596 F test/e_uri.test 6f35b491f80dac005c8144f38b2dfb4d96483596
@@ -988,7 +988,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P 25df2a7458d025bc00380b4a0893637639f9f0d4 P 0bc594e861ae1142e8c6c83f39b095e1432856bf
R d2ba4c243c1dae496337618e0657e24d R eff167ee91b10474f283fe35279e92e9
T *branch * output-minmax-row
T *sym-output-minmax-row *
T -sym-trunk *
U drh U drh
Z ada6e2e4fcf7ab0bc8362d130037dce6 Z cf65185cbe7093f978d4a185698ec6ea

View File

@@ -1 +1 @@
0bc594e861ae1142e8c6c83f39b095e1432856bf adb29232b659c5332b6841776372407fcc350b08

View File

@@ -28,6 +28,14 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
return context->pColl; 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 ** Implementation of the non-aggregate min() and max() functions
*/ */
@@ -1354,6 +1362,8 @@ static void minmaxStep(
cmp = sqlite3MemCompare(pBest, pArg, pColl); cmp = sqlite3MemCompare(pBest, pArg, pColl);
if( (max && cmp<0) || (!max && cmp>0) ){ if( (max && cmp<0) || (!max && cmp>0) ){
sqlite3VdbeMemCopy(pBest, pArg); sqlite3VdbeMemCopy(pBest, pArg);
}else{
sqlite3SkipAccumulatorLoad(context);
} }
}else{ }else{
sqlite3VdbeMemCopy(pBest, pArg); sqlite3VdbeMemCopy(pBest, pArg);

View File

@@ -3596,6 +3596,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
int i; int i;
int regHit = 0;
int addrHitTest = 0;
struct AggInfo_func *pF; struct AggInfo_func *pF;
struct AggInfo_col *pC; struct AggInfo_col *pC;
@@ -3631,7 +3633,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( !pColl ){ if( !pColl ){
pColl = pParse->db->pDfltColl; 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, sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
(void*)pF->pFunc, P4_FUNCDEF); (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 ** Another solution would be to change the OP_SCopy used to copy cached
** values to an OP_Copy. ** values to an OP_Copy.
*/ */
if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit);
}
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
} }
pAggInfo->directMode = 0; pAggInfo->directMode = 0;
sqlite3ExprCacheClear(pParse); sqlite3ExprCacheClear(pParse);
if( addrHitTest ){
sqlite3VdbeJumpHere(v, addrHitTest);
}
} }
/* /*

View File

@@ -1331,19 +1331,26 @@ arithmetic_result_is_null:
break; break;
} }
/* Opcode: CollSeq * * P4 /* Opcode: CollSeq P1 * * P4
** **
** P4 is a pointer to a CollSeq struct. If the next call to a user function ** P4 is a pointer to a CollSeq struct. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif() ** be returned. This is used by the built-in min(), max() and nullif()
** functions. ** 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 ** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available ** to retrieve the collation sequence set by this opcode is not available
** publicly, only to user functions defined in func.c. ** publicly, only to user functions defined in func.c.
*/ */
case OP_CollSeq: { case OP_CollSeq: {
assert( pOp->p4type==P4_COLLSEQ ); assert( pOp->p4type==P4_COLLSEQ );
if( pOp->p1 ){
sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
}
break; break;
} }
@@ -5356,6 +5363,7 @@ case OP_AggStep: {
ctx.s.db = db; ctx.s.db = db;
ctx.isError = 0; ctx.isError = 0;
ctx.pColl = 0; ctx.pColl = 0;
ctx.skipFlag = 0;
if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>p->aOp ); assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].p4type==P4_COLLSEQ );
@@ -5367,6 +5375,11 @@ case OP_AggStep: {
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
rc = ctx.isError; 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); sqlite3VdbeMemRelease(&ctx.s);

View File

@@ -258,6 +258,7 @@ struct sqlite3_context {
Mem *pMem; /* Memory cell used to store aggregate context */ Mem *pMem; /* Memory cell used to store aggregate context */
int isError; /* Error code returned by the function. */ int isError; /* Error code returned by the function. */
CollSeq *pColl; /* Collating sequence */ CollSeq *pColl; /* Collating sequence */
int skipFlag; /* Skip skip accumulator loading if true */
}; };
/* /*

View File

@@ -800,7 +800,7 @@ do_select_tests e_select-4.1 {
6 "SELECT count(*), * FROM z1" {6 63 born -26} 6 "SELECT count(*), * FROM z1" {6 63 born -26}
7 "SELECT max(a), * FROM z1" {63 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" { 9 "SELECT *,* FROM z1,z2 LIMIT 1" {
51.65 -59.58 belfries {} 21 51.65 -59.58 belfries {} 21 51.65 -59.58 belfries {} 21 51.65 -59.58 belfries {} 21