timescaledb/tsl/test/shared/sql/dist_queries.sql
Erik Nordström 8f9975d7be Fix crash during insert into distributed hypertable
For certain inserts on a distributed hypertable, e.g., involving CTEs
and upserts, plans can be generated that weren't properly handled by
the DataNodeCopy and DataNodeDispatch execution nodes. In particular,
the nodes expect ChunkDispatch as a child node, but PostgreSQL can
sometimes insert a Result node above ChunkDispatch, causing the crash.

Further, behavioral changes in PG14 also caused the DataNodeCopy node
to sometimes wrongly believe a RETURNING clause was present. The check
for returning clauses has been updated to fix this issue.

Fixes #4339
2022-06-02 17:25:33 +02:00

59 lines
1.6 KiB
PL/PgSQL

-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
-- Test DataNodeScan with subquery with one-time filter
SELECT
id
FROM
insert_test
WHERE
NULL::int2 >= NULL::int2 OR
EXISTS (SELECT 1 from dist_chunk_copy WHERE insert_test.id IS NOT NULL)
ORDER BY id;
-- Test query that inserts a Result node between ChunkDispatch and
-- DataNodeDispatch/DataNodeCopy. Fix for bug
-- https://github.com/timescale/timescaledb/issues/4339
SET timescaledb.enable_distributed_insert_with_copy=false;
BEGIN;
WITH upsert AS (
UPDATE matches
SET day = day - 1
WHERE location = 'old trafford'
RETURNING *
) INSERT INTO matches (day, location, team1, team2)
SELECT 9, 'old trafford', 'MNU', 'MNC'
WHERE NOT EXISTS (SELECT 1 FROM upsert);
SELECT * FROM matches ORDER BY 1,2,3,4;
ROLLBACK;
SET timescaledb.enable_distributed_insert_with_copy=true;
BEGIN;
WITH upsert AS (
UPDATE matches
SET day = day - 1
WHERE location = 'old trafford'
RETURNING *
) INSERT INTO matches (day, location, team1, team2)
SELECT 9, 'old trafford', 'MNU', 'MNC'
WHERE NOT EXISTS (SELECT 1 FROM upsert);
SELECT * FROM matches ORDER BY 1,2,3,4;
ROLLBACK;
-- Reference. The two queries above should be like this one:
BEGIN;
WITH upsert AS (
UPDATE matches_reference
SET day = day - 1
WHERE location = 'old trafford'
RETURNING *
) INSERT INTO matches_reference (day, location, team1, team2)
SELECT 9, 'old trafford', 'MNU', 'MNC'
WHERE NOT EXISTS (SELECT 1 FROM upsert);
SELECT * FROM matches_reference ORDER BY 1,2,3,4;
ROLLBACK;