diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2022-12-24 15:19:14 -0500 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2022-12-24 15:21:20 -0500 |
commit | e37fe1db6ef930f657be28fe764f7e642b93464a (patch) | |
tree | d7f72770eb4350c6a9192c52e42932019efa0ed2 /src/backend/utils/adt/jsonpath.c | |
parent | 780ec9f1b2a44c118d1246325404ad0ed2226cbf (diff) | |
download | postgresql-e37fe1db6ef930f657be28fe764f7e642b93464a.tar.gz postgresql-e37fe1db6ef930f657be28fe764f7e642b93464a.zip |
Convert jsonpath's input function to report errors softly
Reviewed by Tom Lane
Discussion: https://postgr.es/m/a8dc5700-c341-3ba8-0507-cc09881e6200@dunslane.net
Diffstat (limited to 'src/backend/utils/adt/jsonpath.c')
-rw-r--r-- | src/backend/utils/adt/jsonpath.c | 116 |
1 files changed, 74 insertions, 42 deletions
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c index 91af0300952..bb9364843e6 100644 --- a/src/backend/utils/adt/jsonpath.c +++ b/src/backend/utils/adt/jsonpath.c @@ -66,16 +66,19 @@ #include "funcapi.h" #include "lib/stringinfo.h" #include "libpq/pqformat.h" +#include "nodes/miscnodes.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/json.h" #include "utils/jsonpath.h" -static Datum jsonPathFromCstring(char *in, int len); +static Datum jsonPathFromCstring(char *in, int len, struct Node *escontext); static char *jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len); -static int flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, +static bool flattenJsonPathParseItem(StringInfo buf, int *result, + struct Node *escontext, + JsonPathParseItem *item, int nestingLevel, bool insideArraySubscript); static void alignStringInfoInt(StringInfo buf); static int32 reserveSpaceForItemPointer(StringInfo buf); @@ -95,7 +98,7 @@ jsonpath_in(PG_FUNCTION_ARGS) char *in = PG_GETARG_CSTRING(0); int len = strlen(in); - return jsonPathFromCstring(in, len); + return jsonPathFromCstring(in, len, fcinfo->context); } /* @@ -119,7 +122,7 @@ jsonpath_recv(PG_FUNCTION_ARGS) else elog(ERROR, "unsupported jsonpath version number: %d", version); - return jsonPathFromCstring(str, nbytes); + return jsonPathFromCstring(str, nbytes, NULL); } /* @@ -165,24 +168,29 @@ jsonpath_send(PG_FUNCTION_ARGS) * representation of jsonpath. */ static Datum -jsonPathFromCstring(char *in, int len) +jsonPathFromCstring(char *in, int len, struct Node *escontext) { - JsonPathParseResult *jsonpath = parsejsonpath(in, len); + JsonPathParseResult *jsonpath = parsejsonpath(in, len, escontext); JsonPath *res; StringInfoData buf; - initStringInfo(&buf); - enlargeStringInfo(&buf, 4 * len /* estimation */ ); - - appendStringInfoSpaces(&buf, JSONPATH_HDRSZ); + if (SOFT_ERROR_OCCURRED(escontext)) + return (Datum) 0; if (!jsonpath) - ereport(ERROR, + ereturn(escontext, (Datum) 0, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s: \"%s\"", "jsonpath", in))); - flattenJsonPathParseItem(&buf, jsonpath->expr, 0, false); + initStringInfo(&buf); + enlargeStringInfo(&buf, 4 * len /* estimation */ ); + + appendStringInfoSpaces(&buf, JSONPATH_HDRSZ); + + if (!flattenJsonPathParseItem(&buf, NULL, escontext, + jsonpath->expr, 0, false)) + return (Datum) 0; res = (JsonPath *) buf.data; SET_VARSIZE(res, buf.len); @@ -225,9 +233,10 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len) * Recursive function converting given jsonpath parse item and all its * children into a binary representation. */ -static int -flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, - int nestingLevel, bool insideArraySubscript) +static bool +flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext, + JsonPathParseItem *item, int nestingLevel, + bool insideArraySubscript) { /* position from beginning of jsonpath data */ int32 pos = buf->len - JSONPATH_HDRSZ; @@ -295,16 +304,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, int32 left = reserveSpaceForItemPointer(buf); int32 right = reserveSpaceForItemPointer(buf); - chld = !item->value.args.left ? pos : - flattenJsonPathParseItem(buf, item->value.args.left, - nestingLevel + argNestingLevel, - insideArraySubscript); + if (!item->value.args.left) + chld = pos; + else if (! flattenJsonPathParseItem(buf, &chld, escontext, + item->value.args.left, + nestingLevel + argNestingLevel, + insideArraySubscript)) + return false; *(int32 *) (buf->data + left) = chld - pos; - chld = !item->value.args.right ? pos : - flattenJsonPathParseItem(buf, item->value.args.right, - nestingLevel + argNestingLevel, - insideArraySubscript); + if (!item->value.args.right) + chld = pos; + else if (! flattenJsonPathParseItem(buf, &chld, escontext, + item->value.args.right, + nestingLevel + argNestingLevel, + insideArraySubscript)) + return false; *(int32 *) (buf->data + right) = chld - pos; } break; @@ -323,9 +338,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, item->value.like_regex.patternlen); appendStringInfoChar(buf, '\0'); - chld = flattenJsonPathParseItem(buf, item->value.like_regex.expr, - nestingLevel, - insideArraySubscript); + if (! flattenJsonPathParseItem(buf, &chld, escontext, + item->value.like_regex.expr, + nestingLevel, + insideArraySubscript)) + return false; *(int32 *) (buf->data + offs) = chld - pos; } break; @@ -341,10 +358,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, { int32 arg = reserveSpaceForItemPointer(buf); - chld = !item->value.arg ? pos : - flattenJsonPathParseItem(buf, item->value.arg, - nestingLevel + argNestingLevel, - insideArraySubscript); + if (!item->value.arg) + chld = pos; + else if (! flattenJsonPathParseItem(buf, &chld, escontext, + item->value.arg, + nestingLevel + argNestingLevel, + insideArraySubscript)) + return false; *(int32 *) (buf->data + arg) = chld - pos; } break; @@ -357,13 +377,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, break; case jpiCurrent: if (nestingLevel <= 0) - ereport(ERROR, + ereturn(escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("@ is not allowed in root expressions"))); break; case jpiLast: if (!insideArraySubscript) - ereport(ERROR, + ereturn(escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("LAST is allowed only in array subscripts"))); break; @@ -383,15 +403,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, { int32 *ppos; int32 topos; - int32 frompos = - flattenJsonPathParseItem(buf, - item->value.array.elems[i].from, - nestingLevel, true) - pos; + int32 frompos; + + if (! flattenJsonPathParseItem(buf, &frompos, escontext, + item->value.array.elems[i].from, + nestingLevel, true)) + return false; + frompos -= pos; if (item->value.array.elems[i].to) - topos = flattenJsonPathParseItem(buf, - item->value.array.elems[i].to, - nestingLevel, true) - pos; + { + if (! flattenJsonPathParseItem(buf, &topos, escontext, + item->value.array.elems[i].to, + nestingLevel, true)) + return false; + topos -= pos; + } else topos = 0; @@ -424,12 +451,17 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item, if (item->next) { - chld = flattenJsonPathParseItem(buf, item->next, nestingLevel, - insideArraySubscript) - pos; + if (! flattenJsonPathParseItem(buf, &chld, escontext, + item->next, nestingLevel, + insideArraySubscript)) + return false; + chld -= pos; *(int32 *) (buf->data + next) = chld; } - return pos; + if (result) + *result = pos; + return true; } /* |