Fix DecompressChunk path generation

The non-parallel pathes generated by DecompressChunk were
incorrectly marked as parallel_safe even when the child scan
was not parallel aware. Leading to incorrect query results
when those pathes were used in a parallel plan.
Additionaly DecompressChunk code didnt set total_table_pages on
PlannerInfo leading to an assertion failure in BitmapHeapscan
path creation.
This commit is contained in:
Sven Klemm 2020-10-18 18:02:58 +02:00 committed by Sven Klemm
parent 6cd688c366
commit dc913ef0d4
3 changed files with 125 additions and 5 deletions

View File

@ -6,6 +6,7 @@
#include <postgres.h>
#include <catalog/pg_operator.h>
#include <miscadmin.h>
#include <nodes/bitmapset.h>
#include <nodes/makefuncs.h>
#include <nodes/nodeFuncs.h>
@ -16,7 +17,6 @@
#include <utils/builtins.h>
#include <utils/lsyscache.h>
#include <utils/typcache.h>
#include <miscadmin.h>
#include "compat.h"
#if PG12_LT
@ -946,11 +946,13 @@ decompress_chunk_path_create(PlannerInfo *root, CompressionInfo *info, int paral
path->cpath.flags = 0;
path->cpath.methods = &decompress_chunk_path_methods;
Assert(parallel_workers == 0 || compressed_path->parallel_safe);
path->cpath.path.parallel_aware = false;
path->cpath.path.parallel_safe = compressed_path->parallel_safe;
/* To prevent a non-parallel path with this node appearing
* in a parallel plan we only set parallel_safe to true
* when parallel_workers is greater than 0 which is only
* the case when creating partial paths. */
path->cpath.path.parallel_safe = parallel_workers > 0;
path->cpath.path.parallel_workers = parallel_workers;
path->cpath.path.parallel_aware = false;
path->cpath.custom_paths = list_make1(compressed_path);
path->reverse = false;
@ -970,6 +972,10 @@ create_compressed_scan_paths(PlannerInfo *root, RelOptInfo *compressed_rel, int
{
Path *compressed_path;
/* clamp total_table_pages to 10 pages since this is the
* minimum estimate for number of pages */
root->total_table_pages = Max(compressed_rel->pages, 10);
/* create non parallel scan path */
compressed_path = create_seqscan_path(root, compressed_rel, NULL, 0);
add_path(compressed_rel, compressed_path);

View File

@ -76,3 +76,64 @@ ORDER BY 1,2;
DROP TABLE decompress_phv_ping;
DROP TABLE decompress_phv_device;
-- test assertion failure in bitmapheapscan path creation
-- GH Issue #2211
CREATE TABLE tickers (
time TIMESTAMPTZ,
microseconds INT,
fk_exchange SMALLINT,
fk_trade_pair SMALLINT
);
CREATE INDEX ON tickers (fk_exchange, fk_trade_pair, time DESC, microseconds DESC);
SELECT
table_name
FROM
create_hypertable('tickers', 'time');
NOTICE: adding not-null constraint to column "time"
table_name
------------
tickers
(1 row)
ALTER TABLE tickers SET (timescaledb.compress, timescaledb.compress_segmentby = 'fk_exchange,
fk_trade_pair', timescaledb.compress_orderby = 'time DESC, microseconds DESC');
INSERT INTO tickers
SELECT
'2000-01-01',
0,
i,
j
FROM
generate_series(1, 20) i,
generate_series(1, 40) j;
SELECT
substr(compress_chunk(tableoid::REGCLASS)::TEXT, 1, 29)
FROM
tickers
GROUP BY
tableoid;
substr
-------------------------------
_timescaledb_internal._hyper_
(1 row)
-- make sure we get bitmapheapscan
SET enable_indexscan TO FALSE;
SELECT
*
FROM
tickers
WHERE
time >= '2000-01-01'
AND time < '2020-08-02T00:00Z'
AND fk_exchange = 4
AND fk_trade_pair = 29
ORDER BY
time DESC,
microseconds DESC;
time | microseconds | fk_exchange | fk_trade_pair
------------------------------+--------------+-------------+---------------
Sat Jan 01 00:00:00 2000 PST | 0 | 4 | 29
(1 row)
DROP TABLE tickers;

View File

@ -52,3 +52,56 @@ ORDER BY 1,2;
DROP TABLE decompress_phv_ping;
DROP TABLE decompress_phv_device;
-- test assertion failure in bitmapheapscan path creation
-- GH Issue #2211
CREATE TABLE tickers (
time TIMESTAMPTZ,
microseconds INT,
fk_exchange SMALLINT,
fk_trade_pair SMALLINT
);
CREATE INDEX ON tickers (fk_exchange, fk_trade_pair, time DESC, microseconds DESC);
SELECT
table_name
FROM
create_hypertable('tickers', 'time');
ALTER TABLE tickers SET (timescaledb.compress, timescaledb.compress_segmentby = 'fk_exchange,
fk_trade_pair', timescaledb.compress_orderby = 'time DESC, microseconds DESC');
INSERT INTO tickers
SELECT
'2000-01-01',
0,
i,
j
FROM
generate_series(1, 20) i,
generate_series(1, 40) j;
SELECT
substr(compress_chunk(tableoid::REGCLASS)::TEXT, 1, 29)
FROM
tickers
GROUP BY
tableoid;
-- make sure we get bitmapheapscan
SET enable_indexscan TO FALSE;
SELECT
*
FROM
tickers
WHERE
time >= '2000-01-01'
AND time < '2020-08-02T00:00Z'
AND fk_exchange = 4
AND fk_trade_pair = 29
ORDER BY
time DESC,
microseconds DESC;
DROP TABLE tickers;