Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7bca449

Browse files
author
Nikita Glukhov
committed
Preserve json formatting in json_agg(), json_object_agg()
1 parente7877e0 commit7bca449

File tree

1 file changed

+44
-168
lines changed

1 file changed

+44
-168
lines changed

‎src/backend/utils/adt/jsonb.c

Lines changed: 44 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,19 @@ static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
8787
staticvoidjsonb_categorize_type(Oidtypoid,
8888
JsonbTypeCategory*tcategory,
8989
Oid*outfuncoid);
90-
staticvoidcomposite_to_jsonb(Datumcomposite,JsonbInState*result);
90+
staticvoidcomposite_to_jsonb(Datumcomposite,JsonbInState*result,
91+
boolunpackJson);
9192
staticvoidarray_dim_to_jsonb(JsonbInState*result,intdim,intndims,int*dims,
9293
Datum*vals,bool*nulls,int*valcount,
93-
JsonbTypeCategorytcategory,Oidoutfuncoid);
94-
staticvoidarray_to_jsonb_internal(Datumarray,JsonbInState*result);
94+
JsonbTypeCategorytcategory,Oidoutfuncoid,boolunpackJson);
95+
staticvoidarray_to_jsonb_internal(Datumarray,JsonbInState*result,
96+
boolunpackJson);
9597
staticvoidjsonb_categorize_type(Oidtypoid,
9698
JsonbTypeCategory*tcategory,
9799
Oid*outfuncoid);
98100
staticvoiddatum_to_jsonb(Datumval,boolis_null,JsonbInState*result,
99101
JsonbTypeCategorytcategory,Oidoutfuncoid,
100-
boolkey_scalar);
102+
boolkey_scalar,boolunpackJson);
101103
staticvoidadd_jsonb(Datumval,boolis_null,JsonbInState*result,
102104
Oidval_type,boolkey_scalar);
103105
#ifndefJSON_C
@@ -743,7 +745,7 @@ jsonb_categorize_type(Oid typoid,
743745
staticvoid
744746
datum_to_jsonb(Datumval,boolis_null,JsonbInState*result,
745747
JsonbTypeCategorytcategory,Oidoutfuncoid,
746-
boolkey_scalar)
748+
boolkey_scalar,boolunpackJson)
747749
{
748750
char*outputstr;
749751
boolnumeric_error;
@@ -776,10 +778,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
776778
switch (tcategory)
777779
{
778780
caseJSONBTYPE_ARRAY:
779-
array_to_jsonb_internal(val,result);
781+
array_to_jsonb_internal(val,result,unpackJson);
780782
return;
781783
caseJSONBTYPE_COMPOSITE:
782-
composite_to_jsonb(val,result);
784+
composite_to_jsonb(val,result,unpackJson);
783785
return;
784786
caseJSONBTYPE_BOOL:
785787
if (key_scalar)
@@ -945,6 +947,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
945947
pushScalarJsonbValue(&result->parseState,
946948
JsonToJsonValue(jsonb,&jb),
947949
false, false);
950+
elseif (!unpackJson)
951+
result->res=JsonToJsonValue(jsonb,NULL);
948952
else
949953
{
950954
JsonbIteratorTokentype;
@@ -987,7 +991,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
987991
staticvoid
988992
array_dim_to_jsonb(JsonbInState*result,intdim,intndims,int*dims,Datum*vals,
989993
bool*nulls,int*valcount,JsonbTypeCategorytcategory,
990-
Oidoutfuncoid)
994+
Oidoutfuncoid,boolunpackJson)
991995
{
992996
inti;
993997

@@ -1006,13 +1010,13 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
10061010
if (dim+1==ndims)
10071011
{
10081012
datum_to_jsonb(vals[*valcount],nulls[*valcount],result,tcategory,
1009-
outfuncoid, false);
1013+
outfuncoid, false,unpackJson);
10101014
(*valcount)++;
10111015
}
10121016
else
10131017
{
10141018
array_dim_to_jsonb(result,dim+1,ndims,dims,vals,nulls,
1015-
valcount,tcategory,outfuncoid);
1019+
valcount,tcategory,outfuncoid,unpackJson);
10161020
}
10171021
}
10181022

@@ -1023,7 +1027,7 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
10231027
* Turn an array into JSON.
10241028
*/
10251029
staticvoid
1026-
array_to_jsonb_internal(Datumarray,JsonbInState*result)
1030+
array_to_jsonb_internal(Datumarray,JsonbInState*result,boolunpackJson)
10271031
{
10281032
ArrayType*v=DatumGetArrayTypeP(array);
10291033
Oidelement_type=ARR_ELEMTYPE(v);
@@ -1061,7 +1065,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
10611065
&nitems);
10621066

10631067
array_dim_to_jsonb(result,0,ndim,dim,elements,nulls,&count,tcategory,
1064-
outfuncoid);
1068+
outfuncoid,unpackJson);
10651069

