fix_jsonb_variable.patch

application/octet-stream

Filename: fix_jsonb_variable.patch
Type: application/octet-stream
Part: 0
Message: Re: Bug in jsonb_path_exists (maybe _match) one-element scalar/variable jsonpath handling

Patch

Format: unified
File+
src/backend/utils/adt/jsonpath_exec.c 40 11
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 8d83b2edb35..145a5e75f6b 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -224,8 +224,9 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt,
 										   JsonPathItem *jsp, JsonValueList *found, JsonPathBool res);
 static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
 							JsonbValue *value);
-static void getJsonPathVariable(JsonPathExecContext *cxt,
-								JsonPathItem *variable, Jsonb *vars, JsonbValue *value);
+static JsonPathExecResult getJsonPathVariable(JsonPathExecContext *cxt,
+											  JsonPathItem *variable,
+											  JsonbValue *value);
 static int	JsonbArraySize(JsonbValue *jb);
 static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv,
 									  JsonbValue *rv, void *p);
@@ -952,7 +953,6 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 		case jpiBool:
 		case jpiNumeric:
 		case jpiString:
-		case jpiVariable:
 			{
 				JsonbValue	vbuf;
 				JsonbValue *v;
@@ -975,6 +975,28 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 			}
 			break;
 
+		case jpiVariable:
+			{
+				JsonbValue	vbuf;
+				JsonbValue *v;
+				bool		hasNext = jspGetNext(jsp, &elem);
+
+				v = hasNext ? &vbuf : palloc(sizeof(*v));
+
+				baseObject = cxt->baseObject;
+				res = getJsonPathVariable(cxt, jsp, v);
+
+				if (res == jperOk)
+				{
+					res = executeNextItem(cxt, jsp, &elem,
+										v, found, hasNext);
+					if (jspHasNext(jsp) || !found)
+						pfree(v);
+				}
+				cxt->baseObject = baseObject;
+			}
+			break;
+
 		case jpiType:
 			{
 				JsonbValue *jbv = palloc(sizeof(*jbv));
@@ -2092,9 +2114,6 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
 			value->val.string.val = jspGetString(item,
 												 &value->val.string.len);
 			break;
-		case jpiVariable:
-			getJsonPathVariable(cxt, item, cxt->vars, value);
-			return;
 		default:
 			elog(ERROR, "unexpected jsonpath item type");
 	}
@@ -2103,19 +2122,20 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
 /*
  * Get the value of variable passed to jsonpath executor
  */
-static void
+static JsonPathExecResult
 getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
-					Jsonb *vars, JsonbValue *value)
+					JsonbValue *value)
 {
 	char	   *varName;
 	int			varNameLength;
 	JsonbValue	tmp;
 	JsonbValue *v;
+	Jsonb	   *vars = cxt->vars;
+	JsonPathExecResult res;
 
 	if (!vars)
 	{
-		value->type = jbvNull;
-		return;
+		return jperNotFound;
 	}
 
 	Assert(variable->type == jpiVariable);
@@ -2130,17 +2150,26 @@ getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
 	{
 		*value = *v;
 		pfree(v);
+		res = jperOk;
 	}
-	else
+	else if (!jspIgnoreStructuralErrors(cxt))
 	{
+		if (!jspThrowErrors(cxt))
+			res = jperError;
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("could not find jsonpath variable \"%s\"",
 						pnstrdup(varName, varNameLength))));
 	}
+	else
+	{
+		res = jperNotFound;
+	}
 
 	JsonbInitBinary(&tmp, vars);
 	setBaseObject(cxt, &tmp, 1);
+
+	return res;
 }
 
 /**************** Support functions for JsonPath execution *****************/