Skip to content

Commit

Permalink
Accept fractional seconds in jsonpath's datetime() method.
Browse files Browse the repository at this point in the history
Commit 927d9ab purported to make datetime() accept any string
that could be output for a datetime value by to_jsonb().  But it
overlooked the possibility of fractional seconds being present,
so that cases as simple as to_jsonb(now()) would defeat it.

Fix by adding formats that include ".US" to the list in
executeDateTimeMethod().  (Note that while this is nominally
microseconds, it'll do the right thing for fractions with
fewer than six digits.)

In passing, re-order the list to restore the datatype ordering
specified in its comment.  The violation accidentally did not
break anything; but the next edit might be less lucky, so add
more comments.

Per report from Tim Field.  Back-patch to v13 where datetime()
was added, like the previous patch.

Discussion: https://postgr.es/m/014A028B-5CE6-4FDF-AC24-426CA6FC9CEE@mohiohio.com
  • Loading branch information
tglsfdc committed Jun 12, 2023
1 parent 0c52437 commit 7398e27
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/backend/utils/adt/jsonpath_exec.c
Expand Up @@ -1840,20 +1840,29 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
* According to SQL/JSON standard enumerate ISO formats for: date,
* timetz, time, timestamptz, timestamp.
*
* We also support ISO 8601 for timestamps, because to_json[b]()
* functions use this format.
* We also support ISO 8601 format (with "T") for timestamps, because
* to_json[b]() functions use this format.
*/
static const char *fmt_str[] =
{
"yyyy-mm-dd",
"yyyy-mm-dd", /* date */
"HH24:MI:SS.USTZH:TZM", /* timetz */
"HH24:MI:SS.USTZH",
"HH24:MI:SSTZH:TZM",
"HH24:MI:SSTZH",
"HH24:MI:SS.US", /* time without tz */
"HH24:MI:SS",
"yyyy-mm-dd HH24:MI:SS.USTZH:TZM", /* timestamptz */
"yyyy-mm-dd HH24:MI:SS.USTZH",
"yyyy-mm-dd HH24:MI:SSTZH:TZM",
"yyyy-mm-dd HH24:MI:SSTZH",
"yyyy-mm-dd HH24:MI:SS",
"yyyy-mm-dd\"T\"HH24:MI:SS.USTZH:TZM",
"yyyy-mm-dd\"T\"HH24:MI:SS.USTZH",
"yyyy-mm-dd\"T\"HH24:MI:SSTZH:TZM",
"yyyy-mm-dd\"T\"HH24:MI:SSTZH",
"yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
"yyyy-mm-dd HH24:MI:SS",
"yyyy-mm-dd\"T\"HH24:MI:SS.US",
"yyyy-mm-dd\"T\"HH24:MI:SS"
};

Expand Down
15 changes: 15 additions & 0 deletions src/test/regress/expected/jsonb_jsonpath.out
Expand Up @@ -1920,6 +1920,21 @@ select jsonb_path_query('"2017-03-10T12:34:56+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10t12:34:56+3:10"', '$.datetime()');
ERROR: datetime format is not recognized: "2017-03-10t12:34:56+3:10"
HINT: Use a datetime template argument to specify the input data format.
select jsonb_path_query('"2017-03-10 12:34:56.789+3:10"', '$.datetime()');
jsonb_path_query
---------------------------------
"2017-03-10T12:34:56.789+03:10"
(1 row)

select jsonb_path_query('"2017-03-10T12:34:56.789+3:10"', '$.datetime()');
jsonb_path_query
---------------------------------
"2017-03-10T12:34:56.789+03:10"
(1 row)

select jsonb_path_query('"2017-03-10t12:34:56.789+3:10"', '$.datetime()');
ERROR: datetime format is not recognized: "2017-03-10t12:34:56.789+3:10"
HINT: Use a datetime template argument to specify the input data format.
select jsonb_path_query('"12:34:56"', '$.datetime().type()');
jsonb_path_query
--------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/test/regress/sql/jsonb_jsonpath.sql
Expand Up @@ -414,6 +414,9 @@ select jsonb_path_query('"2017-03-10 12:34:56+3:10"', '$.datetime().type()');
select jsonb_path_query('"2017-03-10 12:34:56+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10T12:34:56+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10t12:34:56+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10 12:34:56.789+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10T12:34:56.789+3:10"', '$.datetime()');
select jsonb_path_query('"2017-03-10t12:34:56.789+3:10"', '$.datetime()');
select jsonb_path_query('"12:34:56"', '$.datetime().type()');
select jsonb_path_query('"12:34:56"', '$.datetime()');
select jsonb_path_query('"12:34:56+3"', '$.datetime().type()');
Expand Down

0 comments on commit 7398e27

Please sign in to comment.