diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 9e14922ec2..a6d8fdb068 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 bfc3f02a86..d6cad95279 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 6364b01282..beff018e18 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 873357aa02..83c286b89b 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 8d31630e5c..663064e659 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 {