aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonpath_exec.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2024-01-03 21:56:41 +0100
committerPeter Eisentraut <peter@eisentraut.org>2024-01-03 21:56:41 +0100
commit59fd390d5e8a7e169ff8f095882e32e189f3c5bd (patch)
tree69ef820292d459b35d5292058ba9ae3e4b78975a /src/backend/utils/adt/jsonpath_exec.c
parent0958f8f6bf60639a1d22d78d5b49a6092b11833d (diff)
downloadpostgresql-59fd390d5e8a7e169ff8f095882e32e189f3c5bd.tar.gz
postgresql-59fd390d5e8a7e169ff8f095882e32e189f3c5bd.zip
Second attempt at organizing jsonpath operators and methods
Second attempt at 283a95da923. Since we can't reorder the enum values of JsonPathItemType, instead reorder the switch cases where they are used to generally follow the order of the enum values, for better maintainability.
Diffstat (limited to 'src/backend/utils/adt/jsonpath_exec.c')
-rw-r--r--src/backend/utils/adt/jsonpath_exec.c332
1 files changed, 166 insertions, 166 deletions
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 9a09604f642..163b75eb815 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -621,6 +621,37 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
switch (jsp->type)
{
+ case jpiNull:
+ case jpiBool:
+ case jpiNumeric:
+ case jpiString:
+ case jpiVariable:
+ {
+ JsonbValue vbuf;
+ JsonbValue *v;
+ bool hasNext = jspGetNext(jsp, &elem);
+
+ if (!hasNext && !found && jsp->type != jpiVariable)
+ {
+ /*
+ * Skip evaluation, but not for variables. We must
+ * trigger an error for the missing variable.
+ */
+ res = jperOk;
+ break;
+ }
+
+ v = hasNext ? &vbuf : palloc(sizeof(*v));
+
+ baseObject = cxt->baseObject;
+ getJsonPathItem(cxt, jsp, v);
+
+ res = executeNextItem(cxt, jsp, &elem,
+ v, found, hasNext);
+ cxt->baseObject = baseObject;
+ }
+ break;
+
/* all boolean item types: */
case jpiAnd:
case jpiOr:
@@ -642,63 +673,32 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
break;
}
- case jpiKey:
- if (JsonbType(jb) == jbvObject)
- {
- JsonbValue *v;
- JsonbValue key;
-
- key.type = jbvString;
- key.val.string.val = jspGetString(jsp, &key.val.string.len);
-
- v = findJsonbValueFromContainer(jb->val.binary.data,
- JB_FOBJECT, &key);
+ case jpiAdd:
+ return executeBinaryArithmExpr(cxt, jsp, jb,
+ numeric_add_opt_error, found);
- if (v != NULL)
- {
- res = executeNextItem(cxt, jsp, NULL,
- v, found, false);
+ case jpiSub:
+ return executeBinaryArithmExpr(cxt, jsp, jb,
+ numeric_sub_opt_error, found);
- /* free value if it was not added to found list */
- if (jspHasNext(jsp) || !found)
- pfree(v);
- }
- else if (!jspIgnoreStructuralErrors(cxt))
- {
- Assert(found);
+ case jpiMul:
+ return executeBinaryArithmExpr(cxt, jsp, jb,
+ numeric_mul_opt_error, found);
- if (!jspThrowErrors(cxt))
- return jperError;
+ case jpiDiv:
+ return executeBinaryArithmExpr(cxt, jsp, jb,
+ numeric_div_opt_error, found);
- ereport(ERROR,
- (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND), \
- errmsg("JSON object does not contain key \"%s\"",
- pnstrdup(key.val.string.val,
- key.val.string.len))));
- }
- }
- else if (unwrap && JsonbType(jb) == jbvArray)
- return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
- else if (!jspIgnoreStructuralErrors(cxt))
- {
- Assert(found);
- RETURN_ERROR(ereport(ERROR,
- (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND),
- errmsg("jsonpath member accessor can only be applied to an object"))));
- }
- break;
+ case jpiMod:
+ return executeBinaryArithmExpr(cxt, jsp, jb,
+ numeric_mod_opt_error, found);
- case jpiRoot:
- jb = cxt->root;
- baseObject = setBaseObject(cxt, jb, 0);
- res = executeNextItem(cxt, jsp, NULL, jb, found, true);
- cxt->baseObject = baseObject;
- break;
+ case jpiPlus:
+ return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
- case jpiCurrent:
- res = executeNextItem(cxt, jsp, NULL, cxt->current,
- found, true);
- break;
+ case jpiMinus:
+ return executeUnaryArithmExpr(cxt, jsp, jb, numeric_uminus,
+ found);
case jpiAnyArray:
if (JsonbType(jb) == jbvArray)
@@ -716,6 +716,30 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
break;
+ case jpiAnyKey:
+ if (JsonbType(jb) == jbvObject)
+ {
+ bool hasNext = jspGetNext(jsp, &elem);
+
+ if (jb->type != jbvBinary)
+ elog(ERROR, "invalid jsonb object type: %d", jb->type);
+
+ return executeAnyItem
+ (cxt, hasNext ? &elem : NULL,
+ jb->val.binary.data, found, 1, 1, 1,
+ false, jspAutoUnwrap(cxt));
+ }
+ else if (unwrap && JsonbType(jb) == jbvArray)
+ return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
+ else if (!jspIgnoreStructuralErrors(cxt))
+ {
+ Assert(found);
+ RETURN_ERROR(ereport(ERROR,
+ (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
+ errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
+ }
+ break;
+
case jpiIndexArray:
if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
{
@@ -822,46 +846,70 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
}
break;
- case jpiLast:
+ case jpiAny:
{
- JsonbValue tmpjbv;
- JsonbValue *lastjbv;
- int last;
bool hasNext = jspGetNext(jsp, &elem);
- if (cxt->innermostArraySize < 0)
- elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
-
- if (!hasNext && !found)
+ /* first try without any intermediate steps */
+ if (jsp->content.anybounds.first == 0)
{
- res = jperOk;
- break;
- }
-
- last = cxt->innermostArraySize - 1;
+ bool savedIgnoreStructuralErrors;
- lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
+ savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
+ cxt->ignoreStructuralErrors = true;
+ res = executeNextItem(cxt, jsp, &elem,
+ jb, found, true);
+ cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
- lastjbv->type = jbvNumeric;
- lastjbv->val.numeric = int64_to_numeric(last);
+ if (res == jperOk && !found)
+ break;
+ }
- res = executeNextItem(cxt, jsp, &elem,
- lastjbv, found, hasNext);
+ if (jb->type == jbvBinary)
+ res = executeAnyItem
+ (cxt, hasNext ? &elem : NULL,
+ jb->val.binary.data, found,
+ 1,
+ jsp->content.anybounds.first,
+ jsp->content.anybounds.last,
+ true, jspAutoUnwrap(cxt));
+ break;
}
- break;
- case jpiAnyKey:
+ case jpiKey:
if (JsonbType(jb) == jbvObject)
{
- bool hasNext = jspGetNext(jsp, &elem);
+ JsonbValue *v;
+ JsonbValue key;
- if (jb->type != jbvBinary)
- elog(ERROR, "invalid jsonb object type: %d", jb->type);
+ key.type = jbvString;
+ key.val.string.val = jspGetString(jsp, &key.val.string.len);
- return executeAnyItem
- (cxt, hasNext ? &elem : NULL,
- jb->val.binary.data, found, 1, 1, 1,
- false, jspAutoUnwrap(cxt));
+ v = findJsonbValueFromContainer(jb->val.binary.data,
+ JB_FOBJECT, &key);
+
+ if (v != NULL)
+ {
+ res = executeNextItem(cxt, jsp, NULL,
+ v, found, false);
+
+ /* free value if it was not added to found list */
+ if (jspHasNext(jsp) || !found)
+ pfree(v);
+ }
+ else if (!jspIgnoreStructuralErrors(cxt))
+ {
+ Assert(found);
+
+ if (!jspThrowErrors(cxt))
+ return jperError;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND), \
+ errmsg("JSON object does not contain key \"%s\"",
+ pnstrdup(key.val.string.val,
+ key.val.string.len))));
+ }
}
else if (unwrap && JsonbType(jb) == jbvArray)
return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
@@ -869,37 +917,22 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
{
Assert(found);
RETURN_ERROR(ereport(ERROR,
- (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
- errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
+ (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND),
+ errmsg("jsonpath member accessor can only be applied to an object"))));
}
break;
- case jpiAdd:
- return executeBinaryArithmExpr(cxt, jsp, jb,
- numeric_add_opt_error, found);
-
- case jpiSub:
- return executeBinaryArithmExpr(cxt, jsp, jb,
- numeric_sub_opt_error, found);
-
- case jpiMul:
- return executeBinaryArithmExpr(cxt, jsp, jb,
- numeric_mul_opt_error, found);
-
- case jpiDiv:
- return executeBinaryArithmExpr(cxt, jsp, jb,
- numeric_div_opt_error, found);
-
- case jpiMod:
- return executeBinaryArithmExpr(cxt, jsp, jb,
- numeric_mod_opt_error, found);
-
- case jpiPlus:
- return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
+ case jpiCurrent:
+ res = executeNextItem(cxt, jsp, NULL, cxt->current,
+ found, true);
+ break;
- case jpiMinus:
- return executeUnaryArithmExpr(cxt, jsp, jb, numeric_uminus,
- found);
+ case jpiRoot:
+ jb = cxt->root;
+ baseObject = setBaseObject(cxt, jb, 0);
+ res = executeNextItem(cxt, jsp, NULL, jb, found, true);
+ cxt->baseObject = baseObject;
+ break;
case jpiFilter:
{
@@ -919,67 +952,6 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
break;
}
- case jpiAny:
- {
- bool hasNext = jspGetNext(jsp, &elem);
-
- /* first try without any intermediate steps */
- if (jsp->content.anybounds.first == 0)
- {
- bool savedIgnoreStructuralErrors;
-
- savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
- cxt->ignoreStructuralErrors = true;
- res = executeNextItem(cxt, jsp, &elem,
- jb, found, true);
- cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
-
- if (res == jperOk && !found)
- break;
- }
-
- if (jb->type == jbvBinary)
- res = executeAnyItem
- (cxt, hasNext ? &elem : NULL,
- jb->val.binary.data, found,
- 1,
- jsp->content.anybounds.first,
- jsp->content.anybounds.last,
- true, jspAutoUnwrap(cxt));
- break;
- }
-
- case jpiNull:
- case jpiBool:
- case jpiNumeric:
- case jpiString:
- case jpiVariable:
- {
- JsonbValue vbuf;
- JsonbValue *v;
- bool hasNext = jspGetNext(jsp, &elem);
-
- if (!hasNext && !found && jsp->type != jpiVariable)
- {
- /*
- * Skip evaluation, but not for variables. We must
- * trigger an error for the missing variable.
- */
- res = jperOk;
- break;
- }
-
- v = hasNext ? &vbuf : palloc(sizeof(*v));
-
- baseObject = cxt->baseObject;
- getJsonPathItem(cxt, jsp, v);
-
- res = executeNextItem(cxt, jsp, &elem,
- v, found, hasNext);
- cxt->baseObject = baseObject;
- }
- break;
-
case jpiType:
{
JsonbValue *jbv = palloc(sizeof(*jbv));
@@ -1110,6 +1082,34 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
return executeKeyValueMethod(cxt, jsp, jb, found);
+ case jpiLast:
+ {
+ JsonbValue tmpjbv;
+ JsonbValue *lastjbv;
+ int last;
+ bool hasNext = jspGetNext(jsp, &elem);
+
+ if (cxt->innermostArraySize < 0)
+ elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
+
+ if (!hasNext && !found)
+ {
+ res = jperOk;
+ break;
+ }
+
+ last = cxt->innermostArraySize - 1;
+
+ lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
+
+ lastjbv->type = jbvNumeric;
+ lastjbv->val.numeric = int64_to_numeric(last);
+
+ res = executeNextItem(cxt, jsp, &elem,
+ lastjbv, found, hasNext);
+ }
+ break;
+
default:
elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
}