From 6f9159935737451df311eb25a24c080b0814af0b Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Fri, 24 Jan 2020 14:30:35 -0800 Subject: [PATCH 1/2] Relocating jsonapi to common. Moving jsonapi.c and jsonapi.h to src/common and src/include/common. Reworking the code to not include elog, ereport, pg_mblen, and similar backend-only functionality. --- contrib/hstore/hstore_io.c | 2 +- src/backend/tsearch/to_tsany.c | 2 +- src/backend/tsearch/wparser.c | 2 +- src/backend/utils/adt/Makefile | 1 - src/backend/utils/adt/json.c | 2 +- src/backend/utils/adt/jsonb.c | 2 +- src/backend/utils/adt/jsonb_util.c | 2 +- src/backend/utils/adt/jsonfuncs.c | 7 ++-- src/common/Makefile | 1 + src/{backend/utils/adt => common}/jsonapi.c | 42 ++++++++++++++++----- src/include/{utils => common}/jsonapi.h | 5 ++- src/include/utils/jsonfuncs.h | 2 +- 12 files changed, 49 insertions(+), 21 deletions(-) rename src/{backend/utils/adt => common}/jsonapi.c (96%) rename src/include/{utils => common}/jsonapi.h (98%) diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index 10ec392775..f3174f2995 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -7,13 +7,13 @@ #include "access/htup_details.h" #include "catalog/pg_type.h" +#include "common/jsonapi.h" #include "funcapi.h" #include "hstore.h" #include "lib/stringinfo.h" #include "libpq/pqformat.h" #include "utils/builtins.h" #include "utils/json.h" -#include "utils/jsonapi.h" #include "utils/jsonb.h" #include "utils/lsyscache.h" #include "utils/memutils.h" diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c index adf181c191..1fe67c4c99 100644 --- a/src/backend/tsearch/to_tsany.c +++ b/src/backend/tsearch/to_tsany.c @@ -13,10 +13,10 @@ */ #include "postgres.h" +#include "common/jsonapi.h" #include "tsearch/ts_cache.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" -#include "utils/jsonapi.h" #include "utils/jsonfuncs.h" diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c index c7499a94ac..88005c0519 100644 --- a/src/backend/tsearch/wparser.c +++ b/src/backend/tsearch/wparser.c @@ -16,11 +16,11 @@ #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "commands/defrem.h" +#include "common/jsonapi.h" #include "funcapi.h" #include "tsearch/ts_cache.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" -#include "utils/jsonapi.h" #include "utils/jsonfuncs.h" #include "utils/varlena.h" diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index 790d7a24fb..13efa9338c 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -44,7 +44,6 @@ OBJS = \ int.o \ int8.o \ json.o \ - jsonapi.o \ jsonb.o \ jsonb_gin.o \ jsonb_op.o \ diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index f6cd2b9911..567eab1e01 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -127,7 +127,7 @@ json_recv(PG_FUNCTION_ARGS) str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); /* Validate it. */ - lex = makeJsonLexContextCstringLen(str, nbytes, false); + lex = makeJsonLexContextCstringLen(str, nbytes, GetDatabaseEncoding(), false); pg_parse_json_or_ereport(lex, &nullSemAction); PG_RETURN_TEXT_P(cstring_to_text_with_len(str, nbytes)); diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index c912f8932d..fea4335951 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -261,7 +261,7 @@ jsonb_from_cstring(char *json, int len) memset(&state, 0, sizeof(state)); memset(&sem, 0, sizeof(sem)); - lex = makeJsonLexContextCstringLen(json, len, true); + lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true); sem.semstate = (void *) &state; diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c index b33c3ef43c..edec657cd3 100644 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@ -15,12 +15,12 @@ #include "catalog/pg_collation.h" #include "catalog/pg_type.h" +#include "common/jsonapi.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/datetime.h" #include "utils/hashutils.h" #include "utils/json.h" -#include "utils/jsonapi.h" #include "utils/jsonb.h" #include "utils/memutils.h" #include "utils/varlena.h" diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 66ea11b971..4f6fd0de02 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -18,6 +18,7 @@ #include "access/htup_details.h" #include "catalog/pg_type.h" +#include "common/jsonapi.h" #include "fmgr.h" #include "funcapi.h" #include "lib/stringinfo.h" @@ -27,7 +28,6 @@ #include "utils/builtins.h" #include "utils/hsearch.h" #include "utils/json.h" -#include "utils/jsonapi.h" #include "utils/jsonb.h" #include "utils/jsonfuncs.h" #include "utils/lsyscache.h" @@ -514,6 +514,7 @@ makeJsonLexContext(text *json, bool need_escapes) { return makeJsonLexContextCstringLen(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json), + GetDatabaseEncoding(), need_escapes); } @@ -2605,7 +2606,7 @@ populate_array_json(PopulateArrayContext *ctx, char *json, int len) PopulateArrayState state; JsonSemAction sem; - state.lex = makeJsonLexContextCstringLen(json, len, true); + state.lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true); state.ctx = ctx; memset(&sem, 0, sizeof(sem)); @@ -3448,7 +3449,7 @@ get_json_object_as_hash(char *json, int len, const char *funcname) HASHCTL ctl; HTAB *tab; JHashState *state; - JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true); + JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true); JsonSemAction *sem; memset(&ctl, 0, sizeof(ctl)); diff --git a/src/common/Makefile b/src/common/Makefile index 44ca68fa6c..e757fb7399 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -56,6 +56,7 @@ OBJS_COMMON = \ f2s.o \ file_perm.o \ ip.o \ + jsonapi.o \ keywords.o \ kwlookup.o \ link-canary.o \ diff --git a/src/backend/utils/adt/jsonapi.c b/src/common/jsonapi.c similarity index 96% rename from src/backend/utils/adt/jsonapi.c rename to src/common/jsonapi.c index 1ac3b7beda..f0e6a63e4d 100644 --- a/src/backend/utils/adt/jsonapi.c +++ b/src/common/jsonapi.c @@ -11,11 +11,18 @@ * *------------------------------------------------------------------------- */ +#ifndef FRONTEND #include "postgres.h" +#else +#include "postgres_fe.h" +#endif +#include "common/jsonapi.h" #include "mb/pg_wchar.h" + +#ifndef FRONTEND #include "miscadmin.h" -#include "utils/jsonapi.h" +#endif /* * The context of the parser is maintained by the recursive descent @@ -135,13 +142,21 @@ IsValidJsonNumber(const char *str, int len) * if really required. */ JsonLexContext * -makeJsonLexContextCstringLen(char *json, int len, bool need_escapes) +makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes) { - JsonLexContext *lex = palloc0(sizeof(JsonLexContext)); + JsonLexContext *lex; + +#ifndef FRONTEND + lex = palloc0(sizeof(JsonLexContext)); +#else + lex = (JsonLexContext*) malloc(sizeof(JsonLexContext)); + memset(lex, 0, sizeof(JsonLexContext)); +#endif lex->input = lex->token_terminator = lex->line_start = json; lex->line_number = 1; lex->input_length = len; + lex->input_encoding = encoding; if (need_escapes) lex->strval = makeStringInfo(); return lex; @@ -360,7 +375,11 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem) JsonTokenType tok; JsonParseErrorType result; +#ifndef FRONTEND check_stack_depth(); +#else + /* TODO: What do we do in frontend code? */ +#endif if (ostart != NULL) (*ostart) (sem->semstate); @@ -460,7 +479,11 @@ parse_array(JsonLexContext *lex, JsonSemAction *sem) json_struct_action aend = sem->array_end; JsonParseErrorType result; +#ifndef FRONTEND check_stack_depth(); +#else + /* TODO: What do we do in frontend code? */ +#endif if (astart != NULL) (*astart) (sem->semstate); @@ -720,7 +743,7 @@ json_lex_string(JsonLexContext *lex) ch = (ch * 16) + (*s - 'A') + 10; else { - lex->token_terminator = s + pg_mblen(s); + lex->token_terminator = s + pg_wchar_table[lex->input_encoding].mblen((const unsigned char *) s); return JSON_UNICODE_ESCAPE_FORMAT; } } @@ -759,7 +782,7 @@ json_lex_string(JsonLexContext *lex) /* We can't allow this, since our TEXT type doesn't */ return JSON_UNICODE_CODE_POINT_ZERO; } - else if (GetDatabaseEncoding() == PG_UTF8) + else if (lex->input_encoding == PG_UTF8) { unicode_to_utf8(ch, (unsigned char *) utf8str); utf8len = pg_utf_mblen((unsigned char *) utf8str); @@ -809,7 +832,7 @@ json_lex_string(JsonLexContext *lex) default: /* Not a valid string escape, so signal error. */ lex->token_start = s; - lex->token_terminator = s + pg_mblen(s); + lex->token_terminator = s + pg_wchar_table[lex->input_encoding].mblen((const unsigned char *) s); return JSON_ESCAPING_INVALID; } } @@ -823,7 +846,7 @@ json_lex_string(JsonLexContext *lex) * shown it's not a performance win. */ lex->token_start = s; - lex->token_terminator = s + pg_mblen(s); + lex->token_terminator = s + pg_wchar_table[lex->input_encoding].mblen((const unsigned char *) s); return JSON_ESCAPING_INVALID; } @@ -1004,7 +1027,7 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex) case JSON_PARSE_OBJECT_COMMA: return JSON_EXPECTED_STRING; default: - elog(ERROR, "unexpected json parse state: %d", ctx); + return JSON_BAD_PARSER_STATE; } } @@ -1017,7 +1040,8 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex) switch (error) { case JSON_SUCCESS: - elog(ERROR, "internal error in json parser"); + case JSON_BAD_PARSER_STATE: + return _("internal error in json parser"); break; case JSON_ESCAPING_INVALID: return psprintf(_("Escape sequence \"\\%s\" is invalid."), diff --git a/src/include/utils/jsonapi.h b/src/include/common/jsonapi.h similarity index 98% rename from src/include/utils/jsonapi.h rename to src/include/common/jsonapi.h index 4d69b18495..375b6d6639 100644 --- a/src/include/utils/jsonapi.h +++ b/src/include/common/jsonapi.h @@ -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_BAD_PARSER_STATE } JsonParseErrorType; @@ -73,6 +74,7 @@ typedef struct JsonLexContext { char *input; int input_length; + int input_encoding; char *token_start; char *token_terminator; char *prev_token_terminator; @@ -149,6 +151,7 @@ extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex, */ extern JsonLexContext *makeJsonLexContextCstringLen(char *json, int len, + int encoding, bool need_escapes); /* lex one token */ diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h index b993f38409..1f1b4029cb 100644 --- a/src/include/utils/jsonfuncs.h +++ b/src/include/utils/jsonfuncs.h @@ -14,7 +14,7 @@ #ifndef JSONFUNCS_H #define JSONFUNCS_H -#include "utils/jsonapi.h" +#include "common/jsonapi.h" #include "utils/jsonb.h" /* -- 2.21.1 (Apple Git-122.3)