Fixes to allow group_concat() to be used as a window function.

FossilOrigin-Name: 89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
This commit is contained in:
dan 2018-06-08 11:45:28 +00:00
parent 07509f8c1e
commit 03854d2ecc
9 changed files with 489 additions and 26 deletions

View File

@ -1,5 +1,5 @@
C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
D 2018-06-07T20:35:28.263
C Fixes\sto\sallow\sgroup_concat()\sto\sbe\sused\sas\sa\swindow\sfunction.
D 2018-06-08T11:45:28.408
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@ -450,7 +450,7 @@ F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
F src/expr.c 7c8880478dfacabff1c3e405fa11dc37e1e244a81bf6d175faecf36adb705ef0
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
F src/func.c 4bee7609e4a736554d3d29db9ced9f4aacb1c81ab1c19e1d02451c647afa692b
F src/func.c 3e8a85f9bfc9117964523a5e17bdbc4b0b9d707830871cbc1dc44b9b538d5d82
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
@ -500,7 +500,7 @@ F src/shell.c.in 4d0ddf10c403710d241bf920163dcf032c21119aebb61e70840942c0eafecdf
F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
F src/sqliteInt.h 7a9f462bffcfd4437982d9a0e6d557e0119fe2b7306c66b4ce1f8bc0e86587c7
F src/sqliteInt.h 94322676f8b66faaeb21ad9bb2b60585ef72320b8e3c5df6f307a06dd231c62a
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@ -1150,7 +1150,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 10793f1de89a226fa22dde9ba9398de22571fee1bfb53a935a11be4aa014704f
F test/pg_common.tcl 2562ad568cfaed67002f6cd9d1de3bc9d38eac99bb09acae3cdf92f8877f1a45
F test/pg_common.tcl b50727fe1ee3369d0421eadea2c2fd247bfb9d89a8e06ececf2f6866de17abd8
F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
@ -1620,10 +1620,10 @@ F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 905fe0842eacfd61e2f30ef7b0a84a7325ffa5cbbcd717ca30f25a142c3bca90
F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fba1b
F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
F test/window3.tcl 8fdcd16a6de3e0ccc1c6f218268ba202d2f74f640e66b3cc624aeee6f2f8653b
F test/window3.test 30da147abfe6b7e3f54b2902ccfa551966a46f3875154106c9ee34d5fa2ac455
F test/window4.tcl 46f5d6adb4c8ad48508f28488586450a7ae010bac654ee871605f3c2217d910f
F test/window4.test aab06a0a1be4cd9cf4ca015d04b072c9164aca508410e6ac01e2e389fa73b830
F test/window3.tcl f2596e9d6bf8d4441eb7a0d3272594185c3b56e8d2413a54b12e6e7557517674
F test/window3.test e43a143131e19a27148215431cf7cec8815c32c7ec04f1cf79d068adff9be028
F test/window4.tcl 9e5698ffb729676b88290a7048ae9bb9b0d31efe0b630e51f9ce796cca737f8c
F test/window4.test 316bf0844fa4966488b3c9d2e69a360f5b4de87022ca44f5a96a62243d9db796
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
@ -1740,7 +1740,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P ef34207073c21ce8618486777671ae78d23f290acd6d3c37e91a49b69cb506ac 09fffbdf9f2f6ce31a22d5a6df7a45f19a16628da622f12d6e33171cce09fb21
R 6c2ae8ade7aa49d26d158d84b6d725cd
P 251022034219819a1dc356542770ff46e3147a080f072eb20af6106771dadd92
R 71ea60b8da4fc9afa69db85d8c7f3e3f
U dan
Z 10ebbb803780df16eda225e4dabc5af4
Z 1cc277689f8095fe42a1da64c8288583

View File

@ -1 +1 @@
251022034219819a1dc356542770ff46e3147a080f072eb20af6106771dadd92
89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a

View File

@ -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

View File

@ -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

View File

@ -60,6 +60,7 @@ proc execsql {sql} {
proc execsql_test {tn sql} {
set res [execsql $sql]
set sql [string map {string_agg group_concat} $sql]
puts $::fd "do_execsql_test $tn {"
puts $::fd " [string trim $sql]"
puts $::fd "} {$res}"

View File

@ -280,6 +280,26 @@ foreach {tn window} {
execsql_test 1.$tn.13.6 "
SELECT lag(b,b) OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
"
execsql_test 1.$tn.14.1 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.14.2 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%10 ORDER BY a $window) FROM t2
"
execsql_test 1.$tn.14.3 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER ( ORDER BY b,a $window ) FROM t2
"
execsql_test 1.$tn.14.4 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER ( PARTITION BY b%10 ORDER BY b,a $window ) FROM t2
"
execsql_test 1.$tn.14.5 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER ( ORDER BY b%10,a $window ) FROM t2
"
execsql_test 1.$tn.14.6 "
SELECT string_agg(CAST(b AS TEXT), '.') OVER (PARTITION BY b%2,a ORDER BY b%10 $window) FROM t2
"
}
finish_test

File diff suppressed because one or more lines are too long

View File

@ -66,6 +66,12 @@ execsql_test 2.3.3 {
SELECT a, lag(b, 3, 'abc') OVER (ORDER BY a) FROM t4
}
execsql_test 2.4.1 {
SELECT string_agg(b, '.') OVER (
ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) FROM t4
}
execsql_test 3.0 {
DROP TABLE IF EXISTS t5;
CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);

View File

@ -145,6 +145,12 @@ do_execsql_test 2.3.3 {
SELECT a, lag(b, 3, 'abc') OVER (ORDER BY a) FROM t4
} {1 abc 2 abc 3 abc 4 A 5 B 6 C 7 D 8 E 9 F 10 G}
do_execsql_test 2.4.1 {
SELECT group_concat(b, '.') OVER (
ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) FROM t4
} {A.B.C.D.E.F.G.H.I.J B.C.D.E.F.G.H.I.J C.D.E.F.G.H.I.J D.E.F.G.H.I.J E.F.G.H.I.J F.G.H.I.J G.H.I.J H.I.J I.J J}
do_execsql_test 3.0 {
DROP TABLE IF EXISTS t5;
CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d INTEGER);