Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add VM code comments on the group-by processing. Extra group-by test case. (CVS 2731) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
655e75ac7d96b05c118226c5b70443da |
User & Date: | drh 2005-09-20 18:13:24.000 |
Context
2005-09-22
| ||
15:45 | Optionally call fdatasync() instead of fsync() only if _POSIX_SYNCHRONIZED_IO is positive, which should only be the case on operating systems that actually support fdatasync(). (CVS 2732) (check-in: a9b341dccf user: drh tags: trunk) | |
2005-09-20
| ||
18:13 | Add VM code comments on the group-by processing. Extra group-by test case. (CVS 2731) (check-in: 655e75ac7d user: drh tags: trunk) | |
17:42 | Code cleanup and simplification. Three new Mem opcodes added. The sqlite3VdbeJumpHere function added. (CVS 2730) (check-in: 2471957fee user: drh tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.276 2005/09/20 18:13:24 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
2911 2912 2913 2914 2915 2916 2917 2918 | iUseFlag = pParse->nMem++; iAbortFlag = pParse->nMem++; iAMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; iBMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag); sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag); | > < > | > > > | 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 | iUseFlag = pParse->nMem++; iAbortFlag = pParse->nMem++; iAMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; iBMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag); VdbeComment((v, "# clear abort flag")); sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag); VdbeComment((v, "# indicate accumulator empty")); sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop); /* Generate a subroutine that outputs a single row of the result ** set. This subroutine first looks at the iUseFlag. If iUseFlag ** is less than or equal to zero, the subroutine is a no-op. If ** the processing calls for the query to abort, this subroutine ** increments the iAbortFlag memory location before returning in ** order to signal the caller to abort. */ addrSetAbort = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag); VdbeComment((v, "# set abort flag")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); VdbeComment((v, "# Groupby result generator entry point")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); } rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, distinct, eDest, iParm, addrOutputRow+1, addrSetAbort, aff); if( rc ){ goto select_end; } sqlite3VdbeAddOp(v, OP_Return, 0, 0); VdbeComment((v, "# end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ addrReset = sqlite3VdbeCurrentAddr(v); resetAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp(v, OP_Return, 0, 0); |
︙ | ︙ | |||
2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 | } j++; } sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); sAggInfo.useSortingIdx = 1; } /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... | > | 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 | } j++; } sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); VdbeComment((v, "# GROUP BY sort")); sAggInfo.useSortingIdx = 1; } /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... |
︙ | ︙ | |||
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 | ** for the next GROUP BY batch. */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; j<pGroupBy->nExpr; j++){ sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j); } sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); /* Update the aggregate accumulators based on the content of ** the current row */ sqlite3VdbeResolveLabel(v, addrProcessRow); updateAccumulator(pParse, &sAggInfo); | > > > | > > | 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 | ** for the next GROUP BY batch. */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; j<pGroupBy->nExpr; j++){ sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j); } sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); VdbeComment((v, "# output one row")); sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); VdbeComment((v, "# check abort flag")); sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); VdbeComment((v, "# reset accumulator")); /* Update the aggregate accumulators based on the content of ** the current row */ sqlite3VdbeResolveLabel(v, addrProcessRow); updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag); VdbeComment((v, "# indicate data in accumulator")); /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); }else{ sqlite3WhereEnd(pWInfo); uncreateSortingIndex(pParse, addrSortingIdx); } /* Output the final row of result */ sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); VdbeComment((v, "# output final row")); } /* endif pGroupBy */ else { /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ |
︙ | ︙ |
Changes to test/select5.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing aggregate functions and the # GROUP BY and HAVING clauses of SELECT statements. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing aggregate functions and the # GROUP BY and HAVING clauses of SELECT statements. # # $Id: select5.test,v 1.15 2005/09/20 18:13:25 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Build some test data # execsql { |
︙ | ︙ | |||
164 165 166 167 168 169 170 | CREATE TABLE t3(x,y); INSERT INTO t3 VALUES(1,NULL); INSERT INTO t3 VALUES(2,NULL); INSERT INTO t3 VALUES(3,4); SELECT count(x), y FROM t3 GROUP BY y ORDER BY 1 } } {1 4 2 {}} | > > > > > > > > > > > > | > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | CREATE TABLE t3(x,y); INSERT INTO t3 VALUES(1,NULL); INSERT INTO t3 VALUES(2,NULL); INSERT INTO t3 VALUES(3,4); SELECT count(x), y FROM t3 GROUP BY y ORDER BY 1 } } {1 4 2 {}} do_test select5-6.2 { execsql { CREATE TABLE t4(x,y,z); INSERT INTO t4 VALUES(1,2,NULL); INSERT INTO t4 VALUES(2,3,NULL); INSERT INTO t4 VALUES(3,NULL,5); INSERT INTO t4 VALUES(4,NULL,6); INSERT INTO t4 VALUES(4,NULL,6); INSERT INTO t4 VALUES(5,NULL,NULL); INSERT INTO t4 VALUES(5,NULL,NULL); INSERT INTO t4 VALUES(6,7,8); SELECT max(x), count(x), y, z FROM t4 GROUP BY y, z ORDER BY 1 } } {1 1 2 {} 2 1 3 {} 3 1 {} 5 4 2 {} 6 5 2 {} {} 6 1 7 8} finish_test |