OSDN Git Service

Fix a crash bug related to non-baserel RTEs and function indexes
authorKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Wed, 26 Sep 2018 02:38:08 +0000 (11:38 +0900)
committerKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Wed, 26 Sep 2018 02:38:08 +0000 (11:38 +0900)
dbms_stats_get_index_stats forgot that simple_rel_array may have empty
slots corresponding to non-baserel RTEs. Server crashes when saved
statitistics for function indexes are accessed while planning such a
query. This is fixed by simply skipping such entries.

expected/ut-common.out
pg_dbms_stats.c
sql/ut-common.sql

index 8592af3..2abe6d9 100644 (file)
@@ -2751,6 +2751,42 @@ ERROR:  permission denied for schema dbms_stats
 LINE 1: SELECT count(*) FROM dbms_stats.stats WHERE false;
                              ^
 RESET SESSION AUTHORIZATION;
+/*
+ * No.19-2 regression for skipping empty simple_rel_array entry
+ */
+CREATE TABLE t1 (a int, b int);
+CREATE TABLE t2 (a int);
+CREATE INDEX t1_a10_idx on t1 ((a % 10));
+INSERT INTO t1 (SELECT a, a FROM generate_series(0, 9999) a);
+INSERT INTO t2 VALUES (1), (3), (7), (8);
+ANALYZE t1;
+SELECT dbms_stats.lock_table_stats('t1');
+ lock_table_stats 
+------------------
+ t1
+(1 row)
+
+EXPLAIN (COSTS off)
+ SELECT * FROM t1 JOIN t2 on (t1.a % 10 = t2.a); -- Don't crash!
+               QUERY PLAN                
+-----------------------------------------
+ Merge Join
+   Merge Cond: ((t1.a % 10) = t2.a)
+   ->  Index Scan using t1_a10_idx on t1
+   ->  Sort
+         Sort Key: t2.a
+         ->  Seq Scan on t2
+(6 rows)
+
+DROP TABLE t1, t2;
+SELECT dbms_stats.clean_up_stats() ORDER BY 1;
+ clean_up_stats 
+----------------
+ public.t1,
+ public.t1, 1
+ public.t1, 2
+(3 rows)
+
 -- No.20 has been moved out to ut-xx.sql
 /*
  * No.21 anyarray stuff
index 51e8414..417fe77 100644 (file)
@@ -1038,8 +1038,13 @@ dbms_stats_get_index_stats(PlannerInfo *root,
                for (i = 1 ; i < root->simple_rel_array_size ; i++)
                {
                        ListCell *lc;
+                       RelOptInfo *rel = root->simple_rel_array[i];
 
-                       foreach (lc, root->simple_rel_array[i]->indexlist)
+                       /* there may be empty slots corresponding to non-baserel RTEs  */
+                       if (rel == NULL)
+                               continue;
+
+                       foreach (lc, rel->indexlist)
                        {
                                IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
                                RangeTblEntry *rte;
index 07f98f3..e5b8053 100644 (file)
@@ -1167,6 +1167,21 @@ SELECT count(*) FROM dbms_stats.column_stats_locked WHERE false;
 SELECT count(*) FROM dbms_stats.stats WHERE false;
 RESET SESSION AUTHORIZATION;
 
+/*
+ * No.19-2 regression for skipping empty simple_rel_array entry
+ */
+CREATE TABLE t1 (a int, b int);
+CREATE TABLE t2 (a int);
+CREATE INDEX t1_a10_idx on t1 ((a % 10));
+INSERT INTO t1 (SELECT a, a FROM generate_series(0, 9999) a);
+INSERT INTO t2 VALUES (1), (3), (7), (8);
+ANALYZE t1;
+SELECT dbms_stats.lock_table_stats('t1');
+EXPLAIN (COSTS off)
+ SELECT * FROM t1 JOIN t2 on (t1.a % 10 = t2.a); -- Don't crash!
+DROP TABLE t1, t2;
+SELECT dbms_stats.clean_up_stats() ORDER BY 1;
+
 -- No.20 has been moved out to ut-xx.sql
 
 /*