Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make sure aggregate functions can take any number of arguments up to the limit imposed by SQLITE_LIMIT_FUNCTION_ARGS. Ticket #3179. Modify the group_concat() function to take an unlimited number of arguments in order to facilitate testing this behavior. (CVS 5233) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
70c6739f4e84b3433e14960346b54d0e |
User & Date: | drh 2008-06-18 15:34:10.000 |
Context
2008-06-18
| ||
17:09 | Implement the 'CONFIG_SINGLETHREAD' and 'CONFIG_MULTITHREAD' configuration modes. (CVS 5234) (check-in: 5059644c4b user: danielk1977 tags: trunk) | |
15:34 | Make sure aggregate functions can take any number of arguments up to the limit imposed by SQLITE_LIMIT_FUNCTION_ARGS. Ticket #3179. Modify the group_concat() function to take an unlimited number of arguments in order to facilitate testing this behavior. (CVS 5233) (check-in: 70c6739f4e user: drh tags: trunk) | |
13:47 | Add documentation on the sqlite3_mutex_methods object. (CVS 5232) (check-in: c3c7bfc9db user: drh tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.194 2008/06/18 15:34:10 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 | sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zVal; StrAccum *pAccum; const char *zSep; | | | | | | > > | | | > > | 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 | sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zVal; StrAccum *pAccum; const char *zSep; int nVal, nSep, i; if( argc==0 || sqlite3_value_type(argv[0])==SQLITE_NULL ) return; pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); pAccum->useMalloc = 1; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( pAccum->nChar ){ if( argc>1 ){ zSep = (char*)sqlite3_value_text(argv[argc-1]); nSep = sqlite3_value_bytes(argv[argc-1]); }else{ zSep = ","; nSep = 1; } sqlite3StrAccumAppend(pAccum, zSep, nSep); } i = 0; do{ zVal = (char*)sqlite3_value_text(argv[i]); nVal = sqlite3_value_bytes(argv[i]); sqlite3StrAccumAppend(pAccum, zVal, nVal); i++; }while( i<argc-1 ); } } static void groupConcatFinalize(sqlite3_context *context){ StrAccum *pAccum; pAccum = sqlite3_aggregate_context(context, 0); if( pAccum ){ if( pAccum->tooBig ){ |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 1, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, | | < | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 1, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize }, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ void *pArg; u8 argType = aFuncs[i].argType; pArg = (void*)(int)argType; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** ** $Id: vdbeaux.c,v 1.388 2008/06/18 15:34:10 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" |
︙ | ︙ | |||
266 267 268 269 270 271 272 | Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; | | < | < < > | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; if( opcode==OP_Function || opcode==OP_AggStep ){ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( opcode==OP_VUpdate ){ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; } #endif if( opcode==OP_Halt ){ if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){ doesStatementRollback = 1; } }else if( opcode==OP_Statement ){ hasStatementBegin = 1; }else if( opcode==OP_Destroy ){ |
︙ | ︙ |
Changes to test/func.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # 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 built-in functions. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # 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 built-in functions. # # $Id: func.test,v 1.79 2008/06/18 15:34:10 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table to work with. # do_test func-0.0 { |
︙ | ︙ | |||
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | } } {thisprogramisfreesoftware} do_test func-24.6 { execsql { SELECT 'BEGIN-'||group_concat(t1) FROM tbl1 } } {BEGIN-this,program,is,free,software} # Use the test_isolation function to make sure that type conversions # on function arguments do not effect subsequent arguments. # do_test func-25.1 { execsql {SELECT test_isolation(t1,t1) FROM tbl1} } {this program is free software} finish_test | > > > > > > > > > > > > | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 | } } {thisprogramisfreesoftware} do_test func-24.6 { execsql { SELECT 'BEGIN-'||group_concat(t1) FROM tbl1 } } {BEGIN-this,program,is,free,software} set midargs {} set midres {} for {set i 1} {$i<[sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1]-1} {incr i} { append midargs ,'/$i' append midres /$i set result \ "this$midres:program$midres:is$midres:free$midres:software$midres" set sql "SELECT group_concat(t1$midargs,':') FROM tbl1" do_test func-24.7.$i { db eval $::sql } $result } # Use the test_isolation function to make sure that type conversions # on function arguments do not effect subsequent arguments. # do_test func-25.1 { execsql {SELECT test_isolation(t1,t1) FROM tbl1} } {this program is free software} finish_test |