Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ All notable changes to this project will be documented in this file. It uses the
* Fixed a use-after-free of a foreign scan's batch memory context on rescan
that could corrupt memory and hang ([#296]).
* Fixed subsecond precision lost inserting timestamps over HTTP ([#300]).
* Fixed loss of subsecond precision in `to_timestamp(float8)` by mapping it
to ClickHouse's microsecond-precision `toDateTime64()` function ([#338]).
* Fixed `date_part('dow', ...)` and `EXTRACT(DOW FROM ...)` pushdown to use
PostgreSQL's Sunday (`0`) through Saturday (`6`) numbering, rather than
ClickHouse's default Monday through Sunday scheme. Thanks to Minh Vu for
Expand Down Expand Up @@ -211,6 +213,8 @@ All notable changes to this project will be documented in this file. It uses the
"ClickHouse/pg_clickhouse#335 Reject JSON paths containing NULL elements"
[#336]: https://github.com/ClickHouse/pg_clickhouse/pull/336
"ClickHouse/pg_clickhouse#336 Preserve array_length semantics"
[#338]: https://github.com/ClickHouse/pg_clickhouse/pull/338
"ClickHouse/pg_clickhouse#338 Preserve fractional seconds in to_timestamp()"

## [v0.3.2] — 2026-06-16

Expand Down
3 changes: 2 additions & 1 deletion doc/pg_clickhouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,8 @@ equivalents as follows:
* `jsonb_extract_path_text`: [sub-column syntax](https://clickhouse.com/docs/sql-reference/data-types/newjson#reading-json-paths-as-sub-columns)
* `jsonb_extract_path`: [toJSONString](https://clickhouse.com/docs/sql-reference/functions/json-functions#toJSONString) + [sub-column syntax](https://clickhouse.com/docs/sql-reference/data-types/newjson#reading-json-paths-as-sub-columns)
* `bit_count(bytea)`: [bitCount](https://clickhouse.com/docs/sql-reference/functions/bit-functions#bitcount)
* `to_timestamp(float8)`: [fromUnixTimestamp](https://clickhouse.com/docs/sql-reference/functions/date-time-functions#fromUnixTimestamp)
* `to_timestamp(float8)`: [toDateTime64](https://clickhouse.com/docs/sql-reference/functions/type-conversion-functions#todatetime64)
with microsecond precision and the `UTC` timezone.
* `to_char(timestamp[tz], fmt)`: [formatDateTime](https://clickhouse.com/docs/sql-reference/functions/date-time-functions#formatDateTime)
when `fmt` is a string constant whose every keyword has a faithful
ClickHouse equivalent. See [to_char()](#to_char) under Compatibility
Expand Down
6 changes: 2 additions & 4 deletions src/custom_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,11 +594,9 @@ lookup_builtin_func(Oid funcid, builtin_func_def* def) {
return true;
/* CH lacks "power", maps to pow */
case F_TO_TIMESTAMP_FLOAT8:
def->ch_name = "fromUnixTimestamp(toInt64";
def->paren_count = 2;
def->cf_type = CF_TO_TIMESTAMP;
def->ch_name = "\1";
return true;
/* ClickHouse doesn't work with subsecond precision */
/* timestamps. */
case F_TO_CHAR_TIMESTAMP_TEXT:
case F_TO_CHAR_TIMESTAMPTZ_TEXT:
def->cf_type = CF_TO_CHAR;
Expand Down
6 changes: 6 additions & 0 deletions src/deparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4406,6 +4406,12 @@ deparseFuncExpr(FuncExpr* node, deparse_expr_cxt* context) {
appendStringInfo(buf, "nowInBlock64(6, %s)", QUOTED_TZ);
return;
}
case CF_TO_TIMESTAMP: {
appendStringInfoString(buf, "toDateTime64(");
deparseExpr((Expr*)linitial(node->args), context);
appendStringInfoString(buf, ", 6, 'UTC')");
return;
}
case CF_DATE_TRUNC: {
Const* arg = (Const*)linitial(node->args);
char* trunctype = TextDatumGetCString(arg->constvalue);
Expand Down
1 change: 1 addition & 0 deletions src/include/fdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ typedef enum {
CF_CURRENT_DATABASE, /* CURRENT_DATABASE → string literal */
CF_CURRENT_SCHEMA, /* CF_CURRENT_SCHEMA → string literal */
CF_CLOCK_TIMESTAMP, /* clock_timestamp → nowInBlock64(6, $TZ) */
CF_TO_TIMESTAMP, /* to_timestamp → toDateTime64($arg, 6, 'UTC') */
CF_ARRAY_LENGTH, /* array_length(array, 1) → nullIf(length(), 0) */
CF_ARRAY_POSITION, /* array_position → nullIf(indexOf(), 0) */
CF_ARRAY_PREPEND, /* array_prepend → arrayPushFront, swap args */
Expand Down
17 changes: 11 additions & 6 deletions test/expected/functions.out
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(0);
Expand All @@ -1654,7 +1654,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(0);
Expand All @@ -1668,7 +1668,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
Expand All @@ -1678,14 +1678,19 @@ SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
(1 row)

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '2034-09-20 00:04:03'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '2034-09-20 00:04:03'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
i64 | f64
-----+-----
(0 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443.232);
i64 | f64
------------+----------------
2042323443 | 2042323443.232
Expand Down
17 changes: 11 additions & 6 deletions test/expected/functions_0.out
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(0);
Expand All @@ -1654,7 +1654,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(0);
Expand All @@ -1668,7 +1668,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
Expand All @@ -1678,14 +1678,19 @@ SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
(1 row)

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '2034-09-20 00:04:03'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '2034-09-20 00:04:03'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
i64 | f64
-----+-----
(0 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443.232);
i64 | f64
------------+----------------
2042323443 | 2042323443.232
Expand Down
17 changes: 11 additions & 6 deletions test/expected/functions_1.out
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(0);
Expand All @@ -1654,7 +1654,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(0);
Expand All @@ -1668,7 +1668,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
Expand All @@ -1678,14 +1678,19 @@ SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
(1 row)

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '2034-09-20 00:04:03'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '2034-09-20 00:04:03'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
i64 | f64
-----+-----
(0 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443.232);
i64 | f64
------------+----------------
2042323443 | 2042323443.232
Expand Down
17 changes: 11 additions & 6 deletions test/expected/functions_2.out
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(0);
Expand All @@ -1654,7 +1654,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(0);
Expand All @@ -1668,7 +1668,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
Expand All @@ -1678,14 +1678,19 @@ SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
(1 row)

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '2034-09-20 00:04:03'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '2034-09-20 00:04:03'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
i64 | f64
-----+-----
(0 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443.232);
i64 | f64
------------+----------------
2042323443 | 2042323443.232
Expand Down
17 changes: 11 additions & 6 deletions test/expected/functions_3.out
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(0);
Expand All @@ -1654,7 +1654,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(0);
Expand All @@ -1668,7 +1668,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(i64) = to_times
------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(i64)) = '1970-01-01 00:00:00'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(i64, 6, 'UTC') = '1970-01-01 00:00:00'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
Expand All @@ -1678,14 +1678,19 @@ SELECT * FROM t6 WHERE to_timestamp(i64) = to_timestamp(2042323443);
(1 row)

EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.t6
Output: i64, f64
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((fromUnixTimestamp(toInt64(f64)) = '2034-09-20 00:04:03'))
Remote SQL: SELECT i64, f64 FROM functions_test.t6 WHERE ((toDateTime64(f64, 6, 'UTC') = '2034-09-20 00:04:03'))
(3 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443);
i64 | f64
-----+-----
(0 rows)

SELECT * FROM t6 WHERE to_timestamp(f64) = to_timestamp(2042323443.232);
i64 | f64
------------+----------------
2042323443 | 2042323443.232
Expand Down
Loading