diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 44 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 |
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 |