/ Check-in [70c6739f]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 70c6739f4e84b3433e14960346b54d0e9e0bb9c6
User & Date: drh 2008-06-18 15:34:10
Context
2008-06-18
17:09
Implement the 'CONFIG_SINGLETHREAD' and 'CONFIG_MULTITHREAD' configuration modes. (CVS 5234) check-in: 5059644c 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: 70c6739f user: drh tags: trunk
13:47
Add documentation on the sqlite3_mutex_methods object. (CVS 5232) check-in: c3c7bfc9 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.193 2008/06/15 02:51:47 drh Exp $
           19  +** $Id: func.c,v 1.194 2008/06/18 15:34:10 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   #include <ctype.h>
    23     23   #include <stdlib.h>
    24     24   #include <assert.h>
    25     25   #include "vdbeInt.h"
    26     26   
................................................................................
  1162   1162     sqlite3_context *context,
  1163   1163     int argc,
  1164   1164     sqlite3_value **argv
  1165   1165   ){
  1166   1166     const char *zVal;
  1167   1167     StrAccum *pAccum;
  1168   1168     const char *zSep;
  1169         -  int nVal, nSep;
  1170         -  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
         1169  +  int nVal, nSep, i;
         1170  +  if( argc==0 || sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  1171   1171     pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
  1172   1172   
  1173   1173     if( pAccum ){
  1174   1174       sqlite3 *db = sqlite3_context_db_handle(context);
  1175   1175       pAccum->useMalloc = 1;
  1176   1176       pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
  1177   1177       if( pAccum->nChar ){
  1178         -      if( argc==2 ){
  1179         -        zSep = (char*)sqlite3_value_text(argv[1]);
  1180         -        nSep = sqlite3_value_bytes(argv[1]);
         1178  +      if( argc>1 ){
         1179  +        zSep = (char*)sqlite3_value_text(argv[argc-1]);
         1180  +        nSep = sqlite3_value_bytes(argv[argc-1]);
  1181   1181         }else{
  1182   1182           zSep = ",";
  1183   1183           nSep = 1;
  1184   1184         }
  1185   1185         sqlite3StrAccumAppend(pAccum, zSep, nSep);
  1186   1186       }
  1187         -    zVal = (char*)sqlite3_value_text(argv[0]);
  1188         -    nVal = sqlite3_value_bytes(argv[0]);
  1189         -    sqlite3StrAccumAppend(pAccum, zVal, nVal);
         1187  +    i = 0;
         1188  +    do{
         1189  +      zVal = (char*)sqlite3_value_text(argv[i]);
         1190  +      nVal = sqlite3_value_bytes(argv[i]);
         1191  +      sqlite3StrAccumAppend(pAccum, zVal, nVal);
         1192  +      i++;
         1193  +    }while( i<argc-1 );
  1190   1194     }
  1191   1195   }
  1192   1196   static void groupConcatFinalize(sqlite3_context *context){
  1193   1197     StrAccum *pAccum;
  1194   1198     pAccum = sqlite3_aggregate_context(context, 0);
  1195   1199     if( pAccum ){
  1196   1200       if( pAccum->tooBig ){
................................................................................
  1271   1275       { "min",    1, 0, 1, minmaxStep,   minMaxFinalize },
  1272   1276       { "max",    1, 1, 1, minmaxStep,   minMaxFinalize },
  1273   1277       { "sum",    1, 0, 0, sumStep,      sumFinalize    },
  1274   1278       { "total",  1, 0, 0, sumStep,      totalFinalize    },
  1275   1279       { "avg",    1, 0, 0, sumStep,      avgFinalize    },
  1276   1280       { "count",  0, 0, 0, countStep,    countFinalize  },
  1277   1281       { "count",  1, 0, 0, countStep,    countFinalize  },
  1278         -    { "group_concat", 1, 0, 0, groupConcatStep, groupConcatFinalize },
  1279         -    { "group_concat", 2, 0, 0, groupConcatStep, groupConcatFinalize },
         1282  +    { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
  1280   1283     };
  1281   1284     int i;
  1282   1285   
  1283   1286     for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
  1284   1287       void *pArg;
  1285   1288       u8 argType = aFuncs[i].argType;
  1286   1289       pArg = (void*)(int)argType;

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.387 2008/06/15 02:51:48 drh Exp $
           17  +** $Id: vdbeaux.c,v 1.388 2008/06/18 15:34:10 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   
    24     24   
................................................................................
   266    266     Op *pOp;
   267    267     int *aLabel = p->aLabel;
   268    268     int doesStatementRollback = 0;
   269    269     int hasStatementBegin = 0;
   270    270     for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
   271    271       u8 opcode = pOp->opcode;
   272    272   
   273         -    if( opcode==OP_Function ){
          273  +    if( opcode==OP_Function || opcode==OP_AggStep ){
   274    274         if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
   275         -    }else if( opcode==OP_AggStep 
   276    275   #ifndef SQLITE_OMIT_VIRTUALTABLE
   277         -        || opcode==OP_VUpdate
   278         -#endif
   279         -    ){
          276  +    }else if( opcode==OP_VUpdate ){
   280    277         if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
   281    278       }
          279  +#endif
   282    280       if( opcode==OP_Halt ){
   283    281         if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
   284    282           doesStatementRollback = 1;
   285    283         }
   286    284       }else if( opcode==OP_Statement ){
   287    285         hasStatementBegin = 1;
   288    286       }else if( opcode==OP_Destroy ){

Changes to test/func.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing built-in functions.
    13     13   #
    14         -# $Id: func.test,v 1.78 2008/04/16 12:58:54 drh Exp $
           14  +# $Id: func.test,v 1.79 2008/06/18 15:34:10 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a table to work with.
    20     20   #
    21     21   do_test func-0.0 {
................................................................................
   925    925     }
   926    926   } {thisprogramisfreesoftware}
   927    927   do_test func-24.6 {
   928    928     execsql {
   929    929       SELECT 'BEGIN-'||group_concat(t1) FROM tbl1
   930    930     }
   931    931   } {BEGIN-this,program,is,free,software}
          932  +set midargs {}
          933  +set midres {}
          934  +for {set i 1} {$i<[sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1]-1} {incr i} {
          935  +  append midargs ,'/$i'
          936  +  append midres /$i
          937  +  set result \
          938  +     "this$midres:program$midres:is$midres:free$midres:software$midres"
          939  +  set sql "SELECT group_concat(t1$midargs,':') FROM tbl1"
          940  +  do_test func-24.7.$i {
          941  +     db eval $::sql
          942  +  } $result
          943  +}
   932    944   
   933    945   # Use the test_isolation function to make sure that type conversions
   934    946   # on function arguments do not effect subsequent arguments.
   935    947   #
   936    948   do_test func-25.1 {
   937    949     execsql {SELECT test_isolation(t1,t1) FROM tbl1}
   938    950   } {this program is free software}
   939    951   
   940    952   finish_test