v1-0001-Don-t-assume-that-cheapest_startup_path-exists.patch
application/octet-stream
Filename: v1-0001-Don-t-assume-that-cheapest_startup_path-exists.patch
Type: application/octet-stream
Part: 0
Message:
Crash in add_paths_to_append_rel
Patch
Format: format-patch
Series: patch v1-0001
Subject: Don't assume that cheapest_startup_path exists
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/allpaths.c | 10 | 2 |
| src/test/regress/expected/union.out | 16 | 0 |
| src/test/regress/sql/union.sql | 8 | 1 |
From 5c555fb67037d34f3a90be6052cb2fa26f34769a Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
Date: Mon, 9 Oct 2023 17:10:59 +0800
Subject: [PATCH v1] Don't assume that cheapest_startup_path exists
Normally only unparameterized paths are considered candidates for
cheapest_startup_path, because startup cost does not have too much value
for parameterized paths since they are on the inside of a nestloop. So
if there are no unparameterized paths, the cheapest_startup_path will be
NULL. In add_paths_to_append_rel() we should not assume that
cheapest_startup_path always exists.
---
src/backend/optimizer/path/allpaths.c | 12 ++++++++++--
src/test/regress/expected/union.out | 16 ++++++++++++++++
src/test/regress/sql/union.sql | 9 ++++++++-
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 7af001feaa..5c4e3695e5 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1352,12 +1352,20 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
* When the planner is considering cheap startup plans, we'll also
* collect all the cheapest_startup_paths and build an AppendPath
* containing those as subpaths.
+ *
+ * Only unparameterized paths are considered candidates for
+ * cheapest_startup_path, so that will be NULL if there are no
+ * unparameterized paths. We have to explicitly check that we have a
+ * valid cheapest_startup_path.
*/
- if (rel->consider_startup && childrel->pathlist != NIL &&
- childrel->cheapest_startup_path->param_info == NULL)
+ if (rel->consider_startup && childrel->cheapest_startup_path != NULL)
+ {
+ /* cheapest_startup_path must be unparameterized path. */
+ Assert(childrel->cheapest_startup_path->param_info == NULL);
accumulate_append_subpath(childrel->cheapest_startup_path,
&startup_subpaths,
NULL);
+ }
else
startup_subpaths_valid = false;
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index f046e522de..a4619cb014 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -1453,3 +1453,19 @@ inner join tenk2 t2 on t1.tenthous = t2.tenthous
-> Result
(8 rows)
+-- Ensure there is no problem if cheapest_startup_path is NULL
+explain (costs off)
+select * from tenk1 t1
+left join lateral
+ (select t1.tenthous from tenk2 t2 union all (values(1)))
+on true limit 1;
+ QUERY PLAN
+-------------------------------------------------------------------
+ Limit
+ -> Nested Loop Left Join
+ -> Seq Scan on tenk1 t1
+ -> Append
+ -> Index Only Scan using tenk2_hundred on tenk2 t2
+ -> Result
+(6 rows)
+
diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql
index d65ca9f86d..213309e226 100644
--- a/src/test/regress/sql/union.sql
+++ b/src/test/regress/sql/union.sql
@@ -550,4 +550,11 @@ explain (costs off)
select t1.unique1 from tenk1 t1
inner join tenk2 t2 on t1.tenthous = t2.tenthous
union all
-(values(1)) limit 1;
\ No newline at end of file
+(values(1)) limit 1;
+
+-- Ensure there is no problem if cheapest_startup_path is NULL
+explain (costs off)
+select * from tenk1 t1
+left join lateral
+ (select t1.tenthous from tenk2 t2 union all (values(1)))
+on true limit 1;
--
2.31.0