]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
For queries of the form "SELECT p, max(q) FROM t1", the value of column p
authordrh <drh@noemail.net>
Thu, 2 Feb 2012 17:35:43 +0000 (17:35 +0000)
committerdrh <drh@noemail.net>
Thu, 2 Feb 2012 17:35:43 +0000 (17:35 +0000)
returned is the one on the same row that holds the maximum value of q.

FossilOrigin-Name: adb29232b659c5332b6841776372407fcc350b08

manifest
manifest.uuid
src/func.c
src/select.c
src/vdbe.c
src/vdbeInt.h
test/e_select.test

index a02f0e5e2c3a7190aae9a0135c17613f32281907..c28861e94cd8cc292651f8a6016711221714b3cc 100644 (file)
--- 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
index 3536af2979f1e8a5320305bb1458e9ed2c8afa8d..e33d5dd10693fbc5bc156ce0b4e610483fb0da2a 100644 (file)
@@ -1 +1 @@
-0bc594e861ae1142e8c6c83f39b095e1432856bf
\ No newline at end of file
+adb29232b659c5332b6841776372407fcc350b08
\ No newline at end of file
index 3a1879ca6949f0cd5c37dd2f46d0b178cb4f93d0..deddd5375b37eee273f42a60b4ad2c0214ab0246 100644 (file)
@@ -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);
index 6fcb37f70d729d858a6db15f966d9aa47c339857..bbdc4e3c5584c6e838e0d61958c46b65bd30958c 100644 (file)
@@ -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; i<pAggInfo->nAccumulator; i++, pC++){
     sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
   }
   pAggInfo->directMode = 0;
   sqlite3ExprCacheClear(pParse);
+  if( addrHitTest ){
+    sqlite3VdbeJumpHere(v, addrHitTest);
+  }
 }
 
 /*
index 111d5b52bb68de5c63cbe99abed95830152cf29f..9ce25942dd25bfa3fea719d8b59fac7e9f7af0fb 100644 (file)
@@ -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);
 
index e201bcde7924461a1300396f877bd032387271bc..f3f9f73a35561678df4b080f0b0ae4efafa798b6 100644 (file)
@@ -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 */
 };
 
 /*
index 39a74cc8d71372716b7e49b625976fb65a0026b9..656bbd1b5670b9ee3ed200c4bd976fe6215a6134 100644 (file)
@@ -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