Fixes to allow group_concat() to be used as a window function.
FossilOrigin-Name: 89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
This commit is contained in:
parent
07509f8c1e
commit
03854d2ecc
24
manifest
24
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
251022034219819a1dc356542770ff46e3147a080f072eb20af6106771dadd92
|
||||
89bbc9ba8f66853a7530453f146c9df1baacd8558468016cefa7602911f7578a
|
44
src/func.c
44
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
|
||||
|
@ -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
|
||||
|
@ -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}"
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user