Contents
Changelog
All notable changes to this project will be documented in this file. It uses the Keep a Changelog format, and this project adheres to Semantic Versioning.
v0.10.0 — 2026-08-11
⚡ Improvements
- Added the
clickhouse_server_version(server)function, which reports the ClickHouse server version (“major.minor.patch”) for a foreign server (#293). - Added pushdown for subqueries the planner cannot flatten into joins
(SubPlans): correlated and uncorrelated scalar aggregate subqueries,
EXISTS, and single-column equalityIN/NOT IN, inWHEREandHAVING. Covers TPC-H Q2, Q11, Q15, Q17, Q20, and Q22 shapes.NOT INpreserves PostgreSQL’s NULL semantics under ClickHouse’s two-valuedIN, deparsing with compensating guards when the columns involved are nullable (#315). Requires ClickHouse 25.8 or later; older servers still evaluate the subquery locally (#289). - Added
transform_null_in 0to the default value of thepg_clickhouse.session_settingsparameter, so that a ClickHouse server profile cannot silently change theINsemantics the pushdown rules rely on (#315). - Added or corrected pushdown for
IN-family operations on arrays. Previous behavior was missing or incorrect, either structurally or due to behavioral differences in the ClickHouse implementation of the operation. Corrected the structurally incorrect pushdown (#315) and handled ClickHouse behavioral changes using special case statements where needed (#317). - Added pushdown for more aggregate functions (#290):
- Mapped the following PostgreSQL ordered set aggregate functions to push
down to corresponding ClickHouse parametric aggregate functions (#291):
percentile_cont(double[])→quantiles()percentile_disc(double)→quantileExactLow()percentile_disc(double[])→quantilesExactLow()
- Added pushdown for
encode(bytea, fmt)with a constant format:encode(bytea, 'hex')→lower(hex())encode(bytea, 'base64')→base64Encode()wrapped to reproduce PostgreSQL’s MIME line break every 76 characters.encode(bytea, 'base64url')(PostgreSQL 19+) →base64URLEncode().
- Extended interval arithmetic pushdown to
dateandtimestampoperands and to interval subtraction, beyond the previoustimestamptz + interval. Deparses to ClickHouseINTERVAL <n> <unit>terms, one per nonzero month, day, and second component, replacing nestedaddMonths/addDays/addSecondscalls that mishandled day arithmetic on dates and drifted across DST boundaries (#301). - The binary driver now flushes an insert block once it buffers 64MiB,
bounding memory for large
COPY FROMandINSERT SELECTcommands (#303). - The binary driver now supports inserting into
Array(Nullable(T))columns (#316). - Added pushdown for the three-argument forms of
ltrim,rtrim, andbtrim(#307). - Added
clickhouse_query(server, sql), a set-returning function that runs a query against a configured foreign server and returns its rows typed by the caller’s column definition list (#309). - Added
clickhouse_perform(server, sql), a procedure that runs a statement against a configured foreign server and discards any result, for statements such as DDL that return no results (#329). - Deprecated
clickhouse_raw_query(), which will be removed in next release. Useclickhouse_query(server, sql)orCALL clickhouse_perform(server, sql), which use a foreign server rather than a connection string (#329). - Any ClickHouse column now reads into
textor another string type, rendered by the output function of the PostgreSQL type it maps to, rather than failing withcould not cast value(#329). - Added pushdown support for partial aggregates under partition-wise
aggregation, so a query over a partitioned table mixing local and foreign
partitions computes the foreign partition’s aggregate on ClickHouse
instead of fetching its rows. Covers decomposable aggregates (
count,sum,min,max,bool_and/bool_or,bit_and/bit_or), plusavgover integers andavg/var_pop/var_samp/stddev_pop/stddev_sampover floats. Aggregates with an internal transition state (anything overnumeric,avg(bigint),avg(interval)) still fall back to local aggregation. Requiresenable_partitionwise_aggregate(#298). - Disabled remote MIN/MAX optimization by raising
MinMaxAggPathcost rather than understating foreign scan cost (#310). - Added mapping to push down the re2 v0.4
@~operator to ClickHouse as thematch()function (#318). - Binary driver errors now name the column and type involved, for example
cannot encode integer into ClickHouse Array(Array(Int32)) (column "c2")in place ofunexpected PG/CH type pair for column 0(#326). - Improved array element coercion in the binary driver. Converting
Array(Int32)tobigint[], orquantilesExactLow()results intodouble precision[]no longer fails withcould not cast value from integer[] to bigint[](#326). - Added support for the third argument to
array_position()when it’s a positive constant value, pushing it down to a call toarraySlice()to start the search from the specified index. Thanks to Minh Vu for the PR (#334)! - The HTTP driver now uses ClickHouse’s Native format, sharing encoding and
decoding with binary driver. Only the deprecated
clickhouse_raw_query()function retainsTabSeparatedbehavior; it will likely be removed in favor ofclickhouse_query()andclickhouse_perform()in a future release. (#328) - Deprecated the
fetch_sizesetting, now ignored. With the switch to binary encoding, the HTTP driver always streams results the same as the binary driver. Settingfetch_sizetriggers a warning and will be removed in a future release. (#328)
🐞 Bug Fixes
- Fixed crashes when a single query ran more than one foreign scan on the binary (native-protocol) driver at once, such as a correlated subquery or a nested-loop join over foreign tables, colliding in the single connection. Each concurrently active scan now gets its own connection (#296).
- 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 the binary driver to use
pg_clickhouse.session_settingswith inserts. - Fixed undefined behavior: out-of-bounds reads in key/value iteration, and the
binary driver’s simple query path;
CollapsingMergeTreevalidation; missing rejection of non-Const/null units indate_trunc/date_partpushdown; NULL handling in record conversion; uncheckedcurl_easy_escapefailures; and unboundedDateTime64scale lookups (#313). - Fixed incorrect results from pushed-down
= ANY/<> ALLexpressions andINexpressions over constant lists and when aNULLcould reach the comparison, compensating for ClickHouse evaluatingINunder two-valued logic vs. PostgreSQL three-valueNULLlogic (#315, #317). - Fixed
<> ANY(array)deparsing to ClickHouse SQL that computes<> ALL, which was incorrect even with noNULLs involved: In Postgres,1 <> ANY('{1,5}')isTRUE. For now, do not push down (#315). - Fixed the pushdown of a
CASE arg WHEN ..expression without checking its branches when the tested expression was itself unshippable (#315). - Fixed an error that incorrectly selected an invalid relation OID when selecting the user to execute the remote query. Thanks to Kostia R for the PR (#319)!
- Fixed the omission of typmod behavior in the binary driver causing
incorrect values. For example, padding will now be preserved in
char(x)columns (#330). - Fixed
date_part('dow', ...)andEXTRACT(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 the PR (#331)! - Fixed the encoding of
byteaarray elements to use the same ClickHouse binary-literal serializer previously for scalar values, preventing PostgreSQLINlists from producing invalid or mismatchedFixedStringcomparisons. Thanks to @jxom for the PR (#333)! - Fixed
array_position()pushdown to returnNULL, rather than zero, when ClickHouse does not find an element. Thanks to Minh Vu for the PR (#334)! - Fixed
array_length()pushdown to preserve empty-array and requested dimension semantics. Thanks to Minh Vu for the PR (#336)! - Taught
json_extract_path*()andjsonb_extract_path*()not to push down when the path array contains anyNULLelements. Thanks to Minh Vu for the PR (#335)! - Fixed loss of subsecond precision in
to_timestamp(float8)by mapping it to the ClickHousetoDateTime64()function instead offromUnixTimestamp(). Thanks to Minh Vu for the PR (#338).
📚 Documentation
- Separated the list of custom ordered set aggregate functions provided by
pg_clickhouse (currently
quantile()andquantileExact()) from the Postgres ordered set aggregate functions, putting them under their own header, “Custom Ordered Set Aggregates”. - Fixed the links to the ClickHouse docs for the functions to which
ltrimandrtrimpush down. - Documented that minimum required version of ClickHouse is 23.3, not 23.0.
- Added a section on managing mixed local and foreign partitions under the
new “Partitioned Tables” header, as well as the example script
doc/offload-partition.sqlto demonstrate migrating data from a Postgres table to a ClickHouse foreign table #298. - Updated discussion of
COPYto document its efficient streaming behavior via the same code path asINSERT. - Noted the need to preserve certain settings in the
pg_clickhouse.session_settingsGUC when overriding the default value. - Documented that columns in Postgres that map to unexpected types in ClickHouse are not converted to text and passed to the input function for the Postgres type.
- Added “IN and NULL Semantics” section.
v0.3.2 — 2026-06-16
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.3 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Added a
compressionserver option for the binary driver to enable ClickHouse native protocol compression of query results andINSERTdata. Acceptsnone,lz4, orzstd, and defaults tolz4(#268). - Added a
secureserver option giving explicit control over TLS for both the binary and HTTP drivers, rather than inferring it from the host name and port. Acceptson(force TLS),off(force plaintext), orauto(the previous cloud-host/port heuristic, still the default). Thanks to Andrey Borodin for the PR (#272). - Added a
min_tls_versionserver option to set the minimum TLS protocol version negotiated by both drivers. AcceptsTLSv1,TLSv1.1,TLSv1.2, orTLSv1.3, and defaults to the TLS library’s own minimum (#272). - Added mapping for
regexp_match()to pushdown toextractGroups(), orarraySlice(extractAll(text, pattern), 1, 1)if the regex contains no capturing groups (#270).
🚀 Distribution
- Added support for PostgreSQL 19beta1 (#269).
🐞 Bug Fixes
- Fixed incorrect translation of regular expression flags introduced in
v0.2.0 to more accurately match the Postgres behavior
when executing in ClickHouse. We no longer automatically push down
-s, because it is enabled by default in both Postgres and ClickHouse. But the Postgres flagssandmcancel each other out, so we only setsif there is nomand if there is anmwe set(?m-s). - Changed the pushdown of the
pregular expression fag as-sinstead ofsto more accurately match the Postgres behavior (#271). - Eliminated push down of regular expression functions when the regular expression argument is not a constant (#270).
- Fixed a memory leak in the http driver when not using streaming (#281).
- Fixed a memory leak when a foreign scan repeatedly re-scans, typically a nested-loop join with a parameterized inner foreign scan (#282).
- Changed the deparsing of
ANY()with an empty array (WHERE x = ANY('{}')) to ahas()function rather than anIN()expression. This fixes errors on versions prior to ClickHouse 25, whereIN()with no list returns an error (#285)
🏗️ Build Setup
- Replaced code formatting, previously performed by
pg_bsd_indent, with clang-format using a modified “Mozilla style” with an emphasis on legibility and safety (#283).
v0.3.1 — 2026-05-02
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.3 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Replaced the
clickhouse-cppbinary client with ClickHouse/clickhouse-c, pulled in as a git submodule and included in the release package undervendor/clickhouse-c. This change eliminates conflicts between the C++ and Postgres memory & exception handling and streams query results by the ClickHouse block for reduced memory consumption. It also greatly reduces build time and the size of the library by over 75%. Thanks to serprex for the the new library and the PR (#254). - Added multidimensional array support across
SELECTandINSERTto both the binary and http drivers. Rectangular ClickHouseArray(Array(...))values now map to PostgreSQL multidimensional arrays (jagged arrays not supported) and PostgreSQL multidimensional arrays inserted into ClickHouseArray(Array(...))columns preserve their nesting. Thanks to serprex for the PR (#233). - Added pushdown for re2 extension functions introduced in pg_re2 v0.3.0:
re2extractallgroupshorizontal,re2extractallgroupsvertical,re2regexpquotemeta, andre2splitbyregexp. Thanks to serprex for the PR (#232). - Add pushdown for the Postgres regular expression flag
wasmin ClickHouse.
🐞 Bug Fixes
- Fixed incorrect casting of ClickHouse
UInt16values toint16in the Binary driver. They now correctly convert toint32(PostgresINT4). Part of the omnibus binary c driver conversion contributed by serprex (#233).
v0.3.0 — 2026-05-11
This release makes binary-compatible changes to the v0.2 releases. Once
installed, any existing use of pg_clickhouse v0.2 will benefit from its
improvements on reload. The only change that requires an upgrade revokes
EXECUTE from clickhouse_raw_query(). We recommend running this command
make this security-sensitive change:
ALTER EXTENSION pg_clickhouse UPDATE TO '0.3';
⚡ Improvements
- Added pushdown for re2 extension functions, if available, to their
ClickHouse equivalents (e.g.,
re2match→match,re2extractall→extractAll). Thanks to serprex for the PR (#204). - Added pushdown for fuzzystrmatch functions
soundex()andlevenshtein()(2-arg, mapped toeditDistanceUTF8). Thanks to serprex for the PR (#210). - Added mapping for
JSON=>jsonbto the binary driver (requires ClickHouse 24.10 or later). - Added support for ClickHouse
JSONmapped to Postgresjson, supporting all the same operators and functions as thejsonbmapping. - Added pushdown for
to_char(timestamp[tz], fmt)to ClickHouseformatDateTime(), with strict format-string validation. Only pushes down when the format is a constant whose every keyword has an identical CH equivalent (YYYY,MM,DD,DDD,HH24,HH12,HH,MI,SS,Q,Mon,Dy,AM/PM, plus lowercase variants). Thanks to serprex for the PR (#244). - Made builtin function pushdown opt-in: Postgres builtins now ship to ClickHouse only when explicitly mapped, so name or signature differences cannot silently alter results. Thanks to serprex for the PR (#245).
- Added explicit mappings for
mod,pow/power,bit_count(bytea), andreverse(text)(→reverseUTF8) to retain previously working pushdowns. Thanks to serprex for the PR (#245).
🐞 Bug Fixes
- Fixed
EXPLAIN (VERBOSE)failing with “could not find window clause for winref N” when window functions push down to ClickHouse. Thanks to serprex for the PR (#223). - Fixed the parsing of strings that start with
[in the http driver so that it no longer assumes it’s the start of an array. Thanks to Kaushik Iska for the PR (#234). - Fixed the parsing of strings in the http driver to distinguish a true
NULLvalue from a string containing\N. Thanks to Kaushik Iska for the PR (#235). - Fixed the
column_nameforeign-table column option being ignored byINSERT, which caused the binary engine to fail to match ClickHouse block columns and the HTTP engine to deparse PostgreSQL attribute names. Thanks to serprex for the PR (#231). - Fixed
length(text)andstrpos(text, text)pushdown to map tolengthUTF8andpositionUTF8rather than ClickHouse’s byte-countinglengthandposition, matching Postgres character semantics. Thanks to serprex for the PR (#245). - Stopped pushing down
asin,acos,atanh, andacosh: Postgres raises an error on out-of-range input where ClickHouse returnsNaN. Evaluating locally preserves Postgres semantics. Thanks to serprex for the PR (#245).
📚 Documentation
- Added “Extension Pushdown” section to the reference docs, covering re2, intarray, and fuzzystrmatch support.
- Added recommendation to the reference docs to consider using the re2 extension and disabling Postgres regular expression pushdown.
- Documented the
column_nameforeign table column option in the reference docs. - Added
jsonb_extract_path_text()andjsonb_extract_path()to the list of push down functions in the reference docs, along withjson_extract_path_text()andjson_extract_path(), which are new in this release. - Fixed the reversed descriptions of
->>and->in the list of pushed down operators in the reference docs.
🚀 Distribution
- Added the ca-certificates package and the re2 extension to the OCI (née Docker) images.
🚨 Security Fixes
- Added SQL to revoke
EXECUTEpermission onclickhouse_raw_query()fromPUBLIC. Leaving it executable byPUBLICwould allow any database user to reach internal services (metadata endpoints, private APIs, etc.) from the PostgreSQL server — a classic SSRF vector. This ensures that admins can limit access only to those who legitimately need to execute ad-hoc ClickHouse queries (e.g., a dedicated ClickHouse admin role). Thanks to Andrey Borodin for the PR (#228).
v0.2.0 — 2026-04-13
This release makes binary-compatible changes to the v0.1 releases. Once
installed, any existing use of pg_clickhouse v0.1 will benefit from its
improvements on reload. The only new feature that requires an upgrade is the
pgch_version() function. Run this command to add it to the extension:
ALTER EXTENSION pg_clickhouse UPDATE TO '0.2';
⚡ Improvements
- Changed the pushdown mappings for the current date and timestamp functions
to account for the session time zone and Postgres-standard millisecond
precision, as follows:
CURRENT_DATE->toDate(now(TZ))CURRENT_TIMESTAMPandLOCALTIMESTAMP=>now64(9, TZ)CURRENT_TIMESTAMP(n)andLOCALTIMESTAMP(n)=>now64(n, TZ)clock_timestamp(),statement_timestamp(), &transaction_timestamp()=>nowInBlock64(n, TZ)
- Added pushdown for the
CURRENT_TIMEandLOCALTIMESQL Value Functions totoTime64(now64(6, TZ), 6), supported by ClickHouse 25.8+. - Added
pgch_version(), which returns the full semantic version. This is the same value visible inpg_get_loaded_modules(), but available in Postgres versions prior to 18, and without having to load pg_clickhouse in advance. - Added support for pushing down the flags passed to
regexp_like()by prepending them to the regular expression (e.g.,(?i)foo). If any of the flags cannot be pushed down, the regular expression function will not be pushed own. - Added pushdown for
regexp_split_to_array()tosplitByRegexp(), including pushdown of applicable flags. - Added pushdown mappings for array functions:
array_cat,array_append,array_remove,array_to_string,cardinality,array_length,array_prepend,string_to_array,trim_array,array_fill,array_reverse,array_shuffle,array_sample,array_sort. - Added mapping for
split_part()to pushdownsplitByString()[n]. - Added pushdown for array operators:
@>(hasAll),<@(hasAll),&&(hasAny). - Array slice syntax (
arr[L:U],arr[:U],arr[L:]) now pushes down asarraySlice(). - Added mapping for
regexp_replace(4-arg)to pushdown toreplaceRegexpAll()when thegflag is set, and to prepend compatible flags to the pushed down expression, or not to push down if any are not compatible. - All regular expression functions with compatible flags and all regular
expression operators now push down prepended with
(?-s)unless thesflag is set, so that the behavior more closely approximates that of Postgres. - Added the
pg_clickhouse.pushdown_regexsetting to prevent regular expressions from being pushed down.
⬆️ Dependency Updates
- Updated vendored clickhouse-cpp library to v2.6.1.
🐞 Bug Fixes
- Fixed a malformed type name in the error message when the http driver is unable to map a ClickHouse type to a Postgres type.
- Fixed reversal of the arguments passed to the ClickHouse
match()function by the mapping fromregexp_like(). array_dims,array_ndims,array_lower,array_upper,array_replace,array_positions,array_fill (3-arg),array_sort (3-arg), andstring_to_array(3-arg)now evaluate locally instead of being pushed to ClickHouse where they would fail.- Changed pushdown for
regexp_replace(3-arg)fromreplaceRegexpAll()toreplaceRegexpOne().
📔 Notes
- Added tests to ensure that
concat_ws()successfully pushes down to the compatible function of the same name (an alias for concatWithSeparator).
v0.1.10 — 2026-04-06
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Added mapping for the
JSONandJSONB-> TEXTand->> TEXToperators to be passed down to ClickHouse using its sub-column syntax. Thanks Kaushik Iska for the PR (#169). - Added pushdown support for
jsonb_extract_path_text()andjsonb_extract_path()to ClickHouse sub-column syntax. Thanks Kaushik Iska for the PR (#176). - Added mapping to push down
now()to now64 rather than now, as previously, because PostgreSQL’snow()produces sub-second precision, so should its clickHouse equivalent. - Added mappings to push down the Postgres
statement_timestamp(),transaction_timestamp(), andclock_timestamp()functions to to nowInBlock64 (requires ClickHouse 25.8 or higher). - Pushdown window functions (
ROW_NUMBER,RANK,DENSE_RANK,LEAD,LAG,FIRST_VALUE,LAST_VALUE,NTH_VALUE,NTILE,CUME_DIST,PERCENT_RANK,MIN/MAX OVER) to ClickHouse instead of computing them locally. Thanks Kaushik Iska for the PR (#175). - Pushdown
bool_and/everyasgroupBitAnd,bool_orasgroupBitOr, andstring_aggasgroupConcatto ClickHouse. Thanks serprex for the PR (#184). - Added mapping to push down the Postgres “SQL Value Functions”, including
CURRENT_TIMESTAMP,CURRENT_USER, andCURRENT_DATABASE. - Changed the behavior of
CURRENT_DATABASE()to push down the name of the current Postgres database rather than to the ClickHousecurrent_database()function. - Added result set streaming to the HTTP driver. The new
fetch_sizeserver and table option specifies the size of each batch to stream and defaults to50000000, about 50MB. Set it to0to disable streaming altogether. A testing loading a 1GB table reduced memory consumption from over 1GB to 73MB peak. Thanks Kaushik Iska for the testing and PR (#181).
🐛 Bug Fixes
- Improved memory management, fixing potential crashes in out of memory situations. Thanks to serprex for the PRs (#173, #173).
- Fixed issue where the
-Mergesuffix was not consistently appended to aggregates onAggregateFunctioncolumns. Thanks to serprex for the PR (#179). - Fixed
NTILE,CUME_DIST, andPERCENT_RANKpushdown failing because the FDW emitted aROWS UNBOUNDED PRECEDINGframe clause that ClickHouse rejects for ranking functions. Thanks serprex for the PR (#184). regr_avgx,regr_avgy,regr_count,regr_intercept,regr_r2,regr_slope,regr_sxx,regr_sxy,regr_syy,json_agg_strict, andjsonb_agg_strictnow evaluate locally instead of being pushed to ClickHouse where they would fail. Thanks serprex for the PR (#184).
📔 Notes
- Eliminated use of a constant that required libcurl 7.87.0, restoring support for earlier versions.
- Introduced clang-tidy and integrated it into
make lintand for use in CI. Thanks to serprex for the PR (#177).
v0.1.6 — 2026-04-02
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Added support for the PostgreSQL
to_timestamp(float8)function, mapped tofromUnixTimestamp(toInt64())in ClickHouse.
🪲 Bug Fixes
- Disabled query pushdown for JSONB subscript syntax (e.g.,
col_name['field']) for now. Thanks Kaushik Iska for the PR (#161). - Added query cancellation via Ctrl-C and
statement_timeoutto the binary driver. Thanks Kaushik Iska for the PR (#162) that fixed this issue (#41). - Fixed
LIKE,ILIKE, and regex operator pushdown, including~~*,!~~*,~,!~,~*,!~*. Thanks Kaushik Iska for the PR (#164).
v0.1.5 — 2026-03-20
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
🚨 Security Fixes
- Changed the http driver connection function to raise an error if the database name contains line ending characters to prevent HTTP header injection.
- Fixed an SQL injection vulnerability in parsing of parameters to the
engine 'CollapsingMergeTree($sign)option toCREATE FOREIGN TABLE.
🪲 Bug Fixes
- Fixed a crash due to an unexpected EOF while the http driver parses a response. Thanks to @serprex for the fix (#153)
- Fixed a crash due to an unchecked memory allocation while the http driver reads a response. Thanks to @serprex for the fix (#154).
v0.1.4 — 2026-02-17
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Added support for the PostgreSQL
md5()function, mapped tolower(hex(MD5()))in ClickHouse. - Added support for mapping PostgreSQL BYTEA columns to ClickHouse String columns.
- Added explicit setting of
format_tsv_null_representationandoutput_format_tsv_crlf_end_of_lineto all http requests, as unexpected values will interfere with its operation. - Improved the error message from the binary driver when attempting to
insert a
NULLinto a column that is notNullable(T).
🪲 Bug Fixes
- Fixed binary driver errors when attempting to insert a
NULLvalue intoNullableNumeric, Text,Enum,UUID, andINETcolumns. Thanks to Rahul Mehta for the report (#140). - Fixed http driver array parsing, which previously did not properly parse
string values and would raise an error on values containing brackets
(
[]). Thanks to serprex for the spot (#142). - Fixed a bug where the binary driver would raise an error on an empty array.
📔 Notes
- Refactored and improved the http engine’s result processing, bringing it into closer alignment with the binary engine and removing double processing of row values.
- The http driver now ignores the following session settings from the
pg_clickhouse.session_settingsto prevent them from interfering with its operation:date_time_output_format,format_tsv_null_representation, andoutput_format_tsv_crlf_end_of_line.
v0.1.3 — 2026-01-23
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Changed the default mapping for
DateTimeandDateTime64values fromTIMESTAMPtoTIMESTAMPTZ, because ClickHouse storesDateTimes as a Unix timestamp, always normalized to UTC, even if it displays as a different time zone. As of the first bug fix listed below, pg_clickhouse (almost) always fetches these values in UTC, so can store them asTIMESTAMPTZvalues. - Implemented
INSERTsupport for the UUID and INET (IPv4 and IPv6) types. Thanks to Rahul Mehta for the report (#127)!
🪲 Bug Fixes
- Fixed time zone conversion in the http engine. Does not work with parameterized execution on ClickHouse versions prior to 25.8 due to ClickHouse Issue 88088; recommend using the binary engine for tables with timestamp values on earlier ClickHouse versions to avoid the issue.
- Fixed a server crash when attempting to insert types not yet supported by the binary engine.
🚀 Distribution
- Added the security policy.
📔 Notes
- Scripted the generation of the TPC-H results table and updated it in the README.
- Cleaned up some comments and old references to postgres_fdw left from the original fork in 2019.
- Added tests demonstrating subqueries that pg_clickhouse does not yet push down, to be improved in future releases.
🏗️ Build Setup
- Added pre-commit hooks to lint the code, including for indentation
enforced by
pg_bsd_indent. A new workflow ensures consistency for these quality checks. Relatedly, a number of issues found by the linters have been corrected. - Configured
make installcheckto run the tests in parallel, resulting in far faster test execution on multi-core systems. Adjusted the schemas in which some of the tests work to ensure they don’t stomp on each other.
v0.1.2 — 2026-01-07
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Added support for parameterized execution, including
PREPAREandEXECUTE, by converting PostgreSQL$1-style parameters to ClickHouse{param:type}-style parameters. - Added support for inserting arrays to the http engine.
🪲 Bug Fixes
- Fixed the http engine’s parsing of UUID arrays selected from ClickHouse.
- Fixed the binary engine’s conversion of Date values, which in arrays ended
up too large by several orders of magnitude (e.g.,
2025-12-05would be converted to10529827-09-17😱). Thanks to Tom Lane for the pointer to the proper function to easily convert epoch seconds to a date. - Fixed a binary engine bug where dates and timestamps for epoch 0
(
1970-01-01 00:00:00) rendered asNULL. - Added support for the
Date32ClickHouse type. - Fixed conversion of
array_agg()to support ClickHouse versions prior to 23.8. - Fixed the precision of fractional seconds in the binary engine’s
conversion of ClickHouse
DateTime64values to PostgresTIMESTAMP(#114).
📔 Notes
- Removed unused code designed to support custom PostgreSQL extensions: ajbool, ajtime, country, and istore.
- Tweaked cost estimation to encourage pushdown of
min()andmax().
📚 Documentation
- Documented
IMPORT FOREIGN SCHEMAidentifier case preservation behavior. - Fixed the Postgres Docker start and connect info in the tutorial.
- Fixed the commands to start and connect to the pg_clickhouse Docker image in the tutorial.
- Added complete DML documentation to the reference
docs, including the new
PREPARE/EXECUTEsupport andINSERT,SET,COPY, as well as shared library preloading. - Documented the Postgres aggregate functions known (via new tests) to push down to ClickHouse.
v0.1.1 — 2025-12-17
This release makes binary-only changes. Once installed, any existing use of
pg_clickhouse v0.1 will get its benefits on reload without needing to
ALTER EXTENSION UPDATE.
⚡ Improvements
- Refactored the internal handling of the
pg_clickhouse.session_settingsGUC to parse the settings only once rather than for every query sent to ClickHouse
🚨 Security Fixes
- Updated the SQL query rewriting to properly quote strings and identifiers
in SQL queries sent to ClickHouse, fixing potential SQL injection
vulnerabilities, notably via
IMPORT SCHEMA. This has the effect of preserving mixed-case and uppercase identifiers.
🪲 Bug Fixes
- Fixed a crash when sending an empty
COPY FROMvia the binary driver
⬆️ Dependency Updates
- Updated vendored clickhouse-cpp library
🏗️ Build Setup
- Fixed the
Makefiletargets so that callingmake installwithout first callingmakewill properly create the versioned SQL file.
📚 Documentation
- Added a versioning policy the documentation
- Fixed the badges and broken TPC-H links in README.md
- Added PGXN installation instructions to README.md
v0.1.0 — 2025-12-09
⚡ Improvements
- Improved function and aggregate pushdown
- Added TLS support to both the http and binary engines
- Added pushdown aggregate functions:
uniq()uniqExact()uniqCombined()uniqCombined64()uniqExact()uniqHLL12()uniqTheta()
- Added pushdown functions:
toUInt8()toUInt16()toUInt32()toUInt64()toUInt128()quantile()quantileExact()
- Mapped PostgreSQL
regexp_like()to push down to ClickHousematch()function - Mapped PostgreSQL
extract()to push down to equivalent ClickHouse DateTime extraction functions (already mapped todate_part()) - Mapped PostgreSQL
percentile_cont()ordered set aggregate function to push down to the ClickHousequantile()parametric aggregate function - Mapped the
COUNT()return value tobigint - Added the query text and, for the http engine, the status code to error messages
- Added
pg_clickhouse.session_settingsGUC, defaulting tojoin_use_nulls 1, group_by_use_nulls 1, final 1 - Added mappings and support for additional data types:
Bool=>booleanDecimal=>numericJSON=>jsonb(http engine only)
- Added the
dbnameoption to http engine connections, includingclickhouse_raw_query() - Added LEFT SEMI JOIN pushdown for
EXISTS()subqueries
🏗️ Build Setup
- Ported from clickhouse_fdw
- Made lots of general code cleanup
- Added PGXS build pipeline
- Added PGXN and GitHub release workflows
- Added
pg_clickhouseOCI image workflow that publishes to ghcr.io/clickhouse/pg_clickhouse, with tags for PostgreSQL versions 13-18
📚 Documentation
- Added tutorial in doc/tutorial.md
- Added reference documentation in doc/pg_clickhouse.md
🪲 Bug Fixes
- Fixed
dictGet(),argMin(), andargMax() - Fixed bug in filtered
COUNT() - Fixed
AggregateFunctionoption to propagate to a nested aggregate function call - Improved unsigned integer support
⬆️ Dependency Updates
- Updated vendored clickhouse-cpp library
- Reimplemented binary engine inserts with clickhouse-cpp improvements
- Support and tested against PostgreSQL 13-18
- Support and tested against ClickHouse 23-25
📔 Notes
- Set full version in
PG_MODULE_MAGIC_EXT - Set to default ports to TLS for ClickHouse Cloud host names