OSDN Git Service

Ignore non-existent prepared statement in get_query_string. PG12
authorKyotaro Horiguchi <horikyota.ntt@gmail.com>
Wed, 9 Mar 2022 02:38:31 +0000 (11:38 +0900)
committerKyotaro Horiguchi <horikyota.ntt@gmail.com>
Wed, 9 Mar 2022 03:18:04 +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 0232d84..b57cf52 100644 (file)
@@ -8388,6 +8388,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 ef6d53f..08e3db3 100644 (file)
@@ -1890,9 +1890,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 7309e1e..8b30c9c 100644 (file)
@@ -1012,6 +1012,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