Index: ext/misc/json1.c ================================================================== --- ext/misc/json1.c +++ ext/misc/json1.c @@ -1818,11 +1818,11 @@ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '['); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } jsonAppendValue(pStr, argv[0]); } @@ -1868,11 +1868,13 @@ int argc, sqlite3_value **argv ){ int i; int inStr = 0; + int nNest = 0; char *z; + char c; JsonString *pStr; UNUSED_PARAM(argc); UNUSED_PARAM(argv); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER @@ -1879,16 +1881,22 @@ /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will ** always have been called to initalize it */ if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; - for(i=1; z[i]!=',' || inStr; i++){ - assert( inUsed ); - if( z[i]=='"' ){ + for(i=1; (c = z[i])!=',' || inStr || nNest; i++){ + if( i>=pStr->nUsed ){ + pStr->nUsed = 1; + return; + } + if( c=='"' ){ inStr = !inStr; - }else if( z[i]=='\\' ){ + }else if( c=='\\' ){ i++; + }else if( !inStr ){ + if( c=='{' || c=='[' ) nNest++; + if( c=='}' || c==']' ) nNest--; } } pStr->nUsed -= i; memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); } @@ -1914,11 +1922,11 @@ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '{'); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } z = (const char*)sqlite3_value_text(argv[0]); n = (u32)sqlite3_value_bytes(argv[0]); Index: test/windowB.test ================================================================== --- test/windowB.test +++ test/windowB.test @@ -81,15 +81,15 @@ #------------------------------------------------------------------------- ifcapable json1 { reset_db do_execsql_test 3.0 { - CREATE TABLE testjson(id INTEGER PRIMARY KEY, j TEXT); - INSERT INTO testjson VALUES(1, '{"a":1}'); - INSERT INTO testjson VALUES(2, '{"b":2}'); - INSERT INTO testjson VALUES(3, '{"c":3}'); - INSERT INTO testjson VALUES(4, '{"d":4}'); + CREATE TABLE testjson(id INTEGER PRIMARY KEY, j TEXT, x TEXT); + INSERT INTO testjson VALUES(1, '{"a":1}', 'a'); + INSERT INTO testjson VALUES(2, '{"b":2}', 'b'); + INSERT INTO testjson VALUES(3, '{"c":3}', 'c'); + INSERT INTO testjson VALUES(4, '{"d":4}', 'd'); } do_execsql_test 3.1 { SELECT json_group_array(json(j)) FROM testjson; } { @@ -105,11 +105,12 @@ {[{"a":1},{"b":2},{"c":3},{"d":4}]} } do_execsql_test 3.3 { SELECT json_group_array(json(j)) OVER ( - ORDER BY id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE TIES + ORDER BY id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + EXCLUDE TIES ) FROM testjson; } { {[{"a":1}]} {[{"a":1},{"b":2}]} {[{"a":1},{"b":2},{"c":3}]} @@ -136,39 +137,69 @@ {[{"a":1}]} {[{"a":1},{"b":2}]} {[{"b":2},{"c":3}]} } - if 0 { - - do_execsql_test 3.5 { + do_execsql_test 3.5a { + UPDATE testjson SET j = replace(j,char(125),',"e":9'||char(125)); + SELECT j FROM testjson; + } { + {{"a":1,"e":9}} + {{"b":2,"e":9}} + {{"c":3,"e":9}} + {{"d":4,"e":9}} + } + do_execsql_test 3.5b { + SELECT group_concat(x,'') OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson ORDER BY id; + } {bc cd d {}} + do_execsql_test 3.5c { SELECT json_group_array(json(j)) OVER ( ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING ) FROM testjson; } { - {[]} - {[{"a":1}]} - {[{"a":1},{"b":2}]} - {[{"b":2},{"c":3}]} - } - - explain_i { - SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER ( - ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING - ) FROM testjson; - } - do_execsql_test 3.7 { - PRAGMA vdbe_trace = 1; - SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER ( - ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING - ) FROM testjson; - } { - {[]} - {[{"a":1}]} - {[{"a":1}]} - {[{"c":3}]} - } - + {[{"b":2,"e":9},{"c":3,"e":9}]} + {[{"c":3,"e":9},{"d":4,"e":9}]} + {[{"d":4,"e":9}]} + {[]} + } + do_execsql_test 3.5d { + SELECT json_group_object(x,json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson; + } { + {{"b":{"b":2,"e":9},"c":{"c":3,"e":9}}} + {{"c":{"c":3,"e":9},"d":{"d":4,"e":9}}} + {{"d":{"d":4,"e":9}}} + {{}} + } + + do_execsql_test 3.7b { + SELECT group_concat(x,'') FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson; + } {{} a a c} + + do_execsql_test 3.7c { + SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {[]} + {[{"a":1,"e":9}]} + {[{"a":1,"e":9}]} + {[{"c":3,"e":9}]} + } + do_execsql_test 3.7d { + SELECT json_group_object(x,json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {{}} + {{"a":{"a":1,"e":9}}} + {{"a":{"a":1,"e":9}}} + {{"c":{"c":3,"e":9}}} } } finish_test