diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-12-11 10:39:05 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-12-11 10:39:05 -0500 |
commit | 50428a301d5ad46316cac2192f2ca8d91898aa3c (patch) | |
tree | af6ebd0e69eed53dfdd8f87eb7d36e228d274d5f /src/common/jsonapi.c | |
parent | d02ef65bce6575e10ac0b4e7b8552ff67687c944 (diff) | |
download | postgresql-50428a301d5ad46316cac2192f2ca8d91898aa3c.tar.gz postgresql-50428a301d5ad46316cac2192f2ca8d91898aa3c.zip |
Change JsonSemAction to allow non-throw error reporting.
Formerly, semantic action functions for the JSON parser returned void,
so that there was no way for them to affect the parser's behavior.
That means in particular that they can't force an error exit except by
longjmp'ing. That won't do in the context of our project to make input
functions return errors softly. Hence, change them to return the same
JsonParseErrorType enum value as the parser itself uses. If an action
function returns anything besides JSON_SUCCESS, the parse is abandoned
and that error code is returned.
Action functions can thus easily return the same error conditions that
the parser already knows about. As an escape hatch for expansion, also
invent a code JSON_SEM_ACTION_FAILED that the core parser does not know
the exact meaning of. When returning this code, an action function
must use some out-of-band mechanism for reporting the error details.
This commit simply makes the API change and causes all the existing
action functions to return JSON_SUCCESS, so that there is no actual
change in behavior here. This is long enough and boring enough that
it seemed best to commit it separately from the changes that make
real use of the new mechanism.
In passing, remove a duplicate assignment of
transform_string_values_scalar.
Discussion: https://postgr.es/m/1436686.1670701118@sss.pgh.pa.us
Diffstat (limited to 'src/common/jsonapi.c')
-rw-r--r-- | src/common/jsonapi.c | 57 |
1 files changed, 46 insertions, 11 deletions
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; } /* |