On Fri, Oct 6, 2023 at 7:47 PM Peter Eisentraut <pe...@eisentraut.org> wrote:
>
> On 29.08.23 09:05, Jeevan Chalke wrote:
> > v1-0001-Implement-jsonpath-.bigint-.integer-and-.number-m.patch
> >
> > This commit implements jsonpath .bigint(), .integer(), and .number()
> > methods.  The JSON string or a numeric value is converted to the
> > bigint, int4, and numeric type representation.
>
> A comment that applies to all of these: These add various keywords,
> switch cases, documentation entries in some order.  Are we happy with
> that?  Should we try to reorder all of that for better maintainability
> or readability?
>
> > v1-0002-Implement-.date-.time-.time_tz-.timestamp-and-.ti.patch
> >
> > This commit implements jsonpath .date(), .time(), .time_tz(),
> > .timestamp(), .timestamp_tz() methods.  The JSON string representing
> > a valid date/time is converted to the specific date or time type
> > representation.
> >
> > The changes use the infrastructure of the .datetime() method and
> > perform the datatype conversion as appropriate.  All these methods
> > accept no argument and use ISO datetime formats.
>
> These should accept an optional precision argument.  Did you plan to add
> that?

compiler warnings issue resolved.

I figured out how to use the precision argument.
But I don't know how to get the precision argument in the parse stage.

attached is my attempt to implement: select
jsonb_path_query('"2017-03-10 11:11:01.123"', '$.timestamp(2)');
not that familiar with src/backend/utils/adt/jsonpath_gram.y. imitate
decimal method failed. decimal has precision and scale two arguments.
here only one argument.

looking for hints.
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index 42f325bd..460e43cb 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -1144,6 +1144,7 @@ jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
 		   v->type == jpiDiv ||
 		   v->type == jpiMod ||
 		   v->type == jpiDecimal ||
+		   v->type == jpiTimestamp ||
 		   v->type == jpiStartsWith);
 
 	jspInitByBuffer(a, v->base, v->content.args.left);
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 94f1052d..4241837f 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -1096,7 +1096,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 		case jpiStringFunc:
 			{
 				JsonbValue	jbv;
-				char	   *tmp;
+				char	   *tmp = NULL;
 
 				switch (JsonbType(jb))
 				{
@@ -1159,6 +1159,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 				res = jperOk;
 
 				jb = &jbv;
+				Assert(tmp != NULL);	/* above switch case, covered all the case jbvType */
 				jb->val.string.val = (jb->type == jbvString) ? tmp : pstrdup(tmp);
 				jb->val.string.len = strlen(jb->val.string.val);
 				jb->type = jbvString;
@@ -1400,9 +1401,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					/* cast string as number */
 					Datum		datum;
 					bool		noerr;
-					char	   *numstr = pnstrdup(jb->val.string.val,
-												  jb->val.string.len);
 					ErrorSaveContext escontext = {T_ErrorSaveContext};
+					numstr		= pnstrdup(jb->val.string.val,
+											jb->val.string.len);
 
 					noerr = DirectInputFunctionCallSafe(numeric_in, numstr,
 														InvalidOid, -1,
@@ -1439,7 +1440,6 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 				 */
 				if (jsp->type == jpiDecimal && jsp->content.args.left)
 				{
-					JsonPathItem elem;
 					Datum		numdatum;
 					Datum		dtypmod;
 					int32		precision;
@@ -2443,6 +2443,7 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 			break;
 		case jpiTimestamp:
 			{
+				Timestamp	tmp;
 				/* Convert result type to timestamp without time zone */
 				switch (typid)
 				{
@@ -2468,6 +2469,9 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 				}
 
 				typid = TIMESTAMPOID;
+				tmp = DatumGetTimestamp(value);
+				AdjustTimestampForTypmod(&tmp, 2, NULL);
+				value = TimestampGetDatum(tmp);
 			}
 			break;
 		case jpiTimestampTz:
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index da031e35..ec188472 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -264,6 +264,18 @@ accessor_op:
 					 errmsg("invalid input syntax for type %s", "jsonpath"),
 					 errdetail(".decimal() can only have an optional precision[,scale].")));
 	}
+	| '.' TIMESTAMP_P '(' opt_csv_list ')'
+	{
+		if (list_length($4) == 0)
+			$$ = makeItemBinary(jpiTimestamp, NULL, NULL);
+		else if (list_length($4) == 1)
+			$$ = makeItemBinary(jpiTimestamp, linitial($4), NULL);
+		else
+			ereturn(escontext, false,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+					 errmsg("invalid input syntax for type %s", "jsonpath"),
+					 errdetail(".jpiTimestamp() can only have an optional precision.")));
+	}
 	| '.' DATETIME_P '(' opt_datetime_template ')'
 									{ $$ = makeItemUnary(jpiDatetime, $4); }
 	| '?' '(' predicate ')'			{ $$ = makeItemUnary(jpiFilter, $3); }
@@ -355,7 +367,6 @@ method:
 	| DATE_P						{ $$ = jpiDate; }
 	| TIME_P						{ $$ = jpiTime; }
 	| TIME_TZ_P						{ $$ = jpiTimeTz; }
-	| TIMESTAMP_P					{ $$ = jpiTimestamp; }
 	| TIMESTAMP_TZ_P				{ $$ = jpiTimestampTz; }
 	;
 %%

Reply via email to