10661070
pfree(elements);
10671071
pfree(nulls);
@@ -1071,7 +1075,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
10711075
* Turn a composite / record into JSON.
10721076
*/
10731077
staticvoid
1074-
composite_to_jsonb(Datumcomposite,JsonbInState*result)
1078+
composite_to_jsonb(Datumcomposite,JsonbInState*result,boolunpackJson)
10751079
{
10761080
HeapTupleHeadertd;
10771081
OidtupType;
@@ -1134,7 +1138,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
11341138
jsonb_categorize_type(tupdesc->attrs[i]->atttypid,
11351139
&tcategory,&outfuncoid);
11361140

1137-
datum_to_jsonb(val,isnull,result,tcategory,outfuncoid, false);
1141+
datum_to_jsonb(val,isnull,result,tcategory,outfuncoid, false,
1142+
unpackJson);
11381143
}
11391144

11401145
result->res=pushJsonbValue(&result->parseState,WJB_END_OBJECT,NULL);
@@ -1170,7 +1175,8 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
11701175
jsonb_categorize_type(val_type,
11711176
&tcategory,&outfuncoid);
11721177

1173-
datum_to_jsonb(val,is_null,result,tcategory,outfuncoid,key_scalar);
1178+
datum_to_jsonb(val,is_null,result,tcategory,outfuncoid,key_scalar,
1179+
true);
11741180
}
11751181

11761182
/*
@@ -1195,7 +1201,7 @@ to_jsonb(PG_FUNCTION_ARGS)
11951201

11961202
memset(&result,0,sizeof(JsonbInState));
11971203

1198-
datum_to_jsonb(val, false,&result,tcategory,outfuncoid, false);
1204+
datum_to_jsonb(val, false,&result,tcategory,outfuncoid, false, true);
11991205

12001206
PG_RETURN_JSONB(JsonbValueToJsonb(result.res));
12011207
}
@@ -1597,11 +1603,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
15971603
JsonbInStateelem;
15981604
Datumval;
15991605
JsonbInState*result;
1600-
boolsingle_scalar= false;
1601-
JsonbIterator*it;
1602-
Jsonb*jbelem;
16031606
JsonbValuev;
1604-
JsonbIteratorTokentype;
16051607

16061608
if (!AggCheckCallContext(fcinfo,&aggcontext))
16071609
{
@@ -1661,62 +1663,14 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
16611663
memset(&elem,0,sizeof(JsonbInState));
16621664

16631665
datum_to_jsonb(val,PG_ARGISNULL(1),&elem,state->val_category,
1664-
state->val_output_func, false);
1665-
1666-
jbelem=JsonbValueToJsonb(elem.res);
1666+
state->val_output_func, false, false);
16671667

16681668
/* switch to the aggregate context for accumulation operations */
16691669

16701670
oldcontext=MemoryContextSwitchTo(aggcontext);
16711671

1672-
it=JsonbIteratorInit(&jbelem->root);
1673-
1674-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1675-
{
1676-
switch (type)
1677-
{
1678-
caseWJB_BEGIN_ARRAY:
1679-
if (v.val.array.rawScalar)
1680-
single_scalar= true;
1681-
else
1682-
result->res=pushJsonbValue(&result->parseState,
1683-
type,NULL);
1684-
break;
1685-
caseWJB_END_ARRAY:
1686-
if (!single_scalar)
1687-
result->res=pushJsonbValue(&result->parseState,
1688-
type,NULL);
1689-
break;
1690-
caseWJB_BEGIN_OBJECT:
1691-
caseWJB_END_OBJECT:
1692-
result->res=pushJsonbValue(&result->parseState,
1693-
type,NULL);
1694-
break;
1695-
caseWJB_ELEM:
1696-
caseWJB_KEY:
1697-
caseWJB_VALUE:
1698-
if (v.type==jbvString)
1699-
{
1700-
/* copy string values in the aggregate context */
1701-
char*buf=palloc(v.val.string.len+1);
1702-
1703-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1704-
v.val.string.val=buf;
1705-
}
1706-
elseif (v.type==jbvNumeric)
1707-
{
1708-
/* same for numeric */
1709-
v.val.numeric=
1710-
DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1711-
NumericGetDatum(v.val.numeric)));
1712-
}
1713-
result->res=pushJsonbValue(&result->parseState,
1714-
type,&v);
1715-
break;
1716-
default:
1717-
elog(ERROR,"unknown jsonb iterator token type");
1718-
}
1719-
}
1672+
result->res=pushJsonbValueExt(&result->parseState,WJB_ELEM,
1673+
JsonValueCopy(&v,elem.res), false);
17201674

17211675
MemoryContextSwitchTo(oldcontext);
17221676

@@ -1767,12 +1721,10 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
17671721
JsonbAggState*state;
17681722
Datumval;
17691723
JsonbInState*result;
1770-
boolsingle_scalar;
1771-
JsonbIterator*it;
1772-
Jsonb*jbkey,
1773-
*jbval;
1774-
JsonbValuev;
1775-
JsonbIteratorTokentype;
1724+
constJsonbValue*jbkey,
1725+
*jbval;
1726+
JsonbValuejbkeybuf,
1727+
v;
17761728

