aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/func.c44
-rw-r--r--src/sqliteInt.h4
2 files changed, 35 insertions, 13 deletions
diff --git a/src/func.c b/src/func.c
index e82652011..62a545e3d 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1665,7 +1665,7 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
- int firstTerm = pAccum->mxAlloc==0;
+ int firstTerm = pAccum->nChar==0;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
@@ -1682,6 +1682,29 @@ static void groupConcatStep(
if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
}
}
+static void groupConcatInverse(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n;
+ assert( argc==1 || argc==2 );
+ StrAccum *pAccum;
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
+ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
+ if( pAccum ){
+ n = sqlite3_value_bytes(argv[0]);
+ if( argc==2 ){
+ n += sqlite3_value_bytes(argv[1]);
+ }
+ if( n>=pAccum->nChar ){
+ pAccum->nChar = 0;
+ }else{
+ pAccum->nChar -= n;
+ memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
+ }
+ }
+}
static void groupConcatFinalize(sqlite3_context *context){
StrAccum *pAccum;
pAccum = sqlite3_aggregate_context(context, 0);
@@ -1894,16 +1917,15 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
- WAGGREGATE(sum, 1, 0, 0, sumStep, sumInverse, sumFinalize),
- WAGGREGATE(total, 1, 0, 0, sumStep, sumInverse, totalFinalize ),
- WAGGREGATE(avg, 1, 0, 0, sumStep, sumInverse, avgFinalize ),
- AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
- SQLITE_FUNC_COUNT ),
- WAGGREGATE(count, 1, 0, 0, countStep, 0, countFinalize ),
- AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize,
- groupConcatValue),
- AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize,
- groupConcatValue),
+ WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse),
+ WAGGREGATE(total, 1,0,0, sumStep, totalFinalize, totalFinalize, sumInverse),
+ WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse),
+ AGGREGATE2(count, 0,0,0, countStep, countFinalize, SQLITE_FUNC_COUNT ),
+ WAGGREGATE(count, 1,0,0, countStep, countFinalize, 0, 0 ),
+ WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
+ groupConcatFinalize, groupConcatValue, groupConcatInverse),
+ WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
+ groupConcatFinalize, groupConcatValue, groupConcatInverse),
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index e3c3c17ca..d69b569f6 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1725,9 +1725,9 @@ struct FuncDestructor {
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
-#define WAGGREGATE(zName, nArg, arg, nc, xStep, xInverse, xFinal) \
+#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,xInverse,#zName, {0}}
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
/*
** All current savepoints are stored in a linked list starting at