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

Commitc00c324

Browse files
committed
Cache argument type information in json(b) aggregate functions.
These functions have been looking up type info for every row theyprocess. Instead of doing that we only look them up the first timethrough and stash the information in the aggregate state object.Affects json_agg, json_object_agg, jsonb_agg and jsonb_object_agg.There is plenty more work to do in making these more efficient,especially the jsonb functions, but this is a virtually cost freeimprovement that can be done right away.Backpatch to 9.5 where the jsonb variants were introduced.
1 parentd9c0c72 commitc00c324

File tree

2 files changed

+173
-133
lines changed

2 files changed

+173
-133
lines changed

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

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ typedef enum/* type categories for datum_to_json */
6868
JSONTYPE_OTHER/* all else */
6969
}JsonTypeCategory;
7070

71+
typedefstructJsonAggState
72+
{
73+
StringInfostr;
74+
JsonTypeCategorykey_category;
75+
Oidkey_output_func;
76+
JsonTypeCategoryval_category;
77+
Oidval_output_func;
78+
}JsonAggState;
79+
7180
staticinlinevoidjson_lex(JsonLexContext*lex);
7281
staticinlinevoidjson_lex_string(JsonLexContext*lex);
7382
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,bool*num_err);
@@ -1858,18 +1867,10 @@ to_json(PG_FUNCTION_ARGS)
18581867
Datum
18591868
json_agg_transfn(PG_FUNCTION_ARGS)
18601869
{
1861-
Oidval_type=get_fn_expr_argtype(fcinfo->flinfo,1);
18621870
MemoryContextaggcontext,
18631871
oldcontext;
1864-
StringInfostate;
1872+
JsonAggState*state;
18651873
Datumval;
1866-
JsonTypeCategorytcategory;
1867-
Oidoutfuncoid;
1868-
1869-
if (val_type==InvalidOid)
1870-
ereport(ERROR,
1871-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1872-
errmsg("could not determine input data type")));
18731874

18741875
if (!AggCheckCallContext(fcinfo,&aggcontext))
18751876
{
@@ -1879,50 +1880,59 @@ json_agg_transfn(PG_FUNCTION_ARGS)
18791880

18801881
if (PG_ARGISNULL(0))
18811882
{
1883+
Oidarg_type=get_fn_expr_argtype(fcinfo->flinfo,1);
1884+
1885+
if (arg_type==InvalidOid)
1886+
ereport(ERROR,
1887+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1888+
errmsg("could not determine input data type")));
1889+
18821890
/*
1883-
* Make thisStringInfo in a context where it will persist for the
1891+
* Make thisstate object in a context where it will persist for the
18841892
* duration of the aggregate call. MemoryContextSwitchTo is only
18851893
* needed the first time, as the StringInfo routines make sure they
18861894
* use the right context to enlarge the object if necessary.
18871895
*/
18881896
oldcontext=MemoryContextSwitchTo(aggcontext);
1889-
state=makeStringInfo();
1897+
state= (JsonAggState*)palloc(sizeof(JsonAggState));
1898+
state->str=makeStringInfo();
18901899
MemoryContextSwitchTo(oldcontext);
18911900

1892-
appendStringInfoChar(state,'[');
1901+
appendStringInfoChar(state->str,'[');
1902+
json_categorize_type(arg_type,&state->val_category,
1903+
&state->val_output_func);
18931904
}
18941905
else
18951906
{
1896-
state= (StringInfo)PG_GETARG_POINTER(0);
1897-
appendStringInfoString(state,", ");
1907+
state= (JsonAggState*)PG_GETARG_POINTER(0);
1908+
appendStringInfoString(state->str,", ");
18981909
}
18991910

19001911
/* fast path for NULLs */
19011912
if (PG_ARGISNULL(1))
19021913
{
1903-
datum_to_json((Datum)0, true,state,JSONTYPE_NULL,InvalidOid, false);
1914+
datum_to_json((Datum)0, true,state->str,JSONTYPE_NULL,
1915+
InvalidOid, false);
19041916
PG_RETURN_POINTER(state);
19051917
}
19061918

19071919
val=PG_GETARG_DATUM(1);
19081920

1909-
/* XXX we do this every time?? */
1910-
json_categorize_type(val_type,
1911-
&tcategory,&outfuncoid);
1912-
19131921
/* add some whitespace if structured type and not first item */
19141922
if (!PG_ARGISNULL(0)&&
1915-
(tcategory==JSONTYPE_ARRAY||tcategory==JSONTYPE_COMPOSITE))
1923+
(state->val_category==JSONTYPE_ARRAY||
1924+
state->val_category==JSONTYPE_COMPOSITE))
19161925
{
1917-
appendStringInfoString(state,"\n ");
1926+
appendStringInfoString(state->str,"\n ");
19181927
}
19191928

1920-
datum_to_json(val, false,state,tcategory,outfuncoid, false);
1929+
datum_to_json(val, false,state->str,state->val_category,
1930+
state->val_output_func, false);
19211931

19221932
/*
19231933
* The transition type for array_agg() is declared to be "internal", which
19241934
* is a pass-by-value type the same size as a pointer. So we can safely
1925-
* pass theArrayBuildState pointer through nodeAgg.c's machinations.
1935+
* pass theJsonAggState pointer through nodeAgg.c's machinations.
19261936
*/
19271937
PG_RETURN_POINTER(state);
19281938
}
@@ -1933,19 +1943,21 @@ json_agg_transfn(PG_FUNCTION_ARGS)
19331943
Datum
19341944
json_agg_finalfn(PG_FUNCTION_ARGS)
19351945
{
1936-
StringInfostate;
1946+
JsonAggState*state;
19371947

19381948
/* cannot be called directly because of internal-type argument */
19391949
Assert(AggCheckCallContext(fcinfo,NULL));
19401950

1941-
state=PG_ARGISNULL(0) ?NULL : (StringInfo)PG_GETARG_POINTER(0);
1951+
state=PG_ARGISNULL(0) ?
1952+
NULL :
1953+
(JsonAggState*)PG_GETARG_POINTER(0);
19421954

19431955
/* NULL result for no rows in, as is standard with aggregates */
19441956
if (state==NULL)
19451957
PG_RETURN_NULL();
19461958

19471959
/* Else return state with appropriate array terminator added */
1948-
PG_RETURN_TEXT_P(catenate_stringinfo_string(state,"]"));
1960+
PG_RETURN_TEXT_P(catenate_stringinfo_string(state->str,"]"));
19491961
}
19501962

19511963
/*
@@ -1956,10 +1968,9 @@ json_agg_finalfn(PG_FUNCTION_ARGS)
19561968
Datum
19571969
json_object_agg_transfn(PG_FUNCTION_ARGS)
19581970
{
1959-
Oidval_type;
19601971
MemoryContextaggcontext,
19611972
oldcontext;
1962-
StringInfostate;
1973+
JsonAggState*state;
19631974
Datumarg;
19641975

19651976
if (!AggCheckCallContext(fcinfo,&aggcontext))
@@ -1970,22 +1981,45 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
19701981

19711982
if (PG_ARGISNULL(0))
19721983
{
1984+
Oidarg_type;
1985+
19731986
/*
19741987
* Make the StringInfo in a context where it will persist for the
19751988
* duration of the aggregate call. Switching context is only needed
19761989
* for this initial step, as the StringInfo routines make sure they
19771990
* use the right context to enlarge the object if necessary.
19781991
*/
19791992
oldcontext=MemoryContextSwitchTo(aggcontext);
1980-
state=makeStringInfo();
1993+
state= (JsonAggState*)palloc(sizeof(JsonAggState));
1994+
state->str=makeStringInfo();
19811995
MemoryContextSwitchTo(oldcontext);
19821996

1983-
appendStringInfoString(state,"{ ");
1997+
arg_type=get_fn_expr_argtype(fcinfo->flinfo,1);
1998+
1999+
if (arg_type==InvalidOid)
2000+
ereport(ERROR,
2001+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2002+
errmsg("could not determine data type for argument 1")));
2003+
2004+
json_categorize_type(arg_type,&state->key_category,
2005+
&state->key_output_func);
2006+
2007+
arg_type=get_fn_expr_argtype(fcinfo->flinfo,2);
2008+
2009+
if (arg_type==InvalidOid)
2010+
ereport(ERROR,
2011+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2012+
errmsg("could not determine data type for argument 2")));
2013+
2014+
json_categorize_type(arg_type,&state->val_category,
2015+
&state->val_output_func);
2016+
2017+
appendStringInfoString(state->str,"{ ");
19842018
}
19852019
else
19862020
{
1987-
state= (StringInfo)PG_GETARG_POINTER(0);
1988-
appendStringInfoString(state,", ");
2021+
state= (JsonAggState*)PG_GETARG_POINTER(0);
2022+
appendStringInfoString(state->str,", ");
19892023
}
19902024

19912025
/*
@@ -1995,12 +2029,6 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
19952029
* type UNKNOWN, which fortunately does not matter to us, since
19962030
* unknownout() works fine.
19972031
*/
1998-
val_type=get_fn_expr_argtype(fcinfo->flinfo,1);
1999-
2000-
if (val_type==InvalidOid)
2001-
ereport(ERROR,
2002-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2003-
errmsg("could not determine data type for argument %d",1)));
20042032

20052033
if (PG_ARGISNULL(1))
20062034
ereport(ERROR,
@@ -2009,23 +2037,18 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
20092037

20102038
arg=PG_GETARG_DATUM(1);
20112039

2012-
add_json(arg, false,state,val_type, true);
2013-
2014-
appendStringInfoString(state," : ");
2040+
datum_to_json(arg, false,state->str,state->key_category,
2041+
state->key_output_func, true);
20152042

2016-
val_type=get_fn_expr_argtype(fcinfo->flinfo,2);
2017-
2018-
if (val_type==InvalidOid)
2019-
ereport(ERROR,
2020-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2021-
errmsg("could not determine data type for argument %d",2)));
2043+
appendStringInfoString(state->str," : ");
20222044

20232045
if (PG_ARGISNULL(2))
20242046
arg= (Datum)0;
20252047
else
20262048
arg=PG_GETARG_DATUM(2);
20272049

2028-
add_json(arg,PG_ARGISNULL(2),state,val_type, false);
2050+
datum_to_json(arg,PG_ARGISNULL(2),state->str,state->val_category,
2051+
state->val_output_func, false);
20292052

20302053
PG_RETURN_POINTER(state);
20312054
}
@@ -2036,19 +2059,19 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
20362059
Datum
20372060
json_object_agg_finalfn(PG_FUNCTION_ARGS)
20382061
{
2039-
StringInfostate;
2062+
JsonAggState*state;
20402063

20412064
/* cannot be called directly because of internal-type argument */
20422065
Assert(AggCheckCallContext(fcinfo,NULL));
20432066

2044-
state=PG_ARGISNULL(0) ?NULL : (StringInfo)PG_GETARG_POINTER(0);
2067+
state=PG_ARGISNULL(0) ?NULL : (JsonAggState*)PG_GETARG_POINTER(0);
20452068

20462069
/* NULL result for no rows in, as is standard with aggregates */
20472070
if (state==NULL)
20482071
PG_RETURN_NULL();
20492072

20502073
/* Else return state with appropriate object terminator added */
2051-
PG_RETURN_TEXT_P(catenate_stringinfo_string(state," }"));
2074+
PG_RETURN_TEXT_P(catenate_stringinfo_string(state->str," }"));
20522075
}
20532076

20542077
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp