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; } ; %%