OSDN Git Service

Ignore non-existent prepared statement in get_query_string. PG11
authorKyotaro Horiguchi <horikyota.ntt@gmail.com>
Wed, 9 Mar 2022 03:04:22 +0000 (12:04 +0900)
committerKyotaro Horiguchi <horikyota.ntt@gmail.com>
Wed, 9 Mar 2022 03:18:23 +0000 (12:18 +0900)
CREATE FUNCTION of SQL function uses post_parse_analyze_hook during
validation.  If the function contained EXECUTE <prepared statement>,
not only that statement may be nonexistent, but also there's no need
of the query string at that point.

Since execution of nonexistent prepared statement ends with failure
sooner or later, we can safely ignore that.

Backpatch to pg_hint_plan10 that are before the core's EOL.

expected/pg_hint_plan.out
pg_hint_plan.c
sql/pg_hint_plan.sql

index c83e1bb..55584c7 100644 (file)
@@ -8426,6 +8426,12 @@ SELECT relname, seq_scan, idx_scan FROM pg_stat_user_tables WHERE schemaname = '
  p1_c2   |        0 |        2
 (2 rows)
 
+-- Make sure the reference to validly non-existent prepared statement
+-- doesn't harm
+CREATE FUNCTION ppf() RETURNS void AS $$
+PREPARE pp1 AS SELECT 1;
+EXECUTE pp1;
+$$ LANGUAGE sql;
 -- Subqueries on inheritance tables under UNION
 EXPLAIN (COSTS off) SELECT val FROM p1 WHERE val < 1000
 UNION ALL
index 9378c75..e3c03ff 100644 (file)
@@ -1885,9 +1885,14 @@ get_query_string(ParseState *pstate, Query *query, Query **jumblequery)
                        ExecuteStmt *stmt = (ExecuteStmt *)target_query;
                        PreparedStatement  *entry;
 
-                       entry = FetchPreparedStatement(stmt->name, true);
+                       /*
+                        * Silently ignore nonexistent prepared statements. This may happen
+                        * for EXECUTE within a function definition.  Otherwise the
+                        * execution will fail anyway.
+                        */
+                       entry = FetchPreparedStatement(stmt->name, false);
 
-                       if (entry->plansource->is_valid)
+                       if (entry && entry->plansource->is_valid)
                        {
                                p = entry->plansource->query_string;
                                target_query = (Query *) linitial (entry->plansource->query_list);
index 15a8d17..d14fe5d 100644 (file)
@@ -1015,6 +1015,13 @@ SELECT pg_sleep(1);
 -- the index scan happened while planning.
 SELECT relname, seq_scan, idx_scan FROM pg_stat_user_tables WHERE schemaname = 'public' AND (relname = 'p1_c1' OR relname = 'p1_c2');
 
+-- Make sure the reference to validly non-existent prepared statement
+-- doesn't harm
+CREATE FUNCTION ppf() RETURNS void AS $$
+PREPARE pp1 AS SELECT 1;
+EXECUTE pp1;
+$$ LANGUAGE sql;
+
 -- Subqueries on inheritance tables under UNION
 EXPLAIN (COSTS off) SELECT val FROM p1 WHERE val < 1000
 UNION ALL