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

Commit1f8928c

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

File tree

1 file changed

+45
-168
lines changed

1 file changed

+45
-168
lines changed

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

Lines changed: 45 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,20 @@ static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
8888
staticvoidjsonb_categorize_type(Oidtypoid,
8989
JsonbTypeCategory*tcategory,
9090
Oid*outfuncoid);
91-
staticvoidcomposite_to_jsonb(Datumcomposite,JsonbInState*result);
91+
staticvoidcomposite_to_jsonb(Datumcomposite,JsonbInState*result,
92+
boolunpackJson);
9293
staticvoidarray_dim_to_jsonb(JsonbInState*result,intdim,intndims,int*dims,
9394
Datum*vals,bool*nulls,int*valcount,
94-
JsonbTypeCategorytcategory,Oidoutfuncoid);
95-
staticvoidarray_to_jsonb_internal(Datumarray,JsonbInState*result);
95+
JsonbTypeCategorytcategory,Oidoutfuncoid,
96+
boolunpackJson);
97+
staticvoidarray_to_jsonb_internal(Datumarray,JsonbInState*result,
98+
boolunpackJson);
9699
staticvoidjsonb_categorize_type(Oidtypoid,
97100
JsonbTypeCategory*tcategory,
98101
Oid*outfuncoid);
99102
staticvoiddatum_to_jsonb(Datumval,boolis_null,JsonbInState*result,
100103
JsonbTypeCategorytcategory,Oidoutfuncoid,
101-
boolkey_scalar);
104+
boolkey_scalar,boolunpackJson);
102105
staticvoidadd_jsonb(Datumval,boolis_null,JsonbInState*result,
103106
Oidval_type,boolkey_scalar);
104107
#ifndefJSON_C
@@ -796,7 +799,7 @@ jsonb_categorize_type(Oid typoid,
796799
staticvoid
797800
datum_to_jsonb(Datumval,boolis_null,JsonbInState*result,
798801
JsonbTypeCategorytcategory,Oidoutfuncoid,
799-
boolkey_scalar)
802+
boolkey_scalar,boolunpackJson)
800803
{
801804
char*outputstr;
802805
boolnumeric_error;
@@ -829,10 +832,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
829832
switch (tcategory)
830833
{
831834
caseJSONBTYPE_ARRAY:
832-
array_to_jsonb_internal(val,result);
835+
array_to_jsonb_internal(val,result,unpackJson);
833836
return;
834837
caseJSONBTYPE_COMPOSITE:
835-
composite_to_jsonb(val,result);
838+
composite_to_jsonb(val,result,unpackJson);
836839
return;
837840
caseJSONBTYPE_BOOL:
838841
if (key_scalar)
@@ -954,6 +957,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
954957
pushScalarJsonbValue(&result->parseState,
955958
JsonToJsonValue(jsonb,&jb),
956959
false, false);
960+
elseif (!unpackJson)
961+
result->res=JsonToJsonValue(jsonb,NULL);
957962
else
958963
{
959964
JsonbIteratorTokentype;
@@ -996,7 +1001,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
9961001
staticvoid
9971002
array_dim_to_jsonb(JsonbInState*result,intdim,intndims,int*dims,Datum*vals,
9981003
bool*nulls,int*valcount,JsonbTypeCategorytcategory,
999-
Oidoutfuncoid)
1004+
Oidoutfuncoid,boolunpackJson)
10001005
{
10011006
inti;
10021007

@@ -1015,13 +1020,13 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
10151020
if (dim+1==ndims)
10161021
{
10171022
datum_to_jsonb(vals[*valcount],nulls[*valcount],result,tcategory,
1018-
outfuncoid, false);
1023+
outfuncoid, false,unpackJson);
10191024
(*valcount)++;
10201025
}
10211026
else
10221027
{
10231028
array_dim_to_jsonb(result,dim+1,ndims,dims,vals,nulls,
1024-
valcount,tcategory,outfuncoid);
1029+
valcount,tcategory,outfuncoid,unpackJson);
10251030
}
10261031
}
10271032

@@ -1032,7 +1037,7 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
10321037
* Turn an array into JSON.
10331038
*/
10341039
staticvoid
1035-
array_to_jsonb_internal(Datumarray,JsonbInState*result)
1040+
array_to_jsonb_internal(Datumarray,JsonbInState*result,boolunpackJson)
10361041
{
10371042
ArrayType*v=DatumGetArrayTypeP(array);
10381043
Oidelement_type=ARR_ELEMTYPE(v);
@@ -1070,7 +1075,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
10701075
&nitems);
10711076

10721077
array_dim_to_jsonb(result,0,ndim,dim,elements,nulls,&count,tcategory,
1073-
outfuncoid);
1078+
outfuncoid,unpackJson);
10741079

