aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonpath_exec.c
diff options
context:
space:
mode:
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);
}