Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4cac4dd

Browse files
author
Nikita Glukhov
committed
Add jsonpath datetime() extension: UNIX epoch time to timestamptz
1 parent 3e21c0e commit 4cac4dd

File tree

3 files changed

+98
-45
lines changed

3 files changed

+98
-45
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,47 +1670,28 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16701670
{
16711671
JsonbValue jbvbuf;
16721672
Datum value;
1673-
text *datetime_txt;
16741673
Oid typid;
16751674
int32 typmod = -1;
16761675
bool hasNext;
16771676

16781677
if (JsonbType(jb) == jbvScalar)
16791678
jb = JsonbExtractScalar(jb->val.binary.data, &jbvbuf);
16801679

1681-
if (jb->type != jbvString)
1680+
if (jb->type == jbvNumeric && !jsp->content.arg)
16821681
{
1683-
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
1684-
break;
1685-
}
1686-
1687-
datetime_txt = cstring_to_text_with_len(jb->val.string.val,
1688-
jb->val.string.len);
1689-
1690-
res = jperOk;
1691-
1692-
if (jsp->content.arg)
1693-
{
1694-
text *template_txt;
1695-
char *template_str;
1696-
int template_len;
1682+
/* Standard extension: unix epoch to timestamptz */
16971683
MemoryContext mcxt = CurrentMemoryContext;
16981684

1699-
jspGetArg(jsp, &elem);
1700-
1701-
if (elem.type != jpiString)
1702-
elog(ERROR, "invalid jsonpath item type for .datetime() argument");
1703-
1704-
template_str = jspGetString(&elem, &template_len);
1705-
template_txt = cstring_to_text_with_len(template_str,
1706-
template_len);
1707-
17081685
PG_TRY();
17091686
{
1710-
value = to_datetime(datetime_txt,
1711-
template_str, template_len,
1712-
false,
1713-
&typid, &typmod);
1687+
Datum unix_epoch =
1688+
DirectFunctionCall1(numeric_float8,
1689+
NumericGetDatum(jb->val.numeric));
1690+
1691+
value = DirectFunctionCall1(float8_timestamptz,
1692+
unix_epoch);
1693+
typid = TIMESTAMPTZOID;
1694+
res = jperOk;
17141695
}
17151696
PG_CATCH();
17161697
{
@@ -1724,29 +1705,80 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17241705
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
17251706
}
17261707
PG_END_TRY();
1727-
1728-
pfree(template_txt);
17291708
}
1730-
else
1709+
else if (jb->type == jbvString)
17311710
{
1732-
if (!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS TZH:TZM",
1711+
1712+
text *datetime_txt =
1713+
cstring_to_text_with_len(jb->val.string.val,
1714+
jb->val.string.len);
1715+
1716+
res = jperOk;
1717+
1718+
if (jsp->content.arg)
1719+
{
1720+
text *template_txt;
1721+
char *template_str;
1722+
int template_len;
1723+
MemoryContext mcxt = CurrentMemoryContext;
1724+
1725+
jspGetArg(jsp, &elem);
1726+
1727+
if (elem.type != jpiString)
1728+
elog(ERROR, "invalid jsonpath item type for .datetime() argument");
1729+
1730+
template_str = jspGetString(&elem, &template_len);
1731+
template_txt = cstring_to_text_with_len(template_str,
1732+
template_len);
1733+
1734+
PG_TRY();
1735+
{
1736+
value = to_datetime(datetime_txt,
1737+
template_str, template_len,
1738+
false,
1739+
&typid, &typmod);
1740+
}
1741+
PG_CATCH();
1742+
{
1743+
if (ERRCODE_TO_CATEGORY(geterrcode()) !=
1744+
ERRCODE_DATA_EXCEPTION)
1745+
PG_RE_THROW();
1746+
1747+
FlushErrorState();
1748+
MemoryContextSwitchTo(mcxt);
1749+
1750+
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
1751+
}
1752+
PG_END_TRY();
1753+
1754+
pfree(template_txt);
1755+
}
1756+
else
1757+
{
1758+
if (!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS TZH:TZM",
17331759
datetime_txt, &value, &typid, &typmod) &&
1734-
!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS TZH",
1760+
!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS TZH",
17351761
datetime_txt, &value, &typid, &typmod) &&
1736-
!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS",
1762+
!tryToParseDatetime("yyyy-mm-dd HH24:MI:SS",
17371763
datetime_txt, &value, &typid, &typmod) &&
1738-
!tryToParseDatetime("yyyy-mm-dd",
1764+
!tryToParseDatetime("yyyy-mm-dd",
17391765
datetime_txt, &value, &typid, &typmod) &&
1740-
!tryToParseDatetime("HH24:MI:SS TZH:TZM",
1766+
!tryToParseDatetime("HH24:MI:SS TZH:TZM",
17411767
datetime_txt, &value, &typid, &typmod) &&
1742-
!tryToParseDatetime("HH24:MI:SS TZH",
1768+
!tryToParseDatetime("HH24:MI:SS TZH",
17431769
datetime_txt, &value, &typid, &typmod) &&
1744-
!tryToParseDatetime("HH24:MI:SS",
1770+
!tryToParseDatetime("HH24:MI:SS",
17451771
datetime_txt, &value, &typid, &typmod))
1746-
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
1747-
}
1772+
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
1773+
}
17481774

1749-
pfree(datetime_txt);
1775+
pfree(datetime_txt);
1776+
}
1777+
else
1778+
{
1779+
res = jperMakeError(ERRCODE_INVALID_ARGUMENT_FOR_JSON_DATETIME_FUNCTION);
1780+
break;
1781+
}
17501782

17511783
if (jperIsError(res))
17521784
break;

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,8 +1113,6 @@ select _jsonpath_query(jsonb 'null', '$.datetime()');
11131113
ERROR: Invalid argument for SQL/JSON datetime function
11141114
select _jsonpath_query(jsonb 'true', '$.datetime()');
11151115
ERROR: Invalid argument for SQL/JSON datetime function
1116-
select _jsonpath_query(jsonb '1', '$.datetime()');
1117-
ERROR: Invalid argument for SQL/JSON datetime function
11181116
select _jsonpath_query(jsonb '[]', '$.datetime()');
11191117
_jsonpath_query
11201118
-----------------
@@ -1126,6 +1124,25 @@ select _jsonpath_query(jsonb '{}', '$.datetime()');
11261124
ERROR: Invalid argument for SQL/JSON datetime function
11271125
select _jsonpath_query(jsonb '""', '$.datetime()');
11281126
ERROR: Invalid argument for SQL/JSON datetime function
1127+
-- Standard extension: UNIX epoch to timestamptz
1128+
select _jsonpath_query(jsonb '0', '$.datetime()');
1129+
_jsonpath_query
1130+
--------------------------------
1131+
"Wed Dec 31 16:00:00 1969 PST"
1132+
(1 row)
1133+
1134+
select _jsonpath_query(jsonb '0', '$.datetime().type()');
1135+
_jsonpath_query
1136+
----------------------------
1137+
"timestamp with time zone"
1138+
(1 row)
1139+
1140+
select _jsonpath_query(jsonb '1490216035.5', '$.datetime()');
1141+
_jsonpath_query
1142+
----------------------------------
1143+
"Wed Mar 22 13:53:55.5 2017 PDT"
1144+
(1 row)
1145+
11291146
select _jsonpath_query(jsonb '"10-03-2017"', '$.datetime("dd-mm-yyyy")');
11301147
_jsonpath_query
11311148
-----------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,16 @@ select _jsonpath_query(jsonb '[null, 1, "abd", "abdabc"]', 'lax $[*] ? ((@ start
229229

230230
select _jsonpath_query(jsonb 'null', '$.datetime()');
231231
select _jsonpath_query(jsonb 'true', '$.datetime()');
232-
select _jsonpath_query(jsonb '1', '$.datetime()');
233232
select _jsonpath_query(jsonb '[]', '$.datetime()');
234233
select _jsonpath_query(jsonb '[]', 'strict $.datetime()');
235234
select _jsonpath_query(jsonb '{}', '$.datetime()');
236235
select _jsonpath_query(jsonb '""', '$.datetime()');
237236

237+
-- Standard extension: UNIX epoch to timestamptz
238+
select _jsonpath_query(jsonb '0', '$.datetime()');
239+
select _jsonpath_query(jsonb '0', '$.datetime().type()');
240+
select _jsonpath_query(jsonb '1490216035.5', '$.datetime()');
241+
238242
select _jsonpath_query(jsonb '"10-03-2017"', '$.datetime("dd-mm-yyyy")');
239243
select _jsonpath_query(jsonb '"10-03-2017"', '$.datetime("dd-mm-yyyy").type()');
240244
select _jsonpath_query(jsonb '"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy")');

0 commit comments

Comments
 (0)