diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/pg_proc.c | 23 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 9 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 16 |
3 files changed, 42 insertions, 6 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 1454d2fb67b..25d35230d02 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -35,6 +35,7 @@ #include "parser/analyze.h" #include "parser/parse_coerce.h" #include "parser/parse_type.h" +#include "rewrite/rewriteHandler.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -891,12 +892,30 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) if (!isnull) { Node *n; + List *stored_query_list; n = stringToNode(TextDatumGetCString(tmp)); if (IsA(n, List)) - querytree_list = castNode(List, n); + stored_query_list = linitial(castNode(List, n)); else - querytree_list = list_make1(list_make1(n)); + stored_query_list = list_make1(n); + + querytree_list = NIL; + foreach(lc, stored_query_list) + { + Query *parsetree = lfirst_node(Query, lc); + List *querytree_sublist; + + /* + * Typically, we'd have acquired locks already while parsing + * the body of the CREATE FUNCTION command. However, a + * validator function cannot assume that it's only called in + * that context. + */ + AcquireRewriteLocks(parsetree, true, false); + querytree_sublist = pg_rewrite_query(parsetree); + querytree_list = lappend(querytree_list, querytree_sublist); + } } else { diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 7187f17da57..3412d31117a 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -43,6 +43,7 @@ #include "parser/parse_agg.h" #include "parser/parse_coerce.h" #include "parser/parse_func.h" +#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -4470,6 +4471,12 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, if (list_length(querytree_list) != 1) goto fail; querytree = linitial(querytree_list); + + /* + * Because we'll insist below that the querytree have an empty rtable + * and no sublinks, it cannot have any relation references that need + * to be locked or rewritten. So we can omit those steps. + */ } else { @@ -5022,6 +5029,8 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) goto fail; querytree = linitial(querytree_list); + /* Acquire necessary locks, then apply rewriter. */ + AcquireRewriteLocks(querytree, true, false); querytree_list = pg_rewrite_query(querytree); if (list_length(querytree_list) != 1) goto fail; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4df8cc5abf6..c92958149e8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2973,7 +2973,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS) } /* And finally the function definition ... */ - tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull); + (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull); if (proc->prolang == SQLlanguageId && !isnull) { print_function_sqlbody(&buf, proctup); @@ -3439,7 +3439,10 @@ print_function_sqlbody(StringInfo buf, HeapTuple proctup) { Query *query = lfirst_node(Query, lc); - get_query_def(query, buf, list_make1(&dpns), NULL, PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1); + /* It seems advisable to get at least AccessShareLock on rels */ + AcquireRewriteLocks(query, false, false); + get_query_def(query, buf, list_make1(&dpns), NULL, + PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1); appendStringInfoChar(buf, ';'); appendStringInfoChar(buf, '\n'); } @@ -3448,7 +3451,12 @@ print_function_sqlbody(StringInfo buf, HeapTuple proctup) } else { - get_query_def(castNode(Query, n), buf, list_make1(&dpns), NULL, 0, WRAP_COLUMN_DEFAULT, 0); + Query *query = castNode(Query, n); + + /* It seems advisable to get at least AccessShareLock on rels */ + AcquireRewriteLocks(query, false, false); + get_query_def(query, buf, list_make1(&dpns), NULL, + 0, WRAP_COLUMN_DEFAULT, 0); } } @@ -3467,7 +3475,7 @@ pg_get_function_sqlbody(PG_FUNCTION_ARGS) if (!HeapTupleIsValid(proctup)) PG_RETURN_NULL(); - SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull); + (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull); if (isnull) { ReleaseSysCache(proctup); |