Skip to content
Merged
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
7 changes: 4 additions & 3 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ jobs:
strategy:
fail-fast: false
matrix:
pgv: [18, 17, 16, 15, 14]
pgv: [19, 18, 17, 16, 15, 14]
steps:
- name: Checkout the Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with: { submodules: recursive }
- name: Set up Depot CLI
uses: depot/setup-action@v1
- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -34,6 +34,7 @@ jobs:
- name: Build${{ startsWith(github.ref, 'refs/tags') && ' and Push' || '' }}
uses: depot/bake-action@v1
with:
files: dist/docker-bake.hcl
project: vrpfjb99c5
platforms: linux/amd64,linux/arm64
pull: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/clickhouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Install Extensions
run: pgxn install re2
- name: Checkout the Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with: { submodules: recursive }
- name: Start ClickHouse
env: { CH_RELEASE: "${{ matrix.ch }}" }
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Install Postgres
run: NO_CLUSTER=1 pg-start ${{ env.pg }} libcurl4-openssl-dev uuid-dev liblz4-dev libzstd-dev clang-tidy bear shellcheck
- name: Checkout the Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with: { submodules: recursive }
- name: Install pre-commit
run: make debian-install-lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Install Extensions
run: pgxn install re2
- name: Checkout the Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with: { submodules: recursive }
- name: Start ClickHouse
run: .github/ubuntu/clickhouse.sh
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
container: pgxn/pgxn-tools
steps:
- name: Check out the repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Start Postgres
run: pg-start 19 libcurl4-openssl-dev uuid-dev liblz4-dev libzstd-dev
- name: Start ClickHouse
Expand All @@ -38,7 +38,7 @@ jobs:
if: startsWith( github.ref, 'refs/tags/v' )
- name: Create GitHub Release
if: startsWith( github.ref, 'refs/tags/v' )
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
name: "Release ${{ github.ref_name }}"
body_path: "${{ steps.notes.outputs.file }}"
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ All notable changes to this project will be documented in this file. It uses the
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
"Semantic Versioning 2.0.0"

## [v0.11.1] — Unreleased

### 🚀 Distribution

* Added Postgres 19beta4 image.
* Added [CloudNativePG] extension images.

[v0.11.1]: https://github.com/ClickHouse/pg_clickhouse/compare/v0.11.0...v0.11.1
[CloudNativePG]: https://cloudnative-pg.io/ "Run PostgreSQL The Kubernetes way"

## [v0.11.0] — 2026-09-30

This release makes binary-compatible changes to the v0.10 releases. Once
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ print-% : ; $(info $* is $(flavor $*) variable set to "$($*)") @true
REGISTRY ?= localhost:5001
REVISION := $(shell git rev-parse --short HEAD)
PLATFORMS ?= linux/amd64,linux/arm64
PG_VERSIONS ?= 18,17,16,15,14
PG_VERSIONS ?= 19,18,17,16,15,14
.PHONY: image # Build the linux/amd64 OCI image.
image:
registry=$(REGISTRY) version=$(DISTVERSION) revision=$(REVISION) pg_versions=$(PG_VERSIONS) \
docker buildx bake --set "*.platform=$(PLATFORMS)" \
docker buildx bake --file dist/docker-bake.hcl --set "*.platform=$(PLATFORMS)" \
$(if $(filter true,$(PUSH)),--push,) \
$(if $(filter true,$(LOAD)),--load,) \
$(if $(filter true,$(LOAD)),--load,)

bake-vars:
@echo "registry=$(REGISTRY)"
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ with 36 GB of memory.
| [Query 21] | 1145 ms | 4470 ms | |
| [Query 22] | 270 ms | 45 ms | ✼ |

## Installation

### Compile From Source

#### General Unix
Expand Down Expand Up @@ -209,6 +211,42 @@ You need to run the test suite using a super user, such as the default
make installcheck PGUSER=postgres
```

### CloudNativePG

Add pg_clickhouse to a [CloudNativePG] cluster using [ExtensionConfiguration]:

```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
# ... <snip>
postgresql:
# ExtensionConfiguration
extensions:
- name: pg_clickhouse
image:
reference: ghcr.io/ClickHouse/cnpg-pg_clickhouse:{pg_major_version}-{pg_clickhouse_version}
```

To load it into a database, use [ExtensionSpec]:

```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: pg_clickhouse-cluster
spec:
name: app
owner: app
cluster:
name: pg_clickhouse-cluster
extensions:
- name: pg_clickhouse
version: {pg_clickhouse_version}
```

### Loading

Once `pg_clickhouse` is installed, you can add it to a database by connecting
Expand Down Expand Up @@ -292,6 +330,11 @@ adding DML features. Our road map:
[LibSSL]: https://openssl-library.org "OpenSSL Library"
[TPC-H]: https://www.tpc.org/tpch/
[re2]: https://github.com/ClickHouse/pg_re2 "pg_re2: ClickHouse-compatible regex functions using RE2"
[CloudNativePG]: https://cloudnative-pg.io/ "Run PostgreSQL The Kubernetes way"
[ExtensionConfiguration]: https://cloudnative-pg.io/docs/devel/cloudnative-pg.v1#extensionconfiguration
"CloudNativePG Docs: ExtensionConfiguration:
[ExtensionSpec]: https://cloudnative-pg.io/docs/devel/cloudnative-pg.v1#extensionspec
"CloudNativePG Docs: ExtensionSpec:

[Query 1]: https://github.com/ClickHouse/pg_clickhouse/blob/main/dev/tpch/queries/1.sql
[Query 2]: https://github.com/ClickHouse/pg_clickhouse/blob/main/dev/tpch/queries/2.sql
Expand Down
76 changes: 76 additions & 0 deletions dist/cnpg.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
ARG PG_MAJOR=19
ARG BASE=postgres

FROM $BASE AS builder
ARG PG_MAJOR

USER 0

WORKDIR /work
COPY . .
RUN set -eux && \
# Initial system libraries
ldconfig -p | awk '{print $NF}' | grep '^/' | sort | uniq > /tmp/base-image-libs.out && \
# Install Dependencies
apt-get update && apt-get install -y --no-install-recommends \
postgresql-server-dev-$PG_MAJOR \
libcurl4-openssl-dev \
uuid-dev \
make \
libssl-dev \
liblz4-dev \
libzstd-dev \
libicu-dev \
g++

RUN make && make install DESTDIR=/dest

# Gather dependent system libraries and their licenses; based on
# https://github.com/cloudnative-pg/postgres-extensions-containers/blob/main/postgis/Dockerfile
RUN mkdir -p /system /licenses && \
# Get libraries
ldd /dest/usr/lib/postgresql/$PG_MAJOR/lib/pg_clickhouse*.so \
| awk '{print $3}' | grep '^/' | sort | uniq > /tmp/all-deps.out && \
# Extract all the libs that aren't already part of the base image
comm -13 /tmp/base-image-libs.out /tmp/all-deps.out > /tmp/libraries.out && \
while read -r lib; do \
resolved=$(readlink -f "$lib"); \
dir=$(dirname "$lib"); \
base=$(basename "$lib"); \
# Copy the real file
cp -a "$resolved" /system/; \
# Reconstruct all its symlinks
for file in "$dir"/"${base%.so*}.so"*; do \
[ -e "$file" ] || continue; \
# If it's a symlink and it resolves to the same real file, we reconstruct it
if [ -L "$file" ] && [ "$(readlink -f "$file")" = "$resolved" ]; then \
ln -sf "$(basename "$resolved")" "/system/$(basename "$file")"; \
fi; \
done; \
done < /tmp/libraries.out && \
# Get licenses
for lib in $(find /system -maxdepth 1 -type f -name '*.so*'); do \
# Get the name of the pkg that installed the library
pkg=$(dpkg -S "$(basename "$lib")" | grep -v "diversion by" | awk -F: '/:/{print $1; exit}'); \
[ -z "$pkg" ] && continue; \
mkdir -p "/licenses/$pkg" && cp -a "/usr/share/doc/$pkg/copyright" "/licenses/$pkg/copyright"; \
done

FROM scratch
ARG VERSION
ARG PG_MAJOR

# Licenses
COPY --from=builder /licenses /licenses/
COPY LICENSE.md /licenses/postgresql-$PG_MAJOR-pg_clickhouse-$VERSION/copyright

# Libraries
COPY --from=builder /dest/usr/lib/postgresql/$PG_MAJOR/lib /lib

# Share
COPY --from=builder /dest/usr/share/postgresql/$PG_MAJOR/extension /share/extension

# System libs
COPY --from=builder /system /system/

USER 65532:65532
145 changes: 145 additions & 0 deletions dist/docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Variables to be specified externally.
variable "registry" {
default = "ghcr.io/clickhouse"
description = "The image registry."
}

variable "version" {
default = ""
description = "The release version."
}

variable "revision" {
default = ""
description = "The current Git commit SHA."
}

# Postgres versions to build. Pass comma-delimited list: pg_versions=18,16.
variable "pg_versions" {
type = list(number)
default = [19, 18, 17, 16, 15, 14]
}

variable "os_name" {
default = "trixie"
description = "The name of the base Debian distribution."
}

# Values to use in the targets.
now = timestamp()
authors = "David E. Wheeler"
url = "https://github.com/ClickHouse/pg_clickhouse"

group "default" {
# Exclude cnpg if not building for Postgres 18 or higher.
targets = length([for v in pg_versions : v if v >= 18]) > 0 ? ["pg_clickhouse", "cnpg"] : ["pg_clickhouse"]
}

target "pg_clickhouse" {
platforms = ["linux/amd64", "linux/arm64"]
matrix = {
pgv = pg_versions
}
name = "pg_clickhouse-${pgv}"
context = "."
dockerfile = "dist/pg.Dockerfile"
args = {
PG_MAJOR = "${pgv}"
BASE = "postgres:${base_version("${pgv}")}-${os_name}"
}
tags = [
"${registry}/pg_clickhouse:${pgv}",
"${registry}/pg_clickhouse:${pgv}-${version}",
]
annotations = [
"index,manifest:org.opencontainers.image.created=${now}",
"index,manifest:org.opencontainers.image.url=${url}",
"index,manifest:org.opencontainers.image.source=${url}",
"index,manifest:org.opencontainers.image.version=${pgv}-${version}",
"index,manifest:org.opencontainers.image.revision=${revision}",
"index,manifest:org.opencontainers.image.vendor=${authors}",
"index,manifest:org.opencontainers.image.title=PostgreSQL ${pgv} with pg_clickhouse ${version}",
"index,manifest:org.opencontainers.image.description=PostgreSQL ${pgv} with pg_clickhouse ${version} on ${os_name}",
"index,manifest:org.opencontainers.image.documentation=${url}",
"index,manifest:org.opencontainers.image.authors=${authors}",
"index,manifest:org.opencontainers.image.licenses=PostgreSQL AND Apache-2.0",
"index,manifest:org.opencontainers.image.base.name=postgres",
]
labels = {
"org.opencontainers.image.created" = "${now}",
"org.opencontainers.image.url" = "${url}",
"org.opencontainers.image.source" = "${url}",
"org.opencontainers.image.version" = "${pgv}-${version}",
"org.opencontainers.image.revision" = "${revision}",
"org.opencontainers.image.vendor" = "${authors}",
"org.opencontainers.image.title" = "PostgreSQL ${pgv} with pg_clickhouse ${version}",
"org.opencontainers.image.description" = "PostgreSQL ${pgv} with pg_clickhouse ${version} on ${os_name}",
"org.opencontainers.image.documentation" = "${url}",
"org.opencontainers.image.authors" = "${authors}",
"org.opencontainers.image.licenses" = "PostgreSQL AND Apache-2.0"
"org.opencontainers.image.base.name" = "postgres",
}
}

target "cnpg" {
platforms = ["linux/amd64", "linux/arm64"]
matrix = {
pgv = [for v in pg_versions : v if v >= 18]
}
name = "cnpg-pg_clickhouse-${pgv}"
context = "."
tags = [
"${registry}/cnpg-pg_clickhouse:${pgv}",
"${registry}/cnpg-pg_clickhouse:${pgv}-${version}",
]
dockerfile = "dist/cnpg.Dockerfile"
args = {
PG_MAJOR = "${pgv}"
BASE = "ghcr.io/cloudnative-pg/postgresql:${base_version("${pgv}")}-minimal-${os_name}"
VERSION = "${version}"
}
annotations = [
"index,manifest:org.opencontainers.image.created=${now}",
"index,manifest:org.opencontainers.image.url=${url}",
"index,manifest:org.opencontainers.image.source=${url}",
"index,manifest:org.opencontainers.image.version=${version}",
"index,manifest:org.opencontainers.image.revision=${revision}",
"index,manifest:org.opencontainers.image.vendor=${authors}",
"index,manifest:org.opencontainers.image.title=pg_clickhouse ${version} ${os_name}",
"index,manifest:org.opencontainers.image.description=pg_clickhouse ${version} container image for PostgreSQL ${pgv} on ${os_name}",
"index,manifest:org.opencontainers.image.documentation=${url}",
"index,manifest:org.opencontainers.image.authors=${authors}",
"index,manifest:org.opencontainers.image.licenses=PostgreSQL AND Apache-2.0",
"index,manifest:org.opencontainers.image.base.name=scratch",
"index,manifest:io.cloudnativepg.image.base.name=ghcr.io/cloudnative-pg/postgresql:${pgv}-minimal-${os_name}",
"index,manifest:io.cloudnativepg.image.base.os=${os_name}",
"index,manifest:io.cloudnativepg.image.base.pgmajor=${pgv}",
"index,manifest:io.cloudnativepg.image.sql.version=${version}",
]
labels = {
"org.opencontainers.image.created" = "${now}",
"org.opencontainers.image.url" = "${url}",
"org.opencontainers.image.source" = "${url}",
"org.opencontainers.image.version" = "${version}",
"org.opencontainers.image.revision" = "${revision}",
"org.opencontainers.image.vendor" = "${authors}",
"org.opencontainers.image.title" = "pg_clickhouse ${version} ${os_name}",
"org.opencontainers.image.description" = "pg_clickhouse ${version} container image for PostgreSQL ${pgv} on ${os_name}",
"org.opencontainers.image.documentation" = "${url}",
"org.opencontainers.image.authors" = "${authors}",
"org.opencontainers.image.licenses" = "PostgreSQL AND Apache-2.0"
"org.opencontainers.image.base.name" = "scratch",
"io.cloudnativepg.image.base.name" = "ghcr.io/cloudnative-pg/postgresql:${pgv}-minimal-${os_name}",
"io.cloudnativepg.image.base.os" = "${os_name}",
"io.cloudnativepg.image.base.pgmajor" = "${pgv}",
"io.cloudnativepg.image.sql.version" = "${version}",
}
}

# Determines the version string used in image tags. Required because beta
# versions have "betaX" in the version name, whereas final releases do not.
# Must be updated upon the release of 19.0 and the introduction of 20beta1.
function base_version {
params = [ pgv ]
result = pgv == 19 ? "${pgv}beta4" : pgv
}
Loading
Loading