10751080
pfree(elements);
10761081
pfree(nulls);
@@ -1080,7 +1085,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
10801085
* Turn a composite / record into JSON.
10811086
*/
10821087
staticvoid
1083-
composite_to_jsonb(Datumcomposite,JsonbInState*result)
1088+
composite_to_jsonb(Datumcomposite,JsonbInState*result,boolunpackJson)
10841089
{
10851090
HeapTupleHeadertd;
10861091
OidtupType;
@@ -1143,7 +1148,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
11431148
else
11441149
jsonb_categorize_type(att->atttypid,&tcategory,&outfuncoid);
11451150

1146-
datum_to_jsonb(val,isnull,result,tcategory,outfuncoid, false);
1151+
datum_to_jsonb(val,isnull,result,tcategory,outfuncoid, false,
1152+
unpackJson);
11471153
}
11481154

11491155
result->res=pushJsonbValue(&result->parseState,WJB_END_OBJECT,NULL);
@@ -1179,7 +1185,8 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
11791185
jsonb_categorize_type(val_type,
11801186
&tcategory,&outfuncoid);
11811187

1182-
datum_to_jsonb(val,is_null,result,tcategory,outfuncoid,key_scalar);
1188+
datum_to_jsonb(val,is_null,result,tcategory,outfuncoid,key_scalar,
1189+
true);
11831190
}
11841191

11851192
/*
@@ -1204,7 +1211,7 @@ to_jsonb(PG_FUNCTION_ARGS)
12041211

12051212
memset(&result,0,sizeof(JsonbInState));
12061213

1207-
datum_to_jsonb(val, false,&result,tcategory,outfuncoid, false);
1214+
datum_to_jsonb(val, false,&result,tcategory,outfuncoid, false, true);
12081215

12091216
PG_RETURN_JSONB_P(JsonbValueToJsonb(result.res));
12101217
}
@@ -1567,11 +1574,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
15671574
JsonbInStateelem;
15681575
Datumval;
15691576
JsonbInState*result;
1570-
boolsingle_scalar= false;
1571-
JsonbIterator*it;
1572-
Jsonb*jbelem;
15731577
JsonbValuev;
1574-
JsonbIteratorTokentype;
15751578

15761579
if (!AggCheckCallContext(fcinfo,&aggcontext))
15771580
{
@@ -1631,62 +1634,14 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
16311634
memset(&elem,0,sizeof(JsonbInState));
16321635

16331636
datum_to_jsonb(val,PG_ARGISNULL(1),&elem,state->val_category,
1634-
state->val_output_func, false);
1635-
1636-
jbelem=JsonbValueToJsonb(elem.res);
1637+
state->val_output_func, false, false);
16371638

16381639
/* switch to the aggregate context for accumulation operations */
16391640

16401641
oldcontext=MemoryContextSwitchTo(aggcontext);
16411642

1642-
it=JsonbIteratorInit(&jbelem->root);
1643-
1644-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1645-
{
1646-
switch (type)
1647-
{
1648-
caseWJB_BEGIN_ARRAY:
1649-
if (v.val.array.rawScalar)
1650-
single_scalar= true;
1651-
else
1652-
result->res=pushJsonbValue(&result->parseState,
1653-
type,NULL);
1654-
break;
1655-
caseWJB_END_ARRAY:
1656-
if (!single_scalar)
1657-
result->res=pushJsonbValue(&result->parseState,
1658-
type,NULL);
1659-
break;
1660-
caseWJB_BEGIN_OBJECT:
1661-
caseWJB_END_OBJECT:
1662-
result->res=pushJsonbValue(&result->parseState,
1663-
type,NULL);
1664-
break;
1665-
caseWJB_ELEM:
1666-
caseWJB_KEY:
1667-
caseWJB_VALUE:
1668-
if (v.type==jbvString)
1669-
{
1670-
/* copy string values in the aggregate context */
1671-
char*buf=palloc(v.val.string.len+1);
1672-
1673-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1674-
v.val.string.val=buf;
1675-
}
1676-
elseif (v.type==jbvNumeric)
1677-
{
1678-
/* same for numeric */
1679-
v.val.numeric=
1680-
DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1681-
NumericGetDatum(v.val.numeric)));
1682-
}
1683-
result->res=pushJsonbValue(&result->parseState,
1684-
type,&v);
1685-
break;
1686-
default:
1687-
elog(ERROR,"unknown jsonb iterator token type");
1688-
}
1689-
}
1643+
result->res=pushJsonbValueExt(&result->parseState,WJB_ELEM,
1644+
JsonValueCopy(&v,elem.res), false);
16901645

16911646
MemoryContextSwitchTo(oldcontext);
16921647

@@ -1737,12 +1692,10 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
17371692
JsonbAggState*state;
17381693
Datumval;
17391694
JsonbInState*result;
1740-
boolsingle_scalar;
1741-
JsonbIterator*it;
1742-
Jsonb*jbkey,
1743-
*jbval;
1744-
JsonbValuev;
1745-
JsonbIteratorTokentype;
1695+
constJsonbValue*jbkey,
1696+
*jbval;
1697+
JsonbValuejbkeybuf,
1698+
v;
17461699

