diff options
Diffstat (limited to 'src/backend/utils/adt/jsonpath_exec.c')
-rw-r--r-- | src/backend/utils/adt/jsonpath_exec.c | 332 |
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); } |