aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan <Dan Kennedy>2024-05-24 18:31:39 +0000
committerdan <Dan Kennedy>2024-05-24 18:31:39 +0000
commit89b04f37864a3dcd30e2e2a6766eac5de3b51baa (patch)
tree7a7f86e2d1851f670b3376908002b4bcb8b79a3b
parent31079226f78a3011b9de6c310c2df3ce727fe883 (diff)
downloadsqlite-89b04f37864a3dcd30e2e2a6766eac5de3b51baa.tar.gz
sqlite-89b04f37864a3dcd30e2e2a6766eac5de3b51baa.zip
Ensure that queries like "SELECT indeterministic(a) FROM tbl GROUP BY 1" invoke the indeterministic function only once for each row of tbl.
FossilOrigin-Name: 4555d66547e28cb110e1012b145bcf3aafb5d4bde05e9d27bcb4ca33837b28f5
-rw-r--r--manifest23
-rw-r--r--manifest.uuid2
-rw-r--r--src/expr.c6
-rw-r--r--src/select.c14
-rw-r--r--src/sqliteInt.h1
-rw-r--r--test/distinct2.test23
6 files changed, 54 insertions, 15 deletions
diff --git a/manifest b/manifest
index 648a0b12d..3a1a67613 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\sstmtrand()\sextension\sfunction\sfor\suse\sin\stesting.
-D 2024-05-24T14:16:06.243
+C Ensure\sthat\squeries\slike\s"SELECT\sindeterministic(a)\sFROM\stbl\sGROUP\sBY\s1"\sinvoke\sthe\sindeterministic\sfunction\sonly\sonce\sfor\seach\srow\sof\stbl.
+D 2024-05-24T18:31:39.505
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -705,7 +705,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
-F src/expr.c 50e71ed518f1b1ba8401006922a309e200d205b2ca5b93d6fd8a006a336dbf67
+F src/expr.c 585109ab97149b2d484697e7469f28c91d495cd1330cc760d24711b7be8d22fb
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 852f93c0ef995e0c2b8983059a2b97151c194cc8259e21f5bc2b7ac508348c2a
F src/func.c f1f57c6863c1380f31ecf3d61732495bfff847a8e35a832c7e306e310db5a799
@@ -755,12 +755,12 @@ F src/printf.c 8b250972305e14b365561be5117ed0fd364e4fd58968776df1ce64c6280b90f9
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 22f1fa3423b377c02ae78d451cfeb1c2d96dcf0389c0642cbdcd19d3bfd7ae01
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c 1a841c38974d45cf15a7611398479182b61ad4c187423c380741d8b1688fe607
+F src/select.c cbdaf9cb2d9a697ee9ce1484f27d2e96762d33cc19259aedfb818a68b9d3be10
F src/shell.c.in 31249f26684467e95e529915bf486961c535ae8288ed7e79890cc9ed3d781d8f
F src/sqlite.h.in c71d9ef76a6d32dc7ff2d373f2e57ce09056af26c1457bcadae5358b7628c7c3
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h 6a9fa3902c9faca2b57060e822f2afadfbf96d64c4ede81e201f0e0c42d7e4aa
+F src/sqliteInt.h 98ba756789b37f8d8217407ce077c31faf0b9b21d593b327c2b9667ad5bea1ac
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -1074,7 +1074,7 @@ F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 691c9e850b0d0b56b66e7e235453198cb4cf0760e324b7403d3c5abbeab0a014
-F test/distinct2.test bb71cc7b5e58e895787f9910a788c254f679928d324732d063fe9bc202ecbe71
+F test/distinct2.test c936bb8652258c04bf066706284f5cd54ec693817399dbd6503c49d41ace626e
F test/distinctagg.test 40d7169ae5846caaf62c6e307d2ca3c333daf9b6f7cde888956a339a97afe85f
F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
@@ -2193,8 +2193,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b8442d2a6012b1f2e15381613267db0982e36bb4c748b15b56e668e0d0a3d0d2
-R 01f61db2371d56efe0fc89de21914b9a
-U drh
-Z 5bafe7bbe2cfe723081ab4c42a45e0a5
+P 5c97a5b9d163b1c427e002f3734687ca0384bc0da6a90fc4bfd358c654d3a7b3
+R 5fdf8e25d08374c3b6caf60dac9645e5
+T *branch * group-by-consistency
+T *sym-group-by-consistency *
+T -sym-trunk *
+U dan
+Z 5149149f75ab1db4d2d6bfcada9a5ce2
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 745372d9b..2a7f5c082 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-5c97a5b9d163b1c427e002f3734687ca0384bc0da6a90fc4bfd358c654d3a7b3 \ No newline at end of file
+4555d66547e28cb110e1012b145bcf3aafb5d4bde05e9d27bcb4ca33837b28f5 \ No newline at end of file
diff --git a/src/expr.c b/src/expr.c
index 7cd50e660..4bab38363 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -4243,7 +4243,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
** register iReg. The caller must ensure that iReg already contains
** the correct value for the expression.
*/
-static void exprToRegister(Expr *pExpr, int iReg){
+void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
p->op2 = p->op;
@@ -5252,7 +5252,7 @@ expr_code_doover:
break;
}
testcase( pX->op==TK_COLUMN );
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
testcase( regFree1==0 );
memset(&opCompare, 0, sizeof(opCompare));
opCompare.op = TK_EQ;
@@ -5602,7 +5602,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = pDel;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
diff --git a/src/select.c b/src/select.c
index 9278ea18b..9ff5c6c53 100644
--- a/src/select.c
+++ b/src/select.c
@@ -7847,12 +7847,18 @@ int sqlite3Select(
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+ && OptimizationEnabled(db, SQLITE_GroupByOrder)
#ifndef SQLITE_OMIT_WINDOWFUNC
&& p->pWin==0
#endif
){
p->selFlags &= ~SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+ if( pGroupBy ){
+ for(i=0; i<pGroupBy->nExpr; i++){
+ pGroupBy->a[i].u.x.iOrderByCol = i+1;
+ }
+ }
p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
@@ -8315,12 +8321,18 @@ int sqlite3Select(
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
+ int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
+
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
pAggInfo->directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
+
+ if( iOrderByCol ){
+ sqlite3ExprToRegister(p->pEList->a[iOrderByCol-1].pExpr, iAMem+j);
+ }
}
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
@@ -8336,9 +8348,9 @@ int sqlite3Select(
** and resets the aggregate accumulator registers in preparation
** for the next GROUP BY batch.
*/
- sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output one row"));
+ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
VdbeComment((v, "check abort flag"));
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d98a4f7f0..f4f8fc5e4 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -5025,6 +5025,7 @@ void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
+void sqlite3ExprToRegister(Expr *pExpr, int iReg);
void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
diff --git a/test/distinct2.test b/test/distinct2.test
index 958d9634f..ca88f5a28 100644
--- a/test/distinct2.test
+++ b/test/distinct2.test
@@ -313,4 +313,27 @@ do_execsql_test 4020 {
SELECT b FROM t1 UNION SELECT 1;
} {1 { }}
+#-------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 5010 {
+ CREATE TABLE cnt(a);
+ WITH RECURSIVE cnt2(x) AS (
+ VALUES(1) UNION ALL SELECT x+1 FROM cnt2 WHERE x<50
+ )
+ INSERT INTO cnt SELECT x FROM cnt2;
+}
+
+do_execsql_test 5020 {
+ SELECT DISTINCT abs(random())%5 AS r FROM cnt ORDER BY r;
+} {0 1 2 3 4}
+
+do_execsql_test 5030 {
+ SELECT abs(random())%5 AS r FROM cnt GROUP BY 1 ORDER BY 1;
+} {0 1 2 3 4}
+
+do_execsql_test 5040 {
+ SELECT a FROM cnt WHERE a>45 GROUP BY 1;
+} {46 47 48 49 50}
+
finish_test