From d05e1fc82a51cb583a0367e72b1afc0de561dd00 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 15 Jan 2020 10:36:52 -0500 Subject: [PATCH 4/6] Introduce json_error() macro. --- src/backend/utils/adt/jsonapi.c | 221 +++++++++++++------------------- 1 file changed, 90 insertions(+), 131 deletions(-) diff --git a/src/backend/utils/adt/jsonapi.c b/src/backend/utils/adt/jsonapi.c index fc8af9f861..20f7f0f7ac 100644 --- a/src/backend/utils/adt/jsonapi.c +++ b/src/backend/utils/adt/jsonapi.c @@ -17,6 +17,9 @@ #include "miscadmin.h" #include "utils/jsonapi.h" +#define json_error(rest) \ + ereport(ERROR, (rest, report_json_context(lex))) + /* * The context of the parser is maintained by the recursive descent * mechanism, but is passed explicitly to the error reporting routine @@ -163,6 +166,7 @@ IsValidJsonNumber(const char *str, int len) return (!numeric_error) && (total_len == dummy_lex.input_length); } +#ifndef FRONTEND /* * makeJsonLexContext * @@ -182,6 +186,7 @@ makeJsonLexContext(text *json, bool need_escapes) VARSIZE_ANY_EXHDR(json), need_escapes); } +#endif JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes) @@ -659,12 +664,10 @@ json_lex_string(JsonLexContext *lex) /* Per RFC4627, these characters MUST be escaped. */ /* Since *s isn't printable, exclude it from the context string */ lex->token_terminator = s; - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Character with value 0x%02x must be escaped.", - (unsigned char) *s), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Character with value 0x%02x must be escaped.", + (unsigned char) *s))); } else if (*s == '\\') { @@ -699,12 +702,10 @@ json_lex_string(JsonLexContext *lex) else { lex->token_terminator = s + pg_mblen(s); - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", - "json"), - errdetail("\"\\u\" must be followed by four hexadecimal digits."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", + "json"), + errdetail("\"\\u\" must be followed by four hexadecimal digits."))); } } if (lex->strval != NULL) @@ -715,33 +716,27 @@ json_lex_string(JsonLexContext *lex) if (ch >= 0xd800 && ch <= 0xdbff) { if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", - "json"), - errdetail("Unicode high surrogate must not follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", + "json"), + errdetail("Unicode high surrogate must not follow a high surrogate."))); hi_surrogate = (ch & 0x3ff) << 10; continue; } else if (ch >= 0xdc00 && ch <= 0xdfff) { if (hi_surrogate == -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Unicode low surrogate must follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Unicode low surrogate must follow a high surrogate."))); ch = 0x10000 + hi_surrogate + (ch & 0x3ff); hi_surrogate = -1; } if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Unicode low surrogate must follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Unicode low surrogate must follow a high surrogate."))); /* * For UTF8, replace the escape sequence by the actual @@ -753,11 +748,9 @@ json_lex_string(JsonLexContext *lex) if (ch == 0) { /* We can't allow this, since our TEXT type doesn't */ - ereport(ERROR, - (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), - errmsg("unsupported Unicode escape sequence"), - errdetail("\\u0000 cannot be converted to text."), - report_json_context(lex))); + json_error((errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), + errmsg("unsupported Unicode escape sequence"), + errdetail("\\u0000 cannot be converted to text."))); } else if (GetDatabaseEncoding() == PG_UTF8) { @@ -776,11 +769,9 @@ json_lex_string(JsonLexContext *lex) } else { - ereport(ERROR, - (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), - errmsg("unsupported Unicode escape sequence"), - errdetail("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."), - report_json_context(lex))); + json_error((errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), + errmsg("unsupported Unicode escape sequence"), + errdetail("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."))); } } @@ -788,12 +779,10 @@ json_lex_string(JsonLexContext *lex) else if (lex->strval != NULL) { if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", - "json"), - errdetail("Unicode low surrogate must follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", + "json"), + errdetail("Unicode low surrogate must follow a high surrogate."))); switch (*s) { @@ -820,13 +809,11 @@ json_lex_string(JsonLexContext *lex) default: /* Not a valid string escape, so error out. */ lex->token_terminator = s + pg_mblen(s); - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", - "json"), - errdetail("Escape sequence \"\\%s\" is invalid.", - extract_mb_char(s)), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", + "json"), + errdetail("Escape sequence \"\\%s\" is invalid.", + extract_mb_char(s)))); } } else if (strchr("\"\\/bfnrt", *s) == NULL) @@ -839,23 +826,19 @@ json_lex_string(JsonLexContext *lex) * shown it's not a performance win. */ lex->token_terminator = s + pg_mblen(s); - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Escape sequence \"\\%s\" is invalid.", - extract_mb_char(s)), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Escape sequence \"\\%s\" is invalid.", + extract_mb_char(s)))); } } else if (lex->strval != NULL) { if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Unicode low surrogate must follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Unicode low surrogate must follow a high surrogate."))); appendStringInfoChar(lex->strval, *s); } @@ -863,11 +846,9 @@ json_lex_string(JsonLexContext *lex) } if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Unicode low surrogate must follow a high surrogate."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Unicode low surrogate must follow a high surrogate."))); /* Hooray, we found the end of the string! */ lex->prev_token_terminator = lex->token_terminator; @@ -1008,11 +989,9 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex) /* Handle case where the input ended prematurely. */ if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("The input string ended unexpectedly."), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("The input string ended unexpectedly."))); /* Separate out the current token. */ toklen = lex->token_terminator - lex->token_start; @@ -1022,79 +1001,61 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex) /* Complain, with the appropriate detail message. */ if (ctx == JSON_PARSE_END) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected end of input, but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected end of input, but found \"%s\".", + token))); else { switch (ctx) { case JSON_PARSE_VALUE: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected JSON value, but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected JSON value, but found \"%s\".", + token))); break; case JSON_PARSE_STRING: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected string, but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected string, but found \"%s\".", + token))); break; case JSON_PARSE_ARRAY_START: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected array element or \"]\", but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected array element or \"]\", but found \"%s\".", + token))); break; case JSON_PARSE_ARRAY_NEXT: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected \",\" or \"]\", but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected \",\" or \"]\", but found \"%s\".", + token))); break; case JSON_PARSE_OBJECT_START: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected string or \"}\", but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected string or \"}\", but found \"%s\".", + token))); break; case JSON_PARSE_OBJECT_LABEL: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected \":\", but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected \":\", but found \"%s\".", + token))); break; case JSON_PARSE_OBJECT_NEXT: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected \",\" or \"}\", but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected \",\" or \"}\", but found \"%s\".", + token))); break; case JSON_PARSE_OBJECT_COMMA: - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Expected string, but found \"%s\".", - token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Expected string, but found \"%s\".", + token))); break; default: elog(ERROR, "unexpected json parse state: %d", ctx); @@ -1119,11 +1080,9 @@ report_invalid_token(JsonLexContext *lex) memcpy(token, lex->token_start, toklen); token[toklen] = '\0'; - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s", "json"), - errdetail("Token \"%s\" is invalid.", token), - report_json_context(lex))); + json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s", "json"), + errdetail("Token \"%s\" is invalid.", token))); } /* -- 2.17.2 (Apple Git-113)