17771729
if (!AggCheckCallContext(fcinfo,&aggcontext))
17781730
{
@@ -1839,122 +1791,46 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
18391791
memset(&elem,0,sizeof(JsonbInState));
18401792

18411793
datum_to_jsonb(val, false,&elem,state->key_category,
1842-
state->key_output_func, true);
1794+
state->key_output_func, true, false);
18431795

1844-
jbkey=JsonbValueToJsonb(elem.res);
1796+
jbkey=elem.res;
18451797

18461798
val=PG_ARGISNULL(2) ? (Datum)0 :PG_GETARG_DATUM(2);
18471799

18481800
memset(&elem,0,sizeof(JsonbInState));
18491801

18501802
datum_to_jsonb(val,PG_ARGISNULL(2),&elem,state->val_category,
1851-
state->val_output_func, false);
1852-
1853-
jbval=JsonbValueToJsonb(elem.res);
1854-
1855-
it=JsonbIteratorInit(&jbkey->root);
1803+
state->val_output_func, false, false);
18561804

1857-
/* switch to the aggregate context for accumulation operations */
1858-
1859-
oldcontext=MemoryContextSwitchTo(aggcontext);
1805+
jbval=elem.res;
18601806

18611807
/*
18621808
* keys should be scalar, and we should have already checked for that
18631809
* above when calling datum_to_jsonb, so we only need to look for these
18641810
* things.
18651811
*/
18661812

1867-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1868-
{
1869-
switch (type)
1870-
{
1871-
caseWJB_BEGIN_ARRAY:
1872-
if (!v.val.array.rawScalar)
1873-
elog(ERROR,"unexpected structure for key");
1874-
break;
1875-
caseWJB_ELEM:
1876-
if (v.type==jbvString)
1877-
{
1878-
/* copy string values in the aggregate context */
1879-
char*buf=palloc(v.val.string.len+1);
1813+
jbkey=JsonValueUnwrap(jbkey,&jbkeybuf);
18801814

1881-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1882-
v.val.string.val=buf;
1883-
}
1884-
else
1885-
{
1886-
ereport(ERROR,
1887-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1888-
errmsg("object keys must be strings")));
1889-
}
1890-
result->res=pushJsonbValue(&result->parseState,
1891-
WJB_KEY,&v);
1892-
break;
1893-
caseWJB_END_ARRAY:
1894-
break;
1895-
default:
1896-
elog(ERROR,"unexpected structure for key");
1897-
break;
1898-
}
1899-
}
1815+
if (jbkey->type!=jbvString)
1816+
ereport(ERROR,
1817+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1818+
errmsg("object keys must be strings")));
19001819

1901-
it=JsonbIteratorInit(&jbval->root);
1820+
/* switch to the aggregate context for accumulation operations */
19021821

1903-
single_scalar=false;
1822+
oldcontext=MemoryContextSwitchTo(aggcontext);
19041823

1824+
result->res=pushJsonbValue(&result->parseState,WJB_KEY,
1825+
JsonValueCopy(&v,jbkey));
19051826
/*
19061827
* values can be anything, including structured and null, so we treat them
19071828
* as in json_agg_transfn, except that single scalars are always pushed as
19081829
* WJB_VALUE items.
19091830
*/
19101831

1911-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1912-
{
1913-
switch (type)
1914-
{
1915-
caseWJB_BEGIN_ARRAY:
1916-
if (v.val.array.rawScalar)
1917-
single_scalar= true;
1918-
else
1919-
result->res=pushJsonbValue(&result->parseState,
1920-
type,NULL);
1921-
break;
1922-
caseWJB_END_ARRAY:
1923-
if (!single_scalar)
1924-
result->res=pushJsonbValue(&result->parseState,
1925-
type,NULL);
1926-
break;
1927-
caseWJB_BEGIN_OBJECT:
1928-
caseWJB_END_OBJECT:
1929-
result->res=pushJsonbValue(&result->parseState,
1930-
type,NULL);
1931-
break;
1932-
caseWJB_ELEM:
1933-
caseWJB_KEY:
1934-
caseWJB_VALUE:
1935-
if (v.type==jbvString)
1936-
{
1937-
/* copy string values in the aggregate context */
1938-
char*buf=palloc(v.val.string.len+1);
1939-
1940-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1941-
v.val.string.val=buf;
1942-
}
1943-
elseif (v.type==jbvNumeric)
1944-
{
1945-
/* same for numeric */
1946-
v.val.numeric=
1947-
DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1948-
NumericGetDatum(v.val.numeric)));
1949-
}
1950-
result->res=pushJsonbValue(&result->parseState,
1951-
single_scalar ?WJB_VALUE :type,
1952-
&v);
1953-
break;
1954-
default:
1955-
elog(ERROR,"unknown jsonb iterator token type");
1956-
}
1957-
}
1832+
result->res=pushJsonbValueExt(&result->parseState,WJB_VALUE,
1833+
JsonValueCopy(&v,jbval), false);
19581834

19591835
MemoryContextSwitchTo(oldcontext);
19601836

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp