v1.1.1
CompareGitHub
What's Changed
- Update to DuckDB v1.4.3 (#985)
- Include application_name in DuckDB its custom_user_agent
Full Changelog: https://github.com/duckdb/pg_duckdb/compare/v1.1.0...v1.1.1
DuckDB-powered Postgres for high performance apps & analytics.
What's Changed
Full Changelog: https://github.com/duckdb/pg_duckdb/compare/v1.1.0...v1.1.1
Added
map_extract, map_keys, map_values, cardinality, element_at, map_concat, map_contains, map_contains_entry, map_contains_value, map_entries, map_extract_value, and map_from_entries. (#902)use_ssl parameter to duckdb.create_simple_secret() function. (#956)STRUCT[], UNION[], MAP[]). (#922)duckdb.custom_user_agent setting. (#989)Changed
duckdb.force_execution as GUC_REPORT for better PgBouncer integration. When using PgBouncer in transaction pooling mode, you should configure track_extra_parameters to include duckdb.force_execution to ensure it syncs correctly across connections. (#982)Fixed
ORDER BY col DESC now uses NULLS FIRST semantics (matching Postgres), instead of NULLS LAST which was the previous DuckDB default. (#935)VARCHAR[] was incorrectly mapped to PostgreSQL VARCHAR[] instead of TEXT[]. This caused assertion failures during statistics analysis. (#979)duckdb.disabled_filesystems was set to LocalFileSystem explicitly. (#937)New Contributors
Full Changelog: https://github.com/duckdb/pg_duckdb/compare/v1.0.0...v1.1.0
The 1.0 release is finally here! A ton of features were added, and performance improved immensely, and of course lots of fixes... And that means pg_duckdb is now ready for production!
You can read the release blog on the MotherDuck website
Added
duckdb.threads_for_postgres_scan to configure how many threads it should use. ([#762])DOMAIN, VARINT, TIME, TIMETZ, BIT, VARBIT, UNION, MAP, STRUCT types. (#532, #626, #627, #628, #636, #678, #689, #669)duckdb.unresolved_type support min, date_trunc, length, regexp_replace, LIKE, ILIKE, SIMILAR TO. (#643)duckdb.unresolved_type to bytea and text. (#643, [#915])strftime, strptime, epoch, epoch_ms, epoch_us, epoch_ns, time_bucket, make_timestamp, make_timestamptz. (#643)COPY ... TO and COPY ... FROM for DuckDB tables. (#665)EXPLAIN (FORMAT JSON) for DuckDB queries. ([#654])ARRAY types from DuckDB, before only LIST was supported. ([#655])TABLESAMPLE. ([#559])duckdb.extension_directory, duckdb.temporary_directory and duckdb.max_temporary_directory_size settings. ([#704])duckdb.default_collation. ([#814])duckdb.azure_transport_option_type setting to configure Azure extension transport options, which can be used to workaround issue #882. ([#910])Changed
CALL duckdb.enable_motherduck(...) or equivalent CREATE SERVER and CREATE USER MAPPING commands. ([#668])duckdb.create_simple_secret or duckdb.create_azure_secret functions. Internally secrets are now stored SERVER and USER MAPPING for the duckdb foreign data wrapper. ([#697])duckdb.unsafe_allow_execution_inside_function to allow functions anyway. ([#764], [#884])duckdb.convert_unsupported_numeric_to_double. ([#795])ddb$ schema that table now uses the duckdb table access method by default. ([#650])duckdb tables in a ddb$ schema. ([#650])FORMAT JSON for COPY commands. (#665)COPY to use DuckDB execution when using duckdb.force_execution. (#665).parquet, .json, .ndjson, jsonl, .gz, .zst). (#665)COPY when copying from Azure and HTTP locations. ([#872])TEXT columns instead of VARCHAR columns when using DuckDB execution. ([#583])duckdb.extensions now get automatically installed before running any DuckDB query if duckdb.autoinstall_known_extensions is set to true. This helps with read-replica setups, where the extension gets installed on the primary and but the replica is queried. ([#801])duckdb.disabled_filesystems is now empty. To keep the default installation secure, LocalFileSystem will now be appended for any user that does not have the pg_read_server_files and pg_write_server_files privileges. ([#802])LIKE expressions and upper()/lower() calls to Postgres storage. These expressions can sometimes be pushed down to the index. ([#808])duckdb.max_memory/duckdb.memory_limit to accept integer values instead of a string, to avoid users entering values that DuckDB does not understand. This breaks backwards compatibility slightly: MiB, GiB etc suffixes are now not supported anymore, only MB, GB etc suffixes are now allowed. ([#883])Fixed
postgres extension for DuckDB (a.k.a. postgres_scanner) into pg_duckdb ([#607])max_memory in Postgres if duckdb.max_memory/duckdb.memory_limit is set to the empty string. ([#614])DatumToString. ([#639])pg_duckdb in databases with different encoding than UTF8. ([#703])CREATE TABLE AS and materialized views if DuckDB execution and Postgres execution did not agree on the types that a query would return. ([#706])duckdb.row (like read_csv & read_parquet) in a CTE. ([#718])CREATE TABLE AS statement in a plpgqsl function ([#735])duckdb.row for queries that don't use those those functions. ([#811])\) or LIKE ... ESCAPE expressions. ([#815])SET TRANSACTION ISOLATION. ([#834])…(truncated)
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="logo-dark.svg"> <img width="800" src="logo-light.svg" alt="pg_duckdb logo" /> </picture> </p>
pg_duckdb is a Postgres extension that embeds DuckDB's columnar-vectorized analytics engine and features into Postgres. We recommend using pg_duckdb to build high performance analytics and data-intensive applications. See the README for install instructions and example usage. Below are the release notes for the 0.3.0 release. The only difference between 0.3.0 and 0.3.1 is a change to CI to fix pushing releases to Docker Hub.
Added
AS (id bigint, name text) syntax is no longer supported when using read_parquet, iceberg_scan, etc. The new syntax is as follows: (#531)SELECT * FROM read_parquet('file.parquet');
SELECT r['id'], r['name'] FROM read_parquet('file.parquet') r WHERE r['age'] > 21;duckdb.query function which allows using DuckDB query syntax in Postgres. (#531)approx_count_distinct DuckDB aggregate. (#499)bytea (aka blob), uhugeint,jsonb, timestamp_ns, timestamp_ms, timestamp_s & interval types. (#511, #525, #513, #534, #573)duckdb.allow_community_extensions setting.Changed
duckdb.raw_query, duckdb.cache_info, duckdb.cache_delete and duckdb.recycle_db as non-superusers. (#572)Fixed
COPY commands. This allows using PARTITION_BY as one of the COPY options. (#465)timestamp with timezone field by enabling DuckDB its icu extension by default. (#512)read_parquet functions when not using superuser privileges. (#550)psql) would be ignored (#548, #584, #587)New Contributors
Full Changelog: https://github.com/duckdb/pg_duckdb/compare/v0.2.0...v0.3.1
pg_duckdb is a Postgres extension that embeds DuckDB's columnar-vectorized analytics engine and features into Postgres. We recommend using pg_duckdb to build high performance analytics and data-intensive applications. See the README for install instructions and example usage.
Added
duckdb.delta_scan(...) function. (#403)duckdb.read_json(...) function. (#405)float , numeric and uuid arrays. (#282)duckdb.cache_info() and duckdb.cache_delete() functions. (#434)scope column to duckdb.secrets table. (#461)duckdb.motherduck_default_database setting. (#470)duckdb.install_extension() is usually not necessary anymore. (#484)Changed
Fixed
CREATE SCHEMA AUTHORIZATION. (#423)DEFAULT values. (#448)duckdb.motherduck_postgres_database in postgresql.conf. (#476)New Contributors
Full Changelog: https://github.com/duckdb/pg_duckdb/compare/v0.1.0...v0.2.0
Initial release :tada:
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="logo-dark.svg"> <img width="800" src="logo-light.svg" alt="pg_duckdb logo" /> </picture> </p>
<p align="center"> <strong>PostgreSQL extension for DuckDB</strong><br> </p>
<p align="center"> <a href="https://hub.docker.com/r/pgduckdb/pgduckdb"><img src="https://img.shields.io/docker/pulls/pgduckdb/pgduckdb?style=flat-square&logo=docker" alt="Docker Pulls"></a> <a href="https://github.com/duckdb/pg_duckdb/releases"><img src="https://img.shields.io/github/v/release/duckdb/pg_duckdb?style=flat-square&logo=github" alt="GitHub Release"></a> <a href="https://github.com/duckdb/pg_duckdb/blob/main/LICENSE"><img src="https://img.shields.io/github/license/duckdb/pg_duckdb?style=flat-square" alt="License"></a> </p>
pg_duckdb integrates DuckDB's columnar-vectorized analytics engine into PostgreSQL, enabling high-performance analytics and data-intensive applications. Built in collaboration with Hydra and MotherDuck.
pg_duckdb will automatically use DuckDB's SQL engine to execute them when you set duckdb.force_execution=true.pg_duckdb workspg_duckdb automatically accelerates your existing analytical queries.
SELECT statements as you normally would, and pg_duckdb will use DuckDB's engine to execute them.pg_duckdb works directly with your existing PostgreSQL tables.This is the most common and straightforward use case. If you have a standard PostgreSQL table, you can query it using standard SQL.
Example:
Let's say you have a PostgreSQL table named orders (to create it, see syntax guide). To run an analytical query, you just write standard SQL, configure duckdb.force_execution and pg_duckdb will handle the rest.
SET duckdb.force_execution = true;
SELECT
order_date,
COUNT(*) AS number_of_orders,
SUM(amount) AS total_revenue
FROM
orders
GROUP BY
order_date
ORDER BY
order_date;pg_duckdb allows you to query external files (like Parquet or CSV) as if they were tables in your database. This is perfect for querying data lakes from pg_duckdb. To learn more on these functions, see read functions documentation.
-- Setup S3 access in seconds directly from SQL
SELECT duckdb.create_simple_secret(
type := 'S3', key_id := 'your_key', secret := 'your_secret', region := 'us-east-1'
);
SELECT
r['product_name'], -- 'r' is to iterate on the row object returned from read_parquet()
AVG(r['rating']) AS average_rating
FROM
read_parquet('s3://your-bucket/reviews.parquet') r
GROUP BY
r['product_name']
ORDER BY
average_rating DESC;You can easily join your PostgreSQL tables with external data from your data lake.
-- Join a PostgreSQL table with a remote Parquet file
SELECT
o.product_name,
o.total_revenue,
r.average_rating
FROM
(
-- First, aggregate our local orders data
SELECT
product_name,
SUM(amount) AS total_revenue
FROM
orders
GROUP BY
product_name
) o
JOIN
(
-- Then, aggregate our remote reviews data
SELECT
r['product_name'] AS product_name,
AVG(r['rating']) AS average_rating
FROM
read_parquet('s3://your-bucket/reviews.parquet') r
GROUP BY
r['product_name']
) r ON o.product_name = r.product_name
ORDER BY
o.total_revenue DESC;Work with modern data formats like DuckLake, Iceberg and Delta Lake. To learn more, see extensions documentation.
-- Query Apache Iceberg tables with time travel
SELECT duckdb.install_extension('iceberg');
SELECT * FROM iceberg_scan('s3://warehouse/sales_iceberg', version := '2024-03-15-snapshot')
-- Process Delta Lake with schema evolution
SELECT duckdb.install_extension('delta');
SELECT * FROM delta_scan('s3://lakehouse/user_events')pg_duckdb integrates with MotherDuck, a cloud analytics platform. This allows you to run your queries on MotherDuck's powerful compute infrastructure, while still using your existing PostgreSQL tables.
To learn more, see MotherDuck documentation.
-- Connect to MotherDuck
CALL duckdb.enable_motherduck('<your_motherduck_token>');-- Your existing MotherDuck tables appear automatically
SELECT region, COUNT(*) FROM my_cloud_analytics_table;
-- Create cloud tables that sync across teams
CREATE TABLE real_time_kpis USING duckdb AS
SELECT
date_trunc('day', created_at) as date,
COUNT(*) as daily_signups,
SUM(revenue) as daily_revenue
FROM user_events
GROUP BY date;Run PostgreSQL with pg_duckdb pre-installed in a docker container:
docker run -d -e POSTGRES_PASSWORD=duckdb pgduckdb/pgduckdb:18-v1.1.1With MotherDuck:
export MOTHERDUCK_TOKEN=<your_token>
docker run -d -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN pgduckdb/pgduckdb:18-v1.1.1You can also get started using Hydra:
pip install hydra-cli
hydraCompile from source:
git clone https://github.com/duckdb/pg_duckdb
cd pg_duckdb
make installSee compilation guide for detailed instructions.
See settings documentation for complete configuration options.
| Topic | Description |
|---|---|
| Functions | Complete function reference |
| Syntax Guide & Gotchas | Quick reference for common SQL patterns and things to know |
| Types | Supported data types and advanced types usage |
| MotherDuck | Cloud integration guide |
| Secrets | Credential management |
| Extensions | DuckDB extension usage |
| Transactions | Transaction behavior |
| Compilation | Build from source |
Note: Advanced DuckDB types (STRUCT, MAP, UNION) require DuckDB execution context. Use duckdb.query() for complex type operations and TEMP tables for DuckDB table creation in most cases. See Types documentation for details.
pg_duckdb excels at:
We welcome contributions! Please see:
Licensed under the MIT License.
<p align="center"> <strong>Built with ❤️</strong><br> in collaboration with <a href="https://hydra.so">Hydra</a> and <a href="https://motherduck.com">MotherDuck</a> </p>