-- Binary-driver counterpart of partitioning.sql, exercising binary decode of -- the int8[]/float8[] partial transition states pushed to ClickHouse. Uses -- distinct object names so it can run alongside partitioning.sql. SET datestyle = 'ISO'; SET max_parallel_workers_per_gather = 0; CREATE SERVER pwagg_bin_svr FOREIGN DATA WRAPPER clickhouse_fdw OPTIONS(dbname 'pwagg_bin_test', driver 'binary'); CREATE USER MAPPING FOR CURRENT_USER SERVER pwagg_bin_svr; -- ClickHouse holds cold data CREATE SERVER pwagg_bin_admin FOREIGN DATA WRAPPER clickhouse_fdw; CREATE USER MAPPING FOR CURRENT_USER SERVER pwagg_bin_admin; CALL clickhouse_perform('pwagg_bin_admin', 'DROP DATABASE IF EXISTS pwagg_bin_test'); CALL clickhouse_perform('pwagg_bin_admin', 'CREATE DATABASE pwagg_bin_test'); CALL clickhouse_perform('pwagg_bin_admin', 'CREATE TABLE pwagg_bin_test.events (id Int32, ts Date, val Int32, amt Float64) ENGINE = MergeTree ORDER BY ts'); CALL clickhouse_perform('pwagg_bin_admin', $$INSERT INTO pwagg_bin_test.events VALUES (1,'2023-01-15',10,10),(2,'2023-02-10',20,20),(3,'2023-03-20',30,30),(4,'2023-04-05',40,40)$$); -- Partitioned table whose cold 2023 range lives on ClickHouse as a foreign -- partition while the hot 2024 range stays local: the layout a consumer builds -- when offloading old partitions (offload itself is left to the consumer) CREATE TABLE events_bin (id int, ts date, val int, amt float8) PARTITION BY RANGE (ts); CREATE FOREIGN TABLE events_bin_cold PARTITION OF events_bin FOR VALUES FROM ('2023-01-01') TO ('2024-01-01') SERVER pwagg_bin_svr OPTIONS (table_name 'events'); CREATE TABLE events_bin_hot PARTITION OF events_bin FOR VALUES FROM ('2024-01-01') TO ('2025-01-01'); INSERT INTO events_bin_hot VALUES (100,'2024-01-10',5,5), (101,'2024-02-15',15,15); SET enable_partitionwise_aggregate = on; -- Decomposable aggregates push the cold partial straight to ClickHouse EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*), sum(val), min(ts), max(ts) FROM events_bin; SELECT count(*), sum(val), min(ts), max(ts) FROM events_bin; -- avg(int) pushes its transition state as int8[2] {count, sum} EXPLAIN (VERBOSE, COSTS OFF) SELECT avg(val) FROM events_bin; SELECT avg(val) FROM events_bin; -- avg/var/stddev over float push float8[3] {N, sum, sum of squared deviations} EXPLAIN (VERBOSE, COSTS OFF) SELECT var_samp(amt) FROM events_bin; SELECT avg(amt), var_pop(amt), var_samp(amt), stddev_pop(amt), stddev_samp(amt) FROM events_bin; -- var_samp(int) keeps an INTERNAL numeric state, so it falls back to fetching -- the cold rows and aggregating locally EXPLAIN (VERBOSE, COSTS OFF) SELECT var_samp(val) FROM events_bin; SELECT var_samp(val) FROM events_bin; -- FILTER pushes too, as ClickHouse -If on each transition-state component EXPLAIN (VERBOSE, COSTS OFF) SELECT avg(val) FILTER (WHERE val > 15) FROM events_bin; SELECT avg(val) FILTER (WHERE val > 15), avg(amt) FILTER (WHERE amt > 15), var_samp(amt) FILTER (WHERE amt > 15) FROM events_bin; RESET enable_partitionwise_aggregate; -- Partitionwise join pushes down the cold self-join with no columns to fetch SET enable_partitionwise_join = on; SELECT count(*) FROM events_bin a JOIN events_bin b ON a.id = b.id AND a.ts = b.ts; RESET enable_partitionwise_join; -- Route inserted rows to ClickHouse and local partitions INSERT INTO events_bin VALUES (5,'2023-05-01',50,50), (102,'2024-03-01',25,25); COPY events_bin FROM stdin; 6 2023-06-01 60 60 103 2024-04-01 35 35 \. SELECT tableoid::regclass, * FROM events_bin WHERE id IN (5, 6, 102, 103) ORDER BY id; -- Move local row into ClickHouse partition UPDATE events_bin SET ts = '2023-03-01' WHERE ts = '2024-03-01' AND id = 102; SELECT tableoid::regclass, * FROM events_bin WHERE id = 102; DROP TABLE events_bin; DROP USER MAPPING FOR CURRENT_USER SERVER pwagg_bin_svr; CALL clickhouse_perform('pwagg_bin_admin', 'DROP DATABASE pwagg_bin_test'); DROP SERVER pwagg_bin_svr CASCADE;