Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5cff431

Browse files
committed
Collect dependency information for parsed CallStmts.
Parse analysis of a CallStmt will inject mutable information,for instance the OID of the called procedure, so that subsequentDDL may create a need to re-parse the CALL. We failed to detectthis for CALLs in plpgsql routines, because no dependency informationwas collected when putting a CallStmt into the plan cache. Thatcould lead to misbehavior or strange errors such as "cache lookupfailed".Before commitee895a6, the issue would only manifest for CALLsappearing in atomic contexts, because we re-planned non-atomicCALLs every time through anyway.It is now apparent that extract_query_dependencies() probablyneeds a special case for every utility statement type for whichstmt_requires_parse_analysis() returns true. I wanted to addsomething like Assert(!stmt_requires_parse_analysis(...)) whenfalling out of extract_query_dependencies_walker without doinganything, but there are API issues as well as a more fundamentalpoint: stmt_requires_parse_analysis is supposed to be applied toraw parser output, so it'd be cheating to assume it will give thecorrect answer for post-parse-analysis trees. I contented myselfwith adding a comment.Per bug #18131 from Christian Stork. Back-patch to all supportedbranches.Discussion:https://postgr.es/m/18131-576854e79c5cd264@postgresql.org
1 parenta2799f5 commit5cff431

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

‎src/backend/optimizer/plan/setrefs.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,8 +3152,27 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
31523152
if (query->commandType==CMD_UTILITY)
31533153
{
31543154
/*
3155-
* Ignore utility statements, except those (such as EXPLAIN) that
3156-
* contain a parsed-but-not-planned query.
3155+
* This logic must handle any utility command for which parse
3156+
* analysis was nontrivial (cf. stmt_requires_parse_analysis).
3157+
*
3158+
* Notably, CALL requires its own processing.
3159+
*/
3160+
if (IsA(query->utilityStmt,CallStmt))
3161+
{
3162+
CallStmt*callstmt= (CallStmt*)query->utilityStmt;
3163+
3164+
/* We need not examine funccall, just the transformed exprs */
3165+
(void)extract_query_dependencies_walker((Node*)callstmt->funcexpr,
3166+
context);
3167+
(void)extract_query_dependencies_walker((Node*)callstmt->outargs,
3168+
context);
3169+
return false;
3170+
}
3171+
3172+
/*
3173+
* Ignore other utility statements, except those (such as EXPLAIN)
3174+
* that contain a parsed-but-not-planned query. For those, we
3175+
* just need to transfer our attention to the contained query.
31573176
*/
31583177
query=UtilityContainsQuery(query->utilityStmt);
31593178
if (query==NULL)

‎src/pl/plpgsql/src/expected/plpgsql_call.out

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,50 @@ BEGIN
471471
END;
472472
$$;
473473
NOTICE: <NULL>
474+
-- check that we detect change of dependencies in CALL
475+
-- atomic and non-atomic call sites used to do this differently, so check both
476+
CREATE PROCEDURE inner_p (f1 int)
477+
AS $$
478+
BEGIN
479+
RAISE NOTICE 'inner_p(%)', f1;
480+
END
481+
$$ LANGUAGE plpgsql;
482+
CREATE FUNCTION f(int) RETURNS int AS $$ SELECT $1 + 1 $$ LANGUAGE sql;
483+
CREATE PROCEDURE outer_p (f1 int)
484+
AS $$
485+
BEGIN
486+
RAISE NOTICE 'outer_p(%)', f1;
487+
CALL inner_p(f(f1));
488+
END
489+
$$ LANGUAGE plpgsql;
490+
CREATE FUNCTION outer_f (f1 int) RETURNS void
491+
AS $$
492+
BEGIN
493+
RAISE NOTICE 'outer_f(%)', f1;
494+
CALL inner_p(f(f1));
495+
END
496+
$$ LANGUAGE plpgsql;
497+
CALL outer_p(42);
498+
NOTICE: outer_p(42)
499+
NOTICE: inner_p(43)
500+
SELECT outer_f(42);
501+
NOTICE: outer_f(42)
502+
NOTICE: inner_p(43)
503+
outer_f
504+
---------
505+
506+
(1 row)
507+
508+
DROP FUNCTION f(int);
509+
CREATE FUNCTION f(int) RETURNS int AS $$ SELECT $1 + 2 $$ LANGUAGE sql;
510+
CALL outer_p(42);
511+
NOTICE: outer_p(42)
512+
NOTICE: inner_p(44)
513+
SELECT outer_f(42);
514+
NOTICE: outer_f(42)
515+
NOTICE: inner_p(44)
516+
outer_f
517+
---------
518+
519+
(1 row)
520+

‎src/pl/plpgsql/src/sql/plpgsql_call.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,3 +442,41 @@ BEGIN
442442
RAISE NOTICE'%', v_Text;
443443
END;
444444
$$;
445+
446+
447+
-- check that we detect change of dependencies in CALL
448+
-- atomic and non-atomic call sites used to do this differently, so check both
449+
450+
CREATE PROCEDURE inner_p (f1int)
451+
AS $$
452+
BEGIN
453+
RAISE NOTICE'inner_p(%)', f1;
454+
END
455+
$$ LANGUAGE plpgsql;
456+
457+
CREATEFUNCTIONf(int) RETURNSintAS $$SELECT $1+1 $$ LANGUAGE sql;
458+
459+
CREATE PROCEDURE outer_p (f1int)
460+
AS $$
461+
BEGIN
462+
RAISE NOTICE'outer_p(%)', f1;
463+
CALL inner_p(f(f1));
464+
END
465+
$$ LANGUAGE plpgsql;
466+
467+
CREATEFUNCTIONouter_f (f1int) RETURNS void
468+
AS $$
469+
BEGIN
470+
RAISE NOTICE'outer_f(%)', f1;
471+
CALL inner_p(f(f1));
472+
END
473+
$$ LANGUAGE plpgsql;
474+
475+
CALL outer_p(42);
476+
SELECT outer_f(42);
477+
478+
DROPFUNCTION f(int);
479+
CREATEFUNCTIONf(int) RETURNSintAS $$SELECT $1+2 $$ LANGUAGE sql;
480+
481+
CALL outer_p(42);
482+
SELECT outer_f(42);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp