/ Check-in [f2ae82c4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Make group_concat() a 1- or 2-value function, as the documentation says it should be. Use the md5sum() function to verify ticket #3179, not group_concat(). This undoes the ill-advised group_concat() change of check-in (5233). (CVS 6233)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f2ae82c4d46c2eca30fc60a50ab5064728f20739
User & Date: drh 2009-02-02 21:57:05
Context
2009-02-03
13:10
Check-in (6230) introduced a bugs in SUBSTR() which was caught by the fuzz tester. Fixed by this check-in. Related to ticket #3628. (CVS 6234) check-in: cd2e7f6c user: drh tags: trunk
2009-02-02
21:57
Make group_concat() a 1- or 2-value function, as the documentation says it should be. Use the md5sum() function to verify ticket #3179, not group_concat(). This undoes the ill-advised group_concat() change of check-in (5233). (CVS 6233) check-in: f2ae82c4 user: drh tags: trunk
18:03
Omit the TEMP keyword from the schema of TEMP tables created using CREATE TEMP TABLE AS SELECT ..... Ticket #3630. (CVS 6232) check-in: 3b0a2554 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1209
1210
1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
....
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
** 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.217 2009/02/02 17:30:00 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"

/*
................................................................................
  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 ){
................................................................................
    FUNCTION(load_extension,     2, 0, 0, loadExt          ),
  #endif
    AGGREGATE(sum,               1, 0, 0, sumStep,         sumFinalize    ),
    AGGREGATE(total,             1, 0, 0, sumStep,         totalFinalize    ),
    AGGREGATE(avg,               1, 0, 0, sumStep,         avgFinalize    ),
    AGGREGATE(count,             0, 0, 0, countStep,       countFinalize  ),
    AGGREGATE(count,             1, 0, 0, countStep,       countFinalize  ),
    AGGREGATE(group_concat,     -1, 0, 0, groupConcatStep, groupConcatFinalize),

  
    LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #ifdef SQLITE_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),







|







 







|
>
|







|
|
|






<
<
|
|
|
<
<







 







|
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234


1235
1236
1237


1238
1239
1240
1241
1242
1243
1244
....
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
** 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.218 2009/02/02 21:57:05 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"

/*
................................................................................
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zVal;
  StrAccum *pAccum;
  const char *zSep;
  int nVal, nSep;
  assert( argc==1 || argc==2 );
  if( 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==2 ){
        zSep = (char*)sqlite3_value_text(argv[1]);
        nSep = sqlite3_value_bytes(argv[1]);
      }else{
        zSep = ",";
        nSep = 1;
      }
      sqlite3StrAccumAppend(pAccum, zSep, nSep);
    }


    zVal = (char*)sqlite3_value_text(argv[0]);
    nVal = sqlite3_value_bytes(argv[0]);
    sqlite3StrAccumAppend(pAccum, zVal, nVal);


  }
}
static void groupConcatFinalize(sqlite3_context *context){
  StrAccum *pAccum;
  pAccum = sqlite3_aggregate_context(context, 0);
  if( pAccum ){
    if( pAccum->tooBig ){
................................................................................
    FUNCTION(load_extension,     2, 0, 0, loadExt          ),
  #endif
    AGGREGATE(sum,               1, 0, 0, sumStep,         sumFinalize    ),
    AGGREGATE(total,             1, 0, 0, sumStep,         totalFinalize    ),
    AGGREGATE(avg,               1, 0, 0, sumStep,         avgFinalize    ),
    AGGREGATE(count,             0, 0, 0, countStep,       countFinalize  ),
    AGGREGATE(count,             1, 0, 0, countStep,       countFinalize  ),
    AGGREGATE(group_concat,      1, 0, 0, groupConcatStep, groupConcatFinalize),
    AGGREGATE(group_concat,      2, 0, 0, groupConcatStep, groupConcatFinalize),
  
    LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #ifdef SQLITE_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),

Changes to test/func.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
955
956
957
958
959
960
961





962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
#    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.89 2009/02/01 18:08:41 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
  }
} {thisprogramisfreesoftware}
do_test func-24.6 {
  execsql {
    SELECT 'BEGIN-'||group_concat(t1) FROM tbl1
  }
} {BEGIN-this,program,is,free,software}





unset -nocomplain midargs
set midargs {}
unset -nocomplain midres
set midres {}
unset -nocomplain result
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.







|







 







>
>
>
>
>





|


|
|
|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
#    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.90 2009/02/02 21:57:05 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
  }
} {thisprogramisfreesoftware}
do_test func-24.6 {
  execsql {
    SELECT 'BEGIN-'||group_concat(t1) FROM tbl1
  }
} {BEGIN-this,program,is,free,software}

# Ticket #3179:  Make sure aggregate functions can take many arguments.
# None of the built-in aggregates do this, so use the md5sum() from the
# test extensions.
#
unset -nocomplain midargs
set midargs {}
unset -nocomplain midres
set midres {}
unset -nocomplain result
for {set i 1} {$i<[sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1]} {incr i} {
  append midargs ,'/$i'
  append midres /$i
  set result [md5 \
     "this${midres}program${midres}is${midres}free${midres}software${midres}"]
  set sql "SELECT md5sum(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.