Hi.
based on v22.

I added some tests again json_value for the sake of coverager test.

A previous email thread mentioned needing to check *empty in ExecEvalJsonExpr.
since JSON_VALUE_OP, JSON_QUERY_OP, JSON_EXISTS_OP all need to have
*empty cases, So I refactored a little bit.
might be helpful. Maybe we can also refactor *error cases.

The following part is not easy to understand.
res = ExecPrepareJsonItemCoercion(jbv,
+  jsestate->item_jcstates,
+  &post_eval->jcstate);
+ if (post_eval->jcstate &&
+ post_eval->jcstate->coercion &&
+ (post_eval->jcstate->coercion->via_io ||
+ post_eval->jcstate->coercion->via_populate))
From 439f98ae55e6f67ca6c5bf023c6e9ab2796f4c49 Mon Sep 17 00:00:00 2001
From: pgaddict <jian.universal...@gmail.com>
Date: Wed, 18 Oct 2023 10:12:33 +0800
Subject: [PATCH v22 1/1] add some test, refactor ExecEvalJsonExpr

add some tests again json_value for code coverage.
refactor ExecEvalJsonExpr, let JSON_VALUE_OP, JSON_QUERY_OP,
JSON_EXISTS_OP handle *empty in a common way.
---
 src/backend/executor/execExprInterp.c       | 41 +++++++++------------
 src/test/regress/expected/jsonb_sqljson.out | 36 ++++++++++++++++++
 src/test/regress/sql/jsonb_sqljson.sql      |  6 +++
 3 files changed, 60 insertions(+), 23 deletions(-)

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 123121a9..1a1f2089 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4218,7 +4218,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 					*op->resvalue = (Datum) 0;
 					return;
 				}
-
+				if(*empty)
+					goto return_empty;
 				resnull = false;
 				res = BoolGetDatum(exists);
 				break;
@@ -4236,7 +4237,10 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 				*op->resvalue = (Datum) 0;
 				return;
 			}
+			if (*empty)
+				goto return_empty;
 			resnull = !DatumGetPointer(res);
+
 			break;
 
 		case JSON_VALUE_OP:
@@ -4253,15 +4257,14 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 					*op->resvalue = (Datum) 0;
 					return;
 				}
-
-				if (!jbv)		/* NULL or empty */
+				if (*empty)
+					goto return_empty;
+				if (!jbv)		/* NULL */
 				{
 					resnull = true;
+					res		= (Datum) 0;
 					break;
 				}
-
-				Assert(!*empty);
-
 				resnull = false;
 
 				/* Coerce scalar item to the output type */
@@ -4322,31 +4325,23 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 			return;
 	}
 
+	*op->resvalue = res;
+	*op->resnull = resnull;
+	return;
 	/*
 	 * If the ON EMPTY behavior is to cause an error, do so here.  Other
 	 * behaviors will be handled in ExecEvalJsonExprBehavior().
 	 */
-	if (*empty)
-	{
-		Assert(jexpr->on_empty);	/* it is not JSON_EXISTS */
-
-		if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR)
+return_empty:
+		Assert(jexpr->on_empty);
+		*op->resnull = true;
+		*op->resvalue = (Datum) 0;
+		if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR && throw_error)
 		{
-			if (!throw_error)
-			{
-				*op->resnull = true;
-				*op->resvalue = (Datum) 0;
-				return;
-			}
-
 			ereport(ERROR,
 					(errcode(ERRCODE_NO_SQL_JSON_ITEM),
 					 errmsg("no SQL/JSON item")));
 		}
-	}
-
-	*op->resvalue = res;
-	*op->resnull = resnull;
 }
 
 /*
@@ -4467,7 +4462,7 @@ ExecEvalJsonExprCoercion(ExprState *state, ExprEvalStep *op,
 			{
 				Jsonb	   *jb = resnull ? NULL : DatumGetJsonbP(res);
 
-				if (jb && JB_ROOT_IS_SCALAR(jb))
+				if (jb)
 				{
 					omit_quotes = true;
 					val_string = JsonbUnquote(jb);
diff --git a/src/test/regress/expected/jsonb_sqljson.out b/src/test/regress/expected/jsonb_sqljson.out
index a3ba44cf..0526ff00 100644
--- a/src/test/regress/expected/jsonb_sqljson.out
+++ b/src/test/regress/expected/jsonb_sqljson.out
@@ -512,6 +512,42 @@ SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +
  Tue Feb 20 18:34:56 2018 PST
 (1 row)
 
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamp '2018-02-21 12:34:56 +10' AS ts);
+        json_value        
+--------------------------
+ Wed Feb 21 12:34:56 2018
+(1 row)
+
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamp(3) '2018-02-21 12:34:56.123456 +10' AS ts);
+          json_value          
+------------------------------
+ Wed Feb 21 12:34:56.123 2018
+(1 row)
+
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz(3) '2018-02-21 12:34:56.123456 +10' AS ts);
+            json_value            
+----------------------------------
+ Tue Feb 20 18:34:56.123 2018 PST
+(1 row)
+
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING date '2018-02-21 12:34:56 +10' AS ts);
+ json_value 
+------------
+ 02-21-2018
+(1 row)
+
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING time '2018-02-21 12:34:56 +10' AS ts);
+ json_value 
+------------
+ 12:34:56
+(1 row)
+
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timetz '2018-02-21 12:34:56 +10' AS ts);
+ json_value  
+-------------
+ 12:34:56+10
+(1 row)
+
 SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamptz);
           json_value          
 ------------------------------
diff --git a/src/test/regress/sql/jsonb_sqljson.sql b/src/test/regress/sql/jsonb_sqljson.sql
index ab73a011..e28be0a2 100644
--- a/src/test/regress/sql/jsonb_sqljson.sql
+++ b/src/test/regress/sql/jsonb_sqljson.sql
@@ -138,6 +138,12 @@ SELECT JSON_VALUE(jsonb 'null', '$a' PASSING point ' (1, 2 )' AS a RETURNING poi
 
 -- Test timestamptz passing and output
 SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamp '2018-02-21 12:34:56 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamp(3) '2018-02-21 12:34:56.123456 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz(3) '2018-02-21 12:34:56.123456 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING date '2018-02-21 12:34:56 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING time '2018-02-21 12:34:56 +10' AS ts);
+SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timetz '2018-02-21 12:34:56 +10' AS ts);
 SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamptz);
 SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamp);
 SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING json);
-- 
2.34.1

Reply via email to