17471700
if (!AggCheckCallContext(fcinfo,&aggcontext))
17481701
{
@@ -1810,122 +1763,46 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
18101763
memset(&elem,0,sizeof(JsonbInState));
18111764

18121765
datum_to_jsonb(val, false,&elem,state->key_category,
1813-
state->key_output_func, true);
1766+
state->key_output_func, true, false);
18141767

1815-
jbkey=JsonbValueToJsonb(elem.res);
1768+
jbkey=elem.res;
18161769

18171770
val=PG_ARGISNULL(2) ? (Datum)0 :PG_GETARG_DATUM(2);
18181771

18191772
memset(&elem,0,sizeof(JsonbInState));
18201773

18211774
datum_to_jsonb(val,PG_ARGISNULL(2),&elem,state->val_category,
1822-
state->val_output_func, false);
1823-
1824-
jbval=JsonbValueToJsonb(elem.res);
1825-
1826-
it=JsonbIteratorInit(&jbkey->root);
1775+
state->val_output_func, false, false);
18271776

1828-
/* switch to the aggregate context for accumulation operations */
1829-
1830-
oldcontext=MemoryContextSwitchTo(aggcontext);
1777+
jbval=elem.res;
18311778

18321779
/*
18331780
* keys should be scalar, and we should have already checked for that
18341781
* above when calling datum_to_jsonb, so we only need to look for these
18351782
* things.
18361783
*/
18371784

1838-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1839-
{
1840-
switch (type)
1841-
{
1842-
caseWJB_BEGIN_ARRAY:
1843-
if (!v.val.array.rawScalar)
1844-
elog(ERROR,"unexpected structure for key");
1845-
break;
1846-
caseWJB_ELEM:
1847-
if (v.type==jbvString)
1848-
{
1849-
/* copy string values in the aggregate context */
1850-
char*buf=palloc(v.val.string.len+1);
1785+
jbkey=JsonValueUnwrap(jbkey,&jbkeybuf);
18511786

1852-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1853-
v.val.string.val=buf;
1854-
}
1855-
else
1856-
{
1857-
ereport(ERROR,
1858-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1859-
errmsg("object keys must be strings")));
1860-
}
1861-
result->res=pushJsonbValue(&result->parseState,
1862-
WJB_KEY,&v);
1863-
break;
1864-
caseWJB_END_ARRAY:
1865-
break;
1866-
default:
1867-
elog(ERROR,"unexpected structure for key");
1868-
break;
1869-
}
1870-
}
1787+
if (jbkey->type!=jbvString)
1788+
ereport(ERROR,
1789+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1790+
errmsg("object keys must be strings")));
18711791

1872-
it=JsonbIteratorInit(&jbval->root);
1792+
/* switch to the aggregate context for accumulation operations */
18731793

1874-
single_scalar=false;
1794+
oldcontext=MemoryContextSwitchTo(aggcontext);
18751795

1796+
result->res=pushJsonbValue(&result->parseState,WJB_KEY,
1797+
JsonValueCopy(&v,jbkey));
18761798
/*
18771799
* values can be anything, including structured and null, so we treat them
18781800
* as in json_agg_transfn, except that single scalars are always pushed as
18791801
* WJB_VALUE items.
18801802
*/
18811803

1882-
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
1883-
{
1884-
switch (type)
1885-
{
1886-
caseWJB_BEGIN_ARRAY:
1887-
if (v.val.array.rawScalar)
1888-
single_scalar= true;
1889-
else
1890-
result->res=pushJsonbValue(&result->parseState,
1891-
type,NULL);
1892-
break;
1893-
caseWJB_END_ARRAY:
1894-
if (!single_scalar)
1895-
result->res=pushJsonbValue(&result->parseState,
1896-
type,NULL);
1897-
break;
1898-
caseWJB_BEGIN_OBJECT:
1899-
caseWJB_END_OBJECT:
1900-
result->res=pushJsonbValue(&result->parseState,
1901-
type,NULL);
1902-
break;
1903-
caseWJB_ELEM:
1904-
caseWJB_KEY:
1905-
caseWJB_VALUE:
1906-
if (v.type==jbvString)
1907-
{
1908-
/* copy string values in the aggregate context */
1909-
char*buf=palloc(v.val.string.len+1);
1910-
1911-
snprintf(buf,v.val.string.len+1,"%s",v.val.string.val);
1912-
v.val.string.val=buf;
1913-
}
1914-
elseif (v.type==jbvNumeric)
1915-
{
1916-
/* same for numeric */
1917-
v.val.numeric=
1918-
DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1919-
NumericGetDatum(v.val.numeric)));
1920-
}
1921-
result->res=pushJsonbValue(&result->parseState,
1922-
single_scalar ?WJB_VALUE :type,
1923-
&v);
1924-
break;
1925-
default:
1926-
elog(ERROR,"unknown jsonb iterator token type");
1927-
}
1928-
}
1804+
result->res=pushJsonbValueExt(&result->parseState,WJB_VALUE,
1805+
JsonValueCopy(&v,jbval), false);
19291806

19301807
MemoryContextSwitchTo(oldcontext);
19311808

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp