On Fri, Oct 6, 2023 at 7:47 PM Peter Eisentraut <[email protected]> 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; }
;
%%