postgres_fdw: Fix assertion in estimate_path_cost_size().
authorEtsuro Fujita <[email protected]>
Fri, 5 Feb 2021 06:30:00 +0000 (15:30 +0900)
committerEtsuro Fujita <[email protected]>
Fri, 5 Feb 2021 06:30:00 +0000 (15:30 +0900)
Commit 08d2d58a2 added an assertion assuming that the retrieved_rows
estimate for a foreign relation, which is re-used to cost pre-sorted
foreign paths with local stats, is set to at least one row in
estimate_path_cost_size(), which isn't correct because if the relation
is a foreign table with tuples=0, the estimate would be set to 0 there
when not using remote estimates.

Per bug #16807 from Alexander Lakhin.  Back-patch to v13 where the
aforementioned commit went in.

Author: Etsuro Fujita
Reviewed-by: Kyotaro Horiguchi
Discussion: https://postgr.es/m/16807-9fe4e08fbaa5c7ce%40postgresql.org

contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/postgres_fdw.c
contrib/postgres_fdw/sql/postgres_fdw.sql

index b09dce63f5ffa83ca8f2102f59662c1cdd4ce6f6..60c7e115d612c1fd2c1134290d572161a2f99727 100644 (file)
@@ -613,6 +613,24 @@ SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2
 
 RESET enable_hashjoin;
 RESET enable_nestloop;
+-- Test executing assertion in estimate_path_cost_size() that makes sure that
+-- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is
+-- a sensible value even when the rel has tuples=0
+CREATE TABLE loct_empty (c1 int NOT NULL, c2 text);
+CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text)
+  SERVER loopback OPTIONS (table_name 'loct_empty');
+INSERT INTO loct_empty
+  SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id;
+DELETE FROM loct_empty;
+ANALYZE ft_empty;
+EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
+                                  QUERY PLAN                                   
+-------------------------------------------------------------------------------
+ Foreign Scan on public.ft_empty
+   Output: c1, c2
+   Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
+(3 rows)
+
 -- ===================================================================
 -- WHERE with remotely-executable conditions
 -- ===================================================================
index 2ce42ce3f113dd493f6fc7803c6878fe71bf0d0d..0e977066a8f94385b2b0707c2c7fda8e58422404 100644 (file)
@@ -2923,7 +2923,7 @@ estimate_path_cost_size(PlannerInfo *root,
         */
        if (fpinfo->rel_startup_cost >= 0 && fpinfo->rel_total_cost >= 0)
        {
-           Assert(fpinfo->retrieved_rows >= 1);
+           Assert(fpinfo->retrieved_rows >= 0);
 
            rows = fpinfo->rows;
            retrieved_rows = fpinfo->retrieved_rows;
index 319c15d635c0652d4c1fd4409d64f0119d7fc734..151f4f18341eb97290c3380ad07bed5f9b843da1 100644 (file)
@@ -309,6 +309,18 @@ SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2
 RESET enable_hashjoin;
 RESET enable_nestloop;
 
+-- Test executing assertion in estimate_path_cost_size() that makes sure that
+-- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is
+-- a sensible value even when the rel has tuples=0
+CREATE TABLE loct_empty (c1 int NOT NULL, c2 text);
+CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text)
+  SERVER loopback OPTIONS (table_name 'loct_empty');
+INSERT INTO loct_empty
+  SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id;
+DELETE FROM loct_empty;
+ANALYZE ft_empty;
+EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
+
 -- ===================================================================
 -- WHERE with remotely-executable conditions
 -- ===================================================================