From 92ef37e68a9e95dbfff10e1bb1b369a957987fa4 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 15 Jan 2020 11:08:13 -0500 Subject: [PATCH 5/6] Frontendify jsonapi.c --- src/backend/utils/adt/jsonapi.c | 71 +++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/adt/jsonapi.c b/src/backend/utils/adt/jsonapi.c index 20f7f0f7ac..f355bd9de1 100644 --- a/src/backend/utils/adt/jsonapi.c +++ b/src/backend/utils/adt/jsonapi.c @@ -13,12 +13,44 @@ */ #include "postgres.h" -#include "mb/pg_wchar.h" +#ifdef FRONTEND +#include "common/logging.h" +#include "libpq-fe.h" +#else #include "miscadmin.h" +#endif + +#include "mb/pg_wchar.h" #include "utils/jsonapi.h" +#ifdef FRONTEND +static void json_frontend_error(int dummy) pg_attribute_noreturn(); + +static int dummy; +#define errcode(something) (dummy = 1) +static int errmsg(const char *fmt, ...) pg_attribute_printf(1,2); +static int errdetail(const char *fmt, ...) pg_attribute_printf(1, 2); + +static void json_frontend_error(int dummy) +{ + exit(1); +} +static int errmsg(const char *fmt, ...) +{ + return 1; +} +static int errdetail(const char *fmt, ...) +{ + return 1; +} + +#define json_error(rest) \ + json_frontend_error(rest) +#define check_stack_depth() +#else #define json_error(rest) \ ereport(ERROR, (rest, report_json_context(lex))) +#endif /* * The context of the parser is maintained by the recursive descent @@ -48,7 +80,9 @@ static void parse_array_element(JsonLexContext *lex, JsonSemAction *sem); static void parse_array(JsonLexContext *lex, JsonSemAction *sem); static void report_parse_error(JsonParseContext ctx, JsonLexContext *lex) pg_attribute_noreturn(); static void report_invalid_token(JsonLexContext *lex) pg_attribute_noreturn(); +#ifndef FRONTEND static int report_json_context(JsonLexContext *lex); +#endif static char *extract_mb_char(char *s); /* the null action object used for pure validation */ @@ -701,7 +735,11 @@ json_lex_string(JsonLexContext *lex) ch = (ch * 16) + (*s - 'A') + 10; else { +#ifdef FRONTEND + lex->token_terminator = s + PQmblen(s, PG_UTF8); +#else lex->token_terminator = s + pg_mblen(s); +#endif json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s", "json"), @@ -752,6 +790,14 @@ json_lex_string(JsonLexContext *lex) errmsg("unsupported Unicode escape sequence"), errdetail("\\u0000 cannot be converted to text."))); } +#ifdef FRONTEND + else + { + unicode_to_utf8(ch, (unsigned char *) utf8str); + utf8len = PQmblen(utf8str, PG_UTF8); + appendBinaryStringInfo(lex->strval, utf8str, utf8len); + } +#else else if (GetDatabaseEncoding() == PG_UTF8) { unicode_to_utf8(ch, (unsigned char *) utf8str); @@ -773,7 +819,7 @@ json_lex_string(JsonLexContext *lex) 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."))); } - +#endif } } else if (lex->strval != NULL) @@ -808,7 +854,11 @@ json_lex_string(JsonLexContext *lex) break; default: /* Not a valid string escape, so error out. */ +#ifdef FRONTEND + lex->token_terminator = s + PQmblen(s, PG_UTF8); +#else lex->token_terminator = s + pg_mblen(s); +#endif json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s", "json"), @@ -825,7 +875,11 @@ json_lex_string(JsonLexContext *lex) * replace it with a switch statement, but testing so far has * shown it's not a performance win. */ - lex->token_terminator = s + pg_mblen(s); +#ifdef FRONTEND + lex->token_terminator = s + PQmblen(s, PG_UTF8); +#else + lex->token_terminator = s + pg_mblen(s); +#endif json_error((errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s", "json"), errdetail("Escape sequence \"\\%s\" is invalid.", @@ -1058,7 +1112,12 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex) token))); break; default: +#ifdef FRONTEND + pg_log_fatal("unexpected json parse state: %d", ctx); + exit(1); +#else elog(ERROR, "unexpected json parse state: %d", ctx); +#endif } } } @@ -1085,6 +1144,7 @@ report_invalid_token(JsonLexContext *lex) errdetail("Token \"%s\" is invalid.", token))); } +#ifndef FRONTEND /* * Report a CONTEXT line for bogus JSON input. * @@ -1156,6 +1216,7 @@ report_json_context(JsonLexContext *lex) return errcontext("JSON data, line %d: %s%s%s", line_number, prefix, ctxt, suffix); } +#endif /* * Extract a single, possibly multi-byte char from the input string. @@ -1166,7 +1227,11 @@ extract_mb_char(char *s) char *res; int len; +#ifdef FRONTEND + len = PQmblen(s, PG_UTF8); +#else len = pg_mblen(s); +#endif res = palloc(len + 1); memcpy(res, s, len); res[len] = '\0'; -- 2.17.2 (Apple Git-113)