Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SkipScan path generation with expressions #3135

Merged
merged 2 commits into from Apr 20, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ accidentally triggering the load of a previous DB version.**
* #3104 Fix use after free in add_reorder_policy
* #3106 Fix use after free in chunk_api_get_chunk_stats
* #3123 Fix crash while using REINDEX TABLE CONCURRENTLY
* #3135 Fix SkipScan path generation in DISTINCT queries with expressions

## 2.2.0 (2021-04-13)

Expand Down
1 change: 0 additions & 1 deletion test/sql/CMakeLists.txt
Expand Up @@ -79,7 +79,6 @@ set(SOLO_TESTS
index-12
index-13
loader
loader
net
pg_dump_unprivileged
tablespace
Expand Down
14 changes: 9 additions & 5 deletions tsl/src/nodes/skip_scan/planner.c
Expand Up @@ -47,7 +47,7 @@ typedef struct SkipScanPath
int sk_attno;
} SkipScanPath;

static TargetEntry *get_tle_for_pathkey(List *tlist, PathKey *pathkey);
static TargetEntry *get_tle_for_pathkey(List *tlist, PathKey *pathkey, bool missing_ok);
static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec, TargetEntry *tle,
Relids relids);
static int get_idx_key(IndexOptInfo *idxinfo, AttrNumber attno);
Expand Down Expand Up @@ -118,7 +118,7 @@ skip_scan_plan_create(PlannerInfo *root, RelOptInfo *relopt, CustomPath *best_pa
skip_plan->custom_plans = custom_plans;
/* get position of skipped column in tuples produced by child scan */
PathKey *pk = linitial_node(PathKey, best_path->path.pathkeys);
TargetEntry *tle = get_tle_for_pathkey(plan->targetlist, pk);
TargetEntry *tle = get_tle_for_pathkey(plan->targetlist, pk, false);

skip_plan->custom_private = list_make5_int(tle->resno,
path->distinct_by_val,
Expand Down Expand Up @@ -381,10 +381,10 @@ skip_scan_path_create(PlannerInfo *root, IndexPath *index_path, double ndistinct
* has to be the distinct column
*/
PathKey *first_pathkey = linitial(index_path->path.pathkeys);
TargetEntry *tle = get_tle_for_pathkey(index_path->indexinfo->indextlist, first_pathkey);
TargetEntry *tle = get_tle_for_pathkey(index_path->indexinfo->indextlist, first_pathkey, true);

/* SkipScan on expressions not supported */
if (!IsA(tle->expr, Var))
if (!tle || !IsA(tle->expr, Var))
return NULL;

/* build skip qual this may fail if we cannot look up the operator */
Expand Down Expand Up @@ -483,7 +483,7 @@ build_skip_qual(SkipScanPath *skip_scan_path, IndexPath *index_path, Var *var)
}

static TargetEntry *
get_tle_for_pathkey(List *tlist, PathKey *pathkey)
get_tle_for_pathkey(List *tlist, PathKey *pathkey, bool missing_ok)
{
EquivalenceClass *ec = pathkey->pk_eclass;
TargetEntry *tle;
Expand All @@ -500,6 +500,10 @@ get_tle_for_pathkey(List *tlist, PathKey *pathkey)
return tle;
}

/* If PathKey is an expression it might not yet be in the targetlist */
if (missing_ok)
return NULL;

elog(ERROR, "skip column not found in targetlist");
pg_unreachable();
}
Expand Down
86 changes: 86 additions & 0 deletions tsl/test/expected/plan_skip_scan-11.out
Expand Up @@ -355,6 +355,39 @@ stable expression in targetlist on skip_scan
Heap Fetches: 12
(6 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=102 loops=1)
Group Key: time_bucket(10, "time"), 'q1_12'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=4 loops=1)
Group Key: length(dev_name), 'q1_13'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=1002 loops=1)
Group Key: (3 * "time"), 'q1_14'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=12 loops=1)
Group Key: ('Device '::text || dev_name)
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down Expand Up @@ -1816,6 +1849,59 @@ stable expression in targetlist on skip_scan_ht
Heap Fetches: 11
(20 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=100 loops=1)
Group Key: time_bucket(10, _hyper_1_1_chunk."time"), 'q1_12'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=3 loops=1)
Group Key: length(_hyper_1_1_chunk.dev_name), 'q1_13'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=1000 loops=1)
Group Key: (3 * _hyper_1_1_chunk."time"), 'q1_14'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=11 loops=1)
Group Key: ('Device '::text || _hyper_1_1_chunk.dev_name)
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down
86 changes: 86 additions & 0 deletions tsl/test/expected/plan_skip_scan-12.out
Expand Up @@ -355,6 +355,39 @@ stable expression in targetlist on skip_scan
Heap Fetches: 12
(6 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=102 loops=1)
Group Key: time_bucket(10, "time"), 'q1_12'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=4 loops=1)
Group Key: length(dev_name), 'q1_13'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=1002 loops=1)
Group Key: (3 * "time"), 'q1_14'::text
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=12 loops=1)
Group Key: ('Device '::text || dev_name)
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(3 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down Expand Up @@ -1803,6 +1836,59 @@ stable expression in targetlist on skip_scan_ht
Heap Fetches: 11
(20 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=100 loops=1)
Group Key: time_bucket(10, _hyper_1_1_chunk."time"), 'q1_12'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=3 loops=1)
Group Key: length(_hyper_1_1_chunk.dev_name), 'q1_13'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=1000 loops=1)
Group Key: (3 * _hyper_1_1_chunk."time"), 'q1_14'::text
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=11 loops=1)
Group Key: ('Device '::text || _hyper_1_1_chunk.dev_name)
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(8 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down
94 changes: 94 additions & 0 deletions tsl/test/expected/plan_skip_scan-13.out
Expand Up @@ -361,6 +361,43 @@ stable expression in targetlist on skip_scan
Heap Fetches: 12
(6 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=102 loops=1)
Group Key: time_bucket(10, "time"), 'q1_12'::text
Batches: 1
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(4 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=4 loops=1)
Group Key: length(dev_name), 'q1_13'::text
Batches: 1
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(4 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=1002 loops=1)
Group Key: (3 * "time"), 'q1_14'::text
Batches: 1
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(4 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------
HashAggregate (actual rows=12 loops=1)
Group Key: ('Device '::text || dev_name)
Batches: 1
-> Seq Scan on skip_scan (actual rows=10022 loops=1)
(4 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down Expand Up @@ -1803,6 +1840,63 @@ stable expression in targetlist on skip_scan_ht
Heap Fetches: 11
(20 rows)

-- distinct on expressions not supported
:PREFIX SELECT DISTINCT time_bucket(10,time), 'q1_12' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=100 loops=1)
Group Key: time_bucket(10, _hyper_1_1_chunk."time"), 'q1_12'::text
Batches: 1
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(9 rows)

:PREFIX SELECT DISTINCT length(dev_name), 'q1_13' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=3 loops=1)
Group Key: length(_hyper_1_1_chunk.dev_name), 'q1_13'::text
Batches: 1
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(9 rows)

:PREFIX SELECT DISTINCT 3*time, 'q1_14' FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=1000 loops=1)
Group Key: (3 * _hyper_1_1_chunk."time"), 'q1_14'::text
Batches: 1
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(9 rows)

:PREFIX SELECT DISTINCT 'Device ' || dev_name FROM :TABLE;
QUERY PLAN
---------------------------------------------------------------------------
HashAggregate (actual rows=11 loops=1)
Group Key: ('Device '::text || _hyper_1_1_chunk.dev_name)
Batches: 1
-> Result (actual rows=10020 loops=1)
-> Append (actual rows=10020 loops=1)
-> Seq Scan on _hyper_1_1_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_2_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_3_chunk (actual rows=2505 loops=1)
-> Seq Scan on _hyper_1_4_chunk (actual rows=2505 loops=1)
(9 rows)

-- DISTINCT ON queries
:PREFIX SELECT DISTINCT ON (dev) dev FROM :TABLE;
QUERY PLAN
Expand Down