aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/adt/jsonb.c36
-rw-r--r--src/backend/utils/adt/jsonfuncs.c356
-rw-r--r--src/bin/pg_verifybackup/parse_manifest.c40
-rw-r--r--src/common/jsonapi.c57
-rw-r--r--src/include/common/jsonapi.h21
5 files changed, 342 insertions, 168 deletions
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 9e14922ec24..a6d8fdb0682 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -63,13 +63,13 @@ typedef struct JsonbAggState
static inline Datum jsonb_from_cstring(char *json, int len);
static size_t checkStringLen(size_t len);
-static void jsonb_in_object_start(void *pstate);
-static void jsonb_in_object_end(void *pstate);
-static void jsonb_in_array_start(void *pstate);
-static void jsonb_in_array_end(void *pstate);
-static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
+static JsonParseErrorType jsonb_in_object_start(void *pstate);
+static JsonParseErrorType jsonb_in_object_end(void *pstate);
+static JsonParseErrorType jsonb_in_array_start(void *pstate);
+static JsonParseErrorType jsonb_in_array_end(void *pstate);
+static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
-static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
+static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
static void jsonb_categorize_type(Oid typoid,
JsonbTypeCategory *tcategory,
Oid *outfuncoid);
@@ -291,39 +291,47 @@ checkStringLen(size_t len)
return len;
}
-static void
+static JsonParseErrorType
jsonb_in_object_start(void *pstate)
{
JsonbInState *_state = (JsonbInState *) pstate;
_state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
jsonb_in_object_end(void *pstate)
{
JsonbInState *_state = (JsonbInState *) pstate;
_state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
jsonb_in_array_start(void *pstate)
{
JsonbInState *_state = (JsonbInState *) pstate;
_state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
jsonb_in_array_end(void *pstate)
{
JsonbInState *_state = (JsonbInState *) pstate;
_state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
{
JsonbInState *_state = (JsonbInState *) pstate;
@@ -335,6 +343,8 @@ jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
v.val.string.val = fname;
_state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
+
+ return JSON_SUCCESS;
}
static void
@@ -367,7 +377,7 @@ jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
/*
* For jsonb we always want the de-escaped value - that's what's in token
*/
-static void
+static JsonParseErrorType
jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
{
JsonbInState *_state = (JsonbInState *) pstate;
@@ -443,6 +453,8 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
elog(ERROR, "unexpected parent of nested structure");
}
}
+
+ return JSON_SUCCESS;
}
/*
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index bfc3f02a863..d6cad952790 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -336,20 +336,20 @@ typedef struct JsObject
static int report_json_context(JsonLexContext *lex);
/* semantic action functions for json_object_keys */
-static void okeys_object_field_start(void *state, char *fname, bool isnull);
-static void okeys_array_start(void *state);
-static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType okeys_array_start(void *state);
+static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype);
/* semantic action functions for json_get* functions */
-static void get_object_start(void *state);
-static void get_object_end(void *state);
-static void get_object_field_start(void *state, char *fname, bool isnull);
-static void get_object_field_end(void *state, char *fname, bool isnull);
-static void get_array_start(void *state);
-static void get_array_end(void *state);
-static void get_array_element_start(void *state, bool isnull);
-static void get_array_element_end(void *state, bool isnull);
-static void get_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType get_object_start(void *state);
+static JsonParseErrorType get_object_end(void *state);
+static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull);
+static JsonParseErrorType get_array_start(void *state);
+static JsonParseErrorType get_array_end(void *state);
+static JsonParseErrorType get_array_element_start(void *state, bool isnull);
+static JsonParseErrorType get_array_element_end(void *state, bool isnull);
+static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype);
/* common worker function for json getter functions */
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
@@ -359,9 +359,9 @@ static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
static text *JsonbValueAsText(JsonbValue *v);
/* semantic action functions for json_array_length */
-static void alen_object_start(void *state);
-static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
-static void alen_array_element_start(void *state, bool isnull);
+static JsonParseErrorType alen_object_start(void *state);
+static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType alen_array_element_start(void *state, bool isnull);
/* common workers for json{b}_each* functions */
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
@@ -369,10 +369,10 @@ static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
bool as_text);
/* semantic action functions for json_each */
-static void each_object_field_start(void *state, char *fname, bool isnull);
-static void each_object_field_end(void *state, char *fname, bool isnull);
-static void each_array_start(void *state);
-static void each_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull);
+static JsonParseErrorType each_array_start(void *state);
+static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype);
/* common workers for json{b}_array_elements_* functions */
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
@@ -381,44 +381,44 @@ static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname
bool as_text);
/* semantic action functions for json_array_elements */
-static void elements_object_start(void *state);
-static void elements_array_element_start(void *state, bool isnull);
-static void elements_array_element_end(void *state, bool isnull);
-static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType elements_object_start(void *state);
+static JsonParseErrorType elements_array_element_start(void *state, bool isnull);
+static JsonParseErrorType elements_array_element_end(void *state, bool isnull);
+static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype);
/* turn a json object into a hash table */
static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname);
/* semantic actions for populate_array_json */
-static void populate_array_object_start(void *_state);
-static void populate_array_array_end(void *_state);
-static void populate_array_element_start(void *_state, bool isnull);
-static void populate_array_element_end(void *_state, bool isnull);
-static void populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType populate_array_object_start(void *_state);
+static JsonParseErrorType populate_array_array_end(void *_state);
+static JsonParseErrorType populate_array_element_start(void *_state, bool isnull);
+static JsonParseErrorType populate_array_element_end(void *_state, bool isnull);
+static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
/* semantic action functions for get_json_object_as_hash */
-static void hash_object_field_start(void *state, char *fname, bool isnull);
-static void hash_object_field_end(void *state, char *fname, bool isnull);
-static void hash_array_start(void *state);
-static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull);
+static JsonParseErrorType hash_array_start(void *state);
+static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype);
/* semantic action functions for populate_recordset */
-static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
-static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
-static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
-static void populate_recordset_object_start(void *state);
-static void populate_recordset_object_end(void *state);
-static void populate_recordset_array_start(void *state);
-static void populate_recordset_array_element_start(void *state, bool isnull);
+static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull);
+static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType populate_recordset_object_start(void *state);
+static JsonParseErrorType populate_recordset_object_end(void *state);
+static JsonParseErrorType populate_recordset_array_start(void *state);
+static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull);
/* semantic action functions for json_strip_nulls */
-static void sn_object_start(void *state);
-static void sn_object_end(void *state);
-static void sn_array_start(void *state);
-static void sn_array_end(void *state);
-static void sn_object_field_start(void *state, char *fname, bool isnull);
-static void sn_array_element_start(void *state, bool isnull);
-static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType sn_object_start(void *state);
+static JsonParseErrorType sn_object_end(void *state);
+static JsonParseErrorType sn_array_start(void *state);
+static JsonParseErrorType sn_array_end(void *state);
+static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType sn_array_element_start(void *state, bool isnull);
+static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype);
/* worker functions for populate_record, to_record, populate_recordset and to_recordset */
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
@@ -478,17 +478,17 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems,
JsonbValue *newval, uint32 nelems, int op_type);
/* function supporting iterate_json_values */
-static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
-static void iterate_values_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull);
/* functions supporting transform_json_string_values */
-static void transform_string_values_object_start(void *state);
-static void transform_string_values_object_end(void *state);
-static void transform_string_values_array_start(void *state);
-static void transform_string_values_array_end(void *state);
-static void transform_string_values_object_field_start(void *state, char *fname, bool isnull);
-static void transform_string_values_array_element_start(void *state, bool isnull);
-static void transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
+static JsonParseErrorType transform_string_values_object_start(void *state);
+static JsonParseErrorType transform_string_values_object_end(void *state);
+static JsonParseErrorType transform_string_values_array_start(void *state);
+static JsonParseErrorType transform_string_values_array_end(void *state);
+static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull);
+static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull);
+static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
/*
* pg_parse_json_or_ereport
@@ -745,14 +745,14 @@ json_object_keys(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx);
}
-static void
+static JsonParseErrorType
okeys_object_field_start(void *state, char *fname, bool isnull)
{
OkeysState *_state = (OkeysState *) state;
/* only collecting keys for the top level object */
if (_state->lex->lex_level != 1)
- return;
+ return JSON_SUCCESS;
/* enlarge result array if necessary */
if (_state->result_count >= _state->result_size)
@@ -764,9 +764,11 @@ okeys_object_field_start(void *state, char *fname, bool isnull)
/* save a copy of the field name */
_state->result[_state->result_count++] = pstrdup(fname);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
okeys_array_start(void *state)
{
OkeysState *_state = (OkeysState *) state;
@@ -777,9 +779,11 @@ okeys_array_start(void *state)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call %s on an array",
"json_object_keys")));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
okeys_scalar(void *state, char *token, JsonTokenType tokentype)
{
OkeysState *_state = (OkeysState *) state;
@@ -790,6 +794,8 @@ okeys_scalar(void *state, char *token, JsonTokenType tokentype)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call %s on a scalar",
"json_object_keys")));
+
+ return JSON_SUCCESS;
}
/*
@@ -1112,7 +1118,7 @@ get_worker(text *json,
return state->tresult;
}
-static void
+static JsonParseErrorType
get_object_start(void *state)
{
GetState *_state = (GetState *) state;
@@ -1127,9 +1133,11 @@ get_object_start(void *state)
*/
_state->result_start = _state->lex->token_start;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_object_end(void *state)
{
GetState *_state = (GetState *) state;
@@ -1143,9 +1151,11 @@ get_object_end(void *state)
_state->tresult = cstring_to_text_with_len(start, len);
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_object_field_start(void *state, char *fname, bool isnull)
{
GetState *_state = (GetState *) state;
@@ -1188,9 +1198,11 @@ get_object_field_start(void *state, char *fname, bool isnull)
_state->result_start = _state->lex->token_start;
}
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_object_field_end(void *state, char *fname, bool isnull)
{
GetState *_state = (GetState *) state;
@@ -1237,9 +1249,11 @@ get_object_field_end(void *state, char *fname, bool isnull)
/* this should be unnecessary but let's do it for cleanliness: */
_state->result_start = NULL;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_array_start(void *state)
{
GetState *_state = (GetState *) state;
@@ -1275,9 +1289,11 @@ get_array_start(void *state)
*/
_state->result_start = _state->lex->token_start;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_array_end(void *state)
{
GetState *_state = (GetState *) state;
@@ -1291,9 +1307,11 @@ get_array_end(void *state)
_state->tresult = cstring_to_text_with_len(start, len);
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_array_element_start(void *state, bool isnull)
{
GetState *_state = (GetState *) state;
@@ -1337,9 +1355,11 @@ get_array_element_start(void *state, bool isnull)
_state->result_start = _state->lex->token_start;
}
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_array_element_end(void *state, bool isnull)
{
GetState *_state = (GetState *) state;
@@ -1379,9 +1399,11 @@ get_array_element_end(void *state, bool isnull)
_state->result_start = NULL;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
get_scalar(void *state, char *token, JsonTokenType tokentype)
{
GetState *_state = (GetState *) state;
@@ -1420,6 +1442,8 @@ get_scalar(void *state, char *token, JsonTokenType tokentype)
/* make sure the next call to get_scalar doesn't overwrite it */
_state->next_scalar = false;
}
+
+ return JSON_SUCCESS;
}
Datum
@@ -1834,7 +1858,7 @@ jsonb_array_length(PG_FUNCTION_ARGS)
* a scalar or an object).
*/
-static void
+static JsonParseErrorType
alen_object_start(void *state)
{
AlenState *_state = (AlenState *) state;
@@ -1844,9 +1868,11 @@ alen_object_start(void *state)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot get array length of a non-array")));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
alen_scalar(void *state, char *token, JsonTokenType tokentype)
{
AlenState *_state = (AlenState *) state;
@@ -1856,9 +1882,11 @@ alen_scalar(void *state, char *token, JsonTokenType tokentype)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot get array length of a scalar")));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
alen_array_element_start(void *state, bool isnull)
{
AlenState *_state = (AlenState *) state;
@@ -1866,6 +1894,8 @@ alen_array_element_start(void *state, bool isnull)
/* just count up all the level 1 elements */
if (_state->lex->lex_level == 1)
_state->count++;
+
+ return JSON_SUCCESS;
}
/*
@@ -2026,7 +2056,7 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
}
-static void
+static JsonParseErrorType
each_object_field_start(void *state, char *fname, bool isnull)
{
EachState *_state = (EachState *) state;
@@ -2044,9 +2074,11 @@ each_object_field_start(void *state, char *fname, bool isnull)
else
_state->result_start = _state->lex->token_start;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
each_object_field_end(void *state, char *fname, bool isnull)
{
EachState *_state = (EachState *) state;
@@ -2059,7 +2091,7 @@ each_object_field_end(void *state, char *fname, bool isnull)
/* skip over nested objects */
if (_state->lex->lex_level != 1)
- return;
+ return JSON_SUCCESS;
/* use the tmp context so we can clean up after each tuple is done */
old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
@@ -2090,9 +2122,11 @@ each_object_field_end(void *state, char *fname, bool isnull)
/* clean up and switch back */
MemoryContextSwitchTo(old_cxt);
MemoryContextReset(_state->tmp_cxt);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
each_array_start(void *state)
{
EachState *_state = (EachState *) state;
@@ -2102,9 +2136,11 @@ each_array_start(void *state)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot deconstruct an array as an object")));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
each_scalar(void *state, char *token, JsonTokenType tokentype)
{
EachState *_state = (EachState *) state;
@@ -2118,6 +2154,8 @@ each_scalar(void *state, char *token, JsonTokenType tokentype)
/* supply de-escaped value if required */
if (_state->next_scalar)
_state->normalized_scalar = token;
+
+ return JSON_SUCCESS;
}
/*
@@ -2268,7 +2306,7 @@ elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
PG_RETURN_NULL();
}
-static void
+static JsonParseErrorType
elements_array_element_start(void *state, bool isnull)
{
ElementsState *_state = (ElementsState *) state;
@@ -2286,9 +2324,11 @@ elements_array_element_start(void *state, bool isnull)
else
_state->result_start = _state->lex->token_start;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
elements_array_element_end(void *state, bool isnull)
{
ElementsState *_state = (ElementsState *) state;
@@ -2301,7 +2341,7 @@ elements_array_element_end(void *state, bool isnull)
/* skip over nested objects */
if (_state->lex->lex_level != 1)
- return;
+ return JSON_SUCCESS;
/* use the tmp context so we can clean up after each tuple is done */
old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
@@ -2330,9 +2370,11 @@ elements_array_element_end(void *state, bool isnull)
/* clean up and switch back */
MemoryContextSwitchTo(old_cxt);
MemoryContextReset(_state->tmp_cxt);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
elements_object_start(void *state)
{
ElementsState *_state = (ElementsState *) state;
@@ -2343,9 +2385,11 @@ elements_object_start(void *state)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call %s on a non-array",
_state->function_name)));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
elements_scalar(void *state, char *token, JsonTokenType tokentype)
{
ElementsState *_state = (ElementsState *) state;
@@ -2360,6 +2404,8 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
/* supply de-escaped value if required */
if (_state->next_scalar)
_state->normalized_scalar = token;
+
+ return JSON_SUCCESS;
}
/*
@@ -2508,7 +2554,7 @@ populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
}
/* json object start handler for populate_array_json() */
-static void
+static JsonParseErrorType
populate_array_object_start(void *_state)
{
PopulateArrayState *state = (PopulateArrayState *) _state;
@@ -2518,10 +2564,12 @@ populate_array_object_start(void *_state)
populate_array_assign_ndims(state->ctx, ndim);
else if (ndim < state->ctx->ndims)
populate_array_report_expected_array(state->ctx, ndim);
+
+ return JSON_SUCCESS;
}
/* json array end handler for populate_array_json() */
-static void
+static JsonParseErrorType
populate_array_array_end(void *_state)
{
PopulateArrayState *state = (PopulateArrayState *) _state;
@@ -2533,10 +2581,12 @@ populate_array_array_end(void *_state)
if (ndim < ctx->ndims)
populate_array_check_dimension(ctx, ndim);
+
+ return JSON_SUCCESS;
}
/* json array element start handler for populate_array_json() */
-static void
+static JsonParseErrorType
populate_array_element_start(void *_state, bool isnull)
{
PopulateArrayState *state = (PopulateArrayState *) _state;
@@ -2549,10 +2599,12 @@ populate_array_element_start(void *_state, bool isnull)
state->element_type = state->lex->token_type;
state->element_scalar = NULL;
}
+
+ return JSON_SUCCESS;
}
/* json array element end handler for populate_array_json() */
-static void
+static JsonParseErrorType
populate_array_element_end(void *_state, bool isnull)
{
PopulateArrayState *state = (PopulateArrayState *) _state;
@@ -2588,10 +2640,12 @@ populate_array_element_end(void *_state, bool isnull)
populate_array_element(ctx, ndim, &jsv);
}
+
+ return JSON_SUCCESS;
}
/* json scalar handler for populate_array_json() */
-static void
+static JsonParseErrorType
populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
{
PopulateArrayState *state = (PopulateArrayState *) _state;
@@ -2610,6 +2664,8 @@ populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
/* element_type must already be set in populate_array_element_start() */
Assert(state->element_type == tokentype);
}
+
+ return JSON_SUCCESS;
}
/* parse a json array and populate array */
@@ -3491,13 +3547,13 @@ get_json_object_as_hash(char *json, int len, const char *funcname)
return tab;
}
-static void
+static JsonParseErrorType
hash_object_field_start(void *state, char *fname, bool isnull)
{
JHashState *_state = (JHashState *) state;
if (_state->lex->lex_level > 1)
- return;
+ return JSON_SUCCESS;
/* remember token type */
_state->saved_token_type = _state->lex->token_type;
@@ -3513,9 +3569,11 @@ hash_object_field_start(void *state, char *fname, bool isnull)
/* must be a scalar */
_state->save_json_start = NULL;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
hash_object_field_end(void *state, char *fname, bool isnull)
{
JHashState *_state = (JHashState *) state;
@@ -3526,7 +3584,7 @@ hash_object_field_end(void *state, char *fname, bool isnull)
* Ignore nested fields.
*/
if (_state->lex->lex_level > 1)
- return;
+ return JSON_SUCCESS;
/*
* Ignore field names >= NAMEDATALEN - they can't match a record field.
@@ -3536,7 +3594,7 @@ hash_object_field_end(void *state, char *fname, bool isnull)
* has previously insisted on exact equality, so we keep this behavior.)
*/
if (strlen(fname) >= NAMEDATALEN)
- return;
+ return JSON_SUCCESS;
hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
@@ -3562,9 +3620,11 @@ hash_object_field_end(void *state, char *fname, bool isnull)
/* must have had a scalar instead */
hashentry->val = _state->saved_scalar;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
hash_array_start(void *state)
{
JHashState *_state = (JHashState *) state;
@@ -3573,9 +3633,11 @@ hash_array_start(void *state)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call %s on an array", _state->function_name)));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
hash_scalar(void *state, char *token, JsonTokenType tokentype)
{
JHashState *_state = (JHashState *) state;
@@ -3591,6 +3653,8 @@ hash_scalar(void *state, char *token, JsonTokenType tokentype)
/* saved_token_type must already be set in hash_object_field_start() */
Assert(_state->saved_token_type == tokentype);
}
+
+ return JSON_SUCCESS;
}
@@ -3840,7 +3904,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
PG_RETURN_NULL();
}
-static void
+static JsonParseErrorType
populate_recordset_object_start(void *state)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
@@ -3856,7 +3920,7 @@ populate_recordset_object_start(void *state)
/* Nested objects require no special processing */
if (lex_level > 1)
- return;
+ return JSON_SUCCESS;
/* Object at level 1: set up a new hash table for this object */
ctl.keysize = NAMEDATALEN;
@@ -3866,9 +3930,11 @@ populate_recordset_object_start(void *state)
100,
&ctl,
HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_object_end(void *state)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
@@ -3876,7 +3942,7 @@ populate_recordset_object_end(void *state)
/* Nested objects require no special processing */
if (_state->lex->lex_level > 1)
- return;
+ return JSON_SUCCESS;
obj.is_json = true;
obj.val.json_hash = _state->json_hash;
@@ -3887,9 +3953,11 @@ populate_recordset_object_end(void *state)
/* Done with hash for this object */
hash_destroy(_state->json_hash);
_state->json_hash = NULL;
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_array_element_start(void *state, bool isnull)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
@@ -3900,15 +3968,18 @@ populate_recordset_array_element_start(void *state, bool isnull)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("argument of %s must be an array of objects",
_state->function_name)));
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_array_start(void *state)
{
/* nothing to do */
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
@@ -3921,15 +3992,17 @@ populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
if (_state->lex->lex_level == 2)
_state->saved_scalar = token;
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_object_field_start(void *state, char *fname, bool isnull)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
if (_state->lex->lex_level > 2)
- return;
+ return JSON_SUCCESS;
_state->saved_token_type = _state->lex->token_type;
@@ -3942,9 +4015,11 @@ populate_recordset_object_field_start(void *state, char *fname, bool isnull)
{
_state->save_json_start = NULL;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
populate_recordset_object_field_end(void *state, char *fname, bool isnull)
{
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
@@ -3955,7 +4030,7 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
* Ignore nested fields.
*/
if (_state->lex->lex_level > 2)
- return;
+ return JSON_SUCCESS;
/*
* Ignore field names >= NAMEDATALEN - they can't match a record field.
@@ -3965,7 +4040,7 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
* has previously insisted on exact equality, so we keep this behavior.)
*/
if (strlen(fname) >= NAMEDATALEN)
- return;
+ return JSON_SUCCESS;
hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
@@ -3991,6 +4066,8 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
/* must have had a scalar instead */
hashentry->val = _state->saved_scalar;
}
+
+ return JSON_SUCCESS;
}
/*
@@ -4002,39 +4079,47 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
* is called.
*/
-static void
+static JsonParseErrorType
sn_object_start(void *state)
{
StripnullState *_state = (StripnullState *) state;
appendStringInfoCharMacro(_state->strval, '{');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_object_end(void *state)
{
StripnullState *_state = (StripnullState *) state;
appendStringInfoCharMacro(_state->strval, '}');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_array_start(void *state)
{
StripnullState *_state = (StripnullState *) state;
appendStringInfoCharMacro(_state->strval, '[');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_array_end(void *state)
{
StripnullState *_state = (StripnullState *) state;
appendStringInfoCharMacro(_state->strval, ']');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_object_field_start(void *state, char *fname, bool isnull)
{
StripnullState *_state = (StripnullState *) state;
@@ -4047,7 +4132,7 @@ sn_object_field_start(void *state, char *fname, bool isnull)
* object or array. The flag will be reset in the scalar action.
*/
_state->skip_next_null = true;
- return;
+ return JSON_SUCCESS;
}
if (_state->strval->data[_state->strval->len - 1] != '{')
@@ -4060,18 +4145,22 @@ sn_object_field_start(void *state, char *fname, bool isnull)
escape_json(_state->strval, fname);
appendStringInfoCharMacro(_state->strval, ':');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_array_element_start(void *state, bool isnull)
{
StripnullState *_state = (StripnullState *) state;
if (_state->strval->data[_state->strval->len - 1] != '[')
appendStringInfoCharMacro(_state->strval, ',');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
sn_scalar(void *state, char *token, JsonTokenType tokentype)
{
StripnullState *_state = (StripnullState *) state;
@@ -4080,13 +4169,15 @@ sn_scalar(void *state, char *token, JsonTokenType tokentype)
{
Assert(tokentype == JSON_TOKEN_NULL);
_state->skip_next_null = false;
- return;
+ return JSON_SUCCESS;
}
if (tokentype == JSON_TOKEN_STRING)
escape_json(_state->strval, token);
else
appendStringInfoString(_state->strval, token);
+
+ return JSON_SUCCESS;
}
/*
@@ -5326,7 +5417,7 @@ iterate_json_values(text *json, uint32 flags, void *action_state,
* An auxiliary function for iterate_json_values to invoke a specified
* JsonIterateStringValuesAction for specified values.
*/
-static void
+static JsonParseErrorType
iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
{
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
@@ -5350,9 +5441,11 @@ iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
/* do not call callback for any other token */
break;
}
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
iterate_values_object_field_start(void *state, char *fname, bool isnull)
{
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
@@ -5363,6 +5456,8 @@ iterate_values_object_field_start(void *state, char *fname, bool isnull)
_state->action(_state->action_state, val, strlen(val));
}
+
+ return JSON_SUCCESS;
}
/*
@@ -5430,7 +5525,6 @@ transform_json_string_values(text *json, void *action_state,
state->action_state = action_state;
sem->semstate = (void *) state;
- sem->scalar = transform_string_values_scalar;
sem->object_start = transform_string_values_object_start;
sem->object_end = transform_string_values_object_end;
sem->array_start = transform_string_values_array_start;
@@ -5449,39 +5543,47 @@ transform_json_string_values(text *json, void *action_state,
* specified JsonTransformStringValuesAction for all values and left everything
* else untouched.
*/
-static void
+static JsonParseErrorType
transform_string_values_object_start(void *state)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
appendStringInfoCharMacro(_state->strval, '{');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_object_end(void *state)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
appendStringInfoCharMacro(_state->strval, '}');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_array_start(void *state)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
appendStringInfoCharMacro(_state->strval, '[');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_array_end(void *state)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
appendStringInfoCharMacro(_state->strval, ']');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_object_field_start(void *state, char *fname, bool isnull)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
@@ -5495,18 +5597,22 @@ transform_string_values_object_field_start(void *state, char *fname, bool isnull
*/
escape_json(_state->strval, fname);
appendStringInfoCharMacro(_state->strval, ':');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_array_element_start(void *state, bool isnull)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
if (_state->strval->data[_state->strval->len - 1] != '[')
appendStringInfoCharMacro(_state->strval, ',');
+
+ return JSON_SUCCESS;
}
-static void
+static JsonParseErrorType
transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
{
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
@@ -5519,4 +5625,6 @@ transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype
}
else
appendStringInfoString(_state->strval, token);
+
+ return JSON_SUCCESS;
}
diff --git a/src/bin/pg_verifybackup/parse_manifest.c b/src/bin/pg_verifybackup/parse_manifest.c
index 6364b012821..beff018e183 100644
--- a/src/bin/pg_verifybackup/parse_manifest.c
+++ b/src/bin/pg_verifybackup/parse_manifest.c
@@ -88,14 +88,14 @@ typedef struct
char *manifest_checksum;
} JsonManifestParseState;
-static void json_manifest_object_start(void *state);
-static void json_manifest_object_end(void *state);
-static void json_manifest_array_start(void *state);
-static void json_manifest_array_end(void *state);
-static void json_manifest_object_field_start(void *state, char *fname,
- bool isnull);
-static void json_manifest_scalar(void *state, char *token,
- JsonTokenType tokentype);
+static JsonParseErrorType json_manifest_object_start(void *state);
+static JsonParseErrorType json_manifest_object_end(void *state);
+static JsonParseErrorType json_manifest_array_start(void *state);
+static JsonParseErrorType json_manifest_array_end(void *state);
+static JsonParseErrorType json_manifest_object_field_start(void *state, char *fname,
+ bool isnull);
+static JsonParseErrorType json_manifest_scalar(void *state, char *token,
+ JsonTokenType tokentype);
static void json_manifest_finalize_file(JsonManifestParseState *parse);
static void json_manifest_finalize_wal_range(JsonManifestParseState *parse);
static void verify_manifest_checksum(JsonManifestParseState *parse,
@@ -162,7 +162,7 @@ json_parse_manifest(JsonManifestParseContext *context, char *buffer,
* WAL range is also expected to be an object. If we're anywhere else in the
* document, it's an error.
*/
-static void
+static JsonParseErrorType
json_manifest_object_start(void *state)
{
JsonManifestParseState *parse = state;
@@ -191,6 +191,8 @@ json_manifest_object_start(void *state)
"unexpected object start");
break;
}
+
+ return JSON_SUCCESS;
}
/*
@@ -201,7 +203,7 @@ json_manifest_object_start(void *state)
* reach the end of an object representing a particular file or WAL range,
* we must call json_manifest_finalize_file() to save the associated details.
*/
-static void
+static JsonParseErrorType
json_manifest_object_end(void *state)
{
JsonManifestParseState *parse = state;
@@ -224,6 +226,8 @@ json_manifest_object_end(void *state)
"unexpected object end");
break;
}
+
+ return JSON_SUCCESS;
}
/*
@@ -233,7 +237,7 @@ json_manifest_object_end(void *state)
* should be an array. Similarly for the "WAL-Ranges" key. No other arrays
* are expected.
*/
-static void
+static JsonParseErrorType
json_manifest_array_start(void *state)
{
JsonManifestParseState *parse = state;
@@ -251,6 +255,8 @@ json_manifest_array_start(void *state)
"unexpected array start");
break;
}
+
+ return JSON_SUCCESS;
}
/*
@@ -258,7 +264,7 @@ json_manifest_array_start(void *state)
*
* The cases here are analogous to those in json_manifest_array_start.
*/
-static void
+static JsonParseErrorType
json_manifest_array_end(void *state)
{
JsonManifestParseState *parse = state;
@@ -274,12 +280,14 @@ json_manifest_array_end(void *state)
"unexpected array end");
break;
}
+
+ return JSON_SUCCESS;
}
/*
* Invoked at the start of each object field in the JSON document.
*/
-static void
+static JsonParseErrorType
json_manifest_object_field_start(void *state, char *fname, bool isnull)
{
JsonManifestParseState *parse = state;
@@ -367,6 +375,8 @@ json_manifest_object_field_start(void *state, char *fname, bool isnull)
"unexpected object field");
break;
}
+
+ return JSON_SUCCESS;
}
/*
@@ -384,7 +394,7 @@ json_manifest_object_field_start(void *state, char *fname, bool isnull)
* reach either the end of the object representing this file, or the end
* of the manifest, as the case may be.
*/
-static void
+static JsonParseErrorType
json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
{
JsonManifestParseState *parse = state;
@@ -448,6 +458,8 @@ json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
json_manifest_parse_failure(parse->context, "unexpected scalar");
break;
}
+
+ return JSON_SUCCESS;
}
/*
diff --git a/src/common/jsonapi.c b/src/common/jsonapi.c
index 873357aa02e..83c286b89ba 100644
--- a/src/common/jsonapi.c
+++ b/src/common/jsonapi.c
@@ -298,9 +298,9 @@ parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
return result;
/* invoke the callback */
- (*sfunc) (sem->semstate, val, tok);
+ result = (*sfunc) (sem->semstate, val, tok);
- return JSON_SUCCESS;
+ return result;
}
static JsonParseErrorType
@@ -335,7 +335,11 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
isnull = tok == JSON_TOKEN_NULL;
if (ostart != NULL)
- (*ostart) (sem->semstate, fname, isnull);
+ {
+ result = (*ostart) (sem->semstate, fname, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
switch (tok)
{
@@ -352,7 +356,12 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
return result;
if (oend != NULL)
- (*oend) (sem->semstate, fname, isnull);
+ {
+ result = (*oend) (sem->semstate, fname, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
return JSON_SUCCESS;
}
@@ -373,7 +382,11 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem)
#endif
if (ostart != NULL)
- (*ostart) (sem->semstate);
+ {
+ result = (*ostart) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
/*
* Data inside an object is at a higher nesting level than the object
@@ -417,7 +430,11 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem)
lex->lex_level--;
if (oend != NULL)
- (*oend) (sem->semstate);
+ {
+ result = (*oend) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
return JSON_SUCCESS;
}
@@ -429,13 +446,16 @@ parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
json_aelem_action aend = sem->array_element_end;
JsonTokenType tok = lex_peek(lex);
JsonParseErrorType result;
-
bool isnull;
isnull = tok == JSON_TOKEN_NULL;
if (astart != NULL)
- (*astart) (sem->semstate, isnull);
+ {
+ result = (*astart) (sem->semstate, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
/* an array element is any object, array or scalar */
switch (tok)
@@ -454,7 +474,11 @@ parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
return result;
if (aend != NULL)
- (*aend) (sem->semstate, isnull);
+ {
+ result = (*aend) (sem->semstate, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
return JSON_SUCCESS;
}
@@ -475,7 +499,11 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem)
#endif
if (astart != NULL)
- (*astart) (sem->semstate);
+ {
+ result = (*astart) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
/*
* Data inside an array is at a higher nesting level than the array
@@ -508,7 +536,11 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem)
lex->lex_level--;
if (aend != NULL)
- (*aend) (sem->semstate);
+ {
+ result = (*aend) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
return JSON_SUCCESS;
}
@@ -1139,6 +1171,9 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
return _("Unicode high surrogate must not follow a high surrogate.");
case JSON_UNICODE_LOW_SURROGATE:
return _("Unicode low surrogate must follow a high surrogate.");
+ case JSON_SEM_ACTION_FAILED:
+ /* fall through to the error code after switch */
+ break;
}
/*
diff --git a/src/include/common/jsonapi.h b/src/include/common/jsonapi.h
index 8d31630e5ce..663064e659d 100644
--- a/src/include/common/jsonapi.h
+++ b/src/include/common/jsonapi.h
@@ -16,7 +16,7 @@
#include "lib/stringinfo.h"
-typedef enum
+typedef enum JsonTokenType
{
JSON_TOKEN_INVALID,
JSON_TOKEN_STRING,
@@ -33,7 +33,7 @@ typedef enum
JSON_TOKEN_END
} JsonTokenType;
-typedef enum
+typedef enum JsonParseErrorType
{
JSON_SUCCESS,
JSON_ESCAPING_INVALID,
@@ -52,7 +52,8 @@ typedef enum
JSON_UNICODE_ESCAPE_FORMAT,
JSON_UNICODE_HIGH_ESCAPE,
JSON_UNICODE_HIGH_SURROGATE,
- JSON_UNICODE_LOW_SURROGATE
+ JSON_UNICODE_LOW_SURROGATE,
+ JSON_SEM_ACTION_FAILED /* error should already be reported */
} JsonParseErrorType;
@@ -84,14 +85,15 @@ typedef struct JsonLexContext
StringInfo strval;
} JsonLexContext;
-typedef void (*json_struct_action) (void *state);
-typedef void (*json_ofield_action) (void *state, char *fname, bool isnull);
-typedef void (*json_aelem_action) (void *state, bool isnull);
-typedef void (*json_scalar_action) (void *state, char *token, JsonTokenType tokentype);
+typedef JsonParseErrorType (*json_struct_action) (void *state);
+typedef JsonParseErrorType (*json_ofield_action) (void *state, char *fname, bool isnull);
+typedef JsonParseErrorType (*json_aelem_action) (void *state, bool isnull);
+typedef JsonParseErrorType (*json_scalar_action) (void *state, char *token, JsonTokenType tokentype);
/*
* Semantic Action structure for use in parsing json.
+ *
* Any of these actions can be NULL, in which case nothing is done at that
* point, Likewise, semstate can be NULL. Using an all-NULL structure amounts
* to doing a pure parse with no side-effects, and is therefore exactly
@@ -100,6 +102,11 @@ typedef void (*json_scalar_action) (void *state, char *token, JsonTokenType toke
* The 'fname' and 'token' strings passed to these actions are palloc'd.
* They are not free'd or used further by the parser, so the action function
* is free to do what it wishes with them.
+ *
+ * All action functions return JsonParseErrorType. If the result isn't
+ * JSON_SUCCESS, the parse is abandoned and that error code is returned.
+ * If it is JSON_SEM_ACTION_FAILED, the action function is responsible
+ * for having reported the error in some appropriate way.
*/
typedef struct JsonSemAction
{