summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2022-02-11 20:23:52 +0000
committerTom Lane2022-02-11 20:23:52 +0000
commit14ee565f399b69b56eaed29c5e2f5a33ab45710f (patch)
tree290e95ffb0d5a6596cc63f00af27d75a6cf3bbd6
parent69cc15c316b8a0421cd5a8baa2a3041b22fa979c (diff)
Don't use_physical_tlist for an IOS with non-returnable columns.
createplan.c tries to save a runtime projection step by specifying a scan plan node's output as being exactly the table's columns, or index's columns in the case of an index-only scan, if there is not a reason to do otherwise. This logic did not previously pay attention to whether an index's columns are returnable. That worked, sort of accidentally, until commit 9a3ddeb51 taught setrefs.c to reject plans that try to read a non-returnable column. I have no desire to loosen setrefs.c's new check, so instead adjust use_physical_tlist() to not try to optimize this way when there are non-returnable column(s). Per report from Ryan Kelly. Like the previous patch, back-patch to all supported branches. Discussion: https://postgr.es/m/CAHUie24ddN+pDNw7fkhNrjrwAX=fXXfGZZEHhRuofV_N_ftaSg@mail.gmail.com
-rw-r--r--src/backend/optimizer/plan/createplan.c16
-rw-r--r--src/test/regress/expected/gist.out16
-rw-r--r--src/test/regress/sql/gist.sql5
3 files changed, 37 insertions, 0 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 839f20a7f6f..90661f2b147 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -857,6 +857,22 @@ use_physical_tlist(PlannerInfo *root, Path *path, int flags)
}
/*
+ * For an index-only scan, the "physical tlist" is the index's indextlist.
+ * We can only return that without a projection if all the index's columns
+ * are returnable.
+ */
+ if (path->pathtype == T_IndexOnlyScan)
+ {
+ IndexOptInfo *indexinfo = ((IndexPath *) path)->indexinfo;
+
+ for (i = 0; i < indexinfo->ncolumns; i++)
+ {
+ if (!indexinfo->canreturn[i])
+ return false;
+ }
+ }
+
+ /*
* Also, can't do it if CP_LABEL_TLIST is specified and path is requested
* to emit any sort/group columns that are not simple Vars. (If they are
* simple Vars, they should appear in the physical tlist, and
diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out
index 6a9e33eb430..717bb7f03b9 100644
--- a/src/test/regress/expected/gist.out
+++ b/src/test/regress/expected/gist.out
@@ -283,6 +283,22 @@ select p from gist_tbl where circle(p,1) @> circle(point(0,0),0.95);
(0,0)
(1 row)
+-- Also check that use_physical_tlist doesn't trigger in such cases.
+explain (verbose, costs off)
+select count(*) from gist_tbl;
+ QUERY PLAN
+---------------------------------------------------------------------
+ Aggregate
+ Output: count(*)
+ -> Index Only Scan using gist_tbl_multi_index on public.gist_tbl
+(3 rows)
+
+select count(*) from gist_tbl;
+ count
+-------
+ 10001
+(1 row)
+
-- This case isn't supported, but it should at least EXPLAIN correctly.
explain (verbose, costs off)
select p from gist_tbl order by circle(p,1) <-> point(0,0) limit 1;
diff --git a/src/test/regress/sql/gist.sql b/src/test/regress/sql/gist.sql
index ab77dc27218..b1dc41b91bc 100644
--- a/src/test/regress/sql/gist.sql
+++ b/src/test/regress/sql/gist.sql
@@ -145,6 +145,11 @@ explain (verbose, costs off)
select p from gist_tbl where circle(p,1) @> circle(point(0,0),0.95);
select p from gist_tbl where circle(p,1) @> circle(point(0,0),0.95);
+-- Also check that use_physical_tlist doesn't trigger in such cases.
+explain (verbose, costs off)
+select count(*) from gist_tbl;
+select count(*) from gist_tbl;
+
-- This case isn't supported, but it should at least EXPLAIN correctly.
explain (verbose, costs off)
select p from gist_tbl order by circle(p,1) <-> point(0,0) limit 1;