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

Commit055f786

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 parent72bf3f0 commit055f786

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
@@ -3537,8 +3537,27 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
35373537
if (query->commandType==CMD_UTILITY)
35383538
{
35393539
/*
3540-
* Ignore utility statements, except those (such as EXPLAIN) that
3541-
* contain a parsed-but-not-planned query.
3540+
* This logic must handle any utility command for which parse
3541+
* analysis was nontrivial (cf. stmt_requires_parse_analysis).
3542+
*
3543+
* Notably, CALL requires its own processing.
3544+
*/
3545+
if (IsA(query->utilityStmt,CallStmt))
3546+
{
3547+
CallStmt*callstmt= (CallStmt*)query->utilityStmt;
3548+
3549+
/* We need not examine funccall, just the transformed exprs */
3550+
(void)extract_query_dependencies_walker((Node*)callstmt->funcexpr,
3551+
context);
3552+
(void)extract_query_dependencies_walker((Node*)callstmt->outargs,
3553+
context);
3554+
return false;
3555+
}
3556+
3557+
/*
3558+
* Ignore other utility statements, except those (such as EXPLAIN)
3559+
* that contain a parsed-but-not-planned query. For those, we
3560+
* just need to transfer our attention to the contained query.
35423561
*/
35433562
query=UtilityContainsQuery(query->utilityStmt);
35443563
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
@@ -483,3 +483,50 @@ BEGIN
483483
END;
484484
$$;
485485
NOTICE: <NULL>
486+
-- check that we detect change of dependencies in CALL
487+
-- atomic and non-atomic call sites used to do this differently, so check both
488+
CREATE PROCEDURE inner_p (f1 int)
489+
AS $$
490+
BEGIN
491+
RAISE NOTICE 'inner_p(%)', f1;
492+
END
493+
$$ LANGUAGE plpgsql;
494+
CREATE FUNCTION f(int) RETURNS int AS $$ SELECT $1 + 1 $$ LANGUAGE sql;
495+
CREATE PROCEDURE outer_p (f1 int)
496+
AS $$
497+
BEGIN
498+
RAISE NOTICE 'outer_p(%)', f1;
499+
CALL inner_p(f(f1));
500+
END
501+
$$ LANGUAGE plpgsql;
502+
CREATE FUNCTION outer_f (f1 int) RETURNS void
503+
AS $$
504+
BEGIN
505+
RAISE NOTICE 'outer_f(%)', f1;
506+
CALL inner_p(f(f1));
507+
END
508+
$$ LANGUAGE plpgsql;
509+
CALL outer_p(42);
510+
NOTICE: outer_p(42)
511+
NOTICE: inner_p(43)
512+
SELECT outer_f(42);
513+
NOTICE: outer_f(42)
514+
NOTICE: inner_p(43)
515+
outer_f
516+
---------
517+
518+
(1 row)
519+
520+
DROP FUNCTION f(int);
521+
CREATE FUNCTION f(int) RETURNS int AS $$ SELECT $1 + 2 $$ LANGUAGE sql;
522+
CALL outer_p(42);
523+
NOTICE: outer_p(42)
524+
NOTICE: inner_p(44)
525+
SELECT outer_f(42);
526+
NOTICE: outer_f(42)
527+
NOTICE: inner_p(44)
528+
outer_f
529+
---------
530+
531+
(1 row)
532+

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,41 @@ BEGIN
454454
RAISE NOTICE'%', v_Text;
455455
END;
456456
$$;
457+
458+
459+
-- check that we detect change of dependencies in CALL
460+
-- atomic and non-atomic call sites used to do this differently, so check both
461+
462+
CREATE PROCEDURE inner_p (f1int)
463+
AS $$
464+
BEGIN
465+
RAISE NOTICE'inner_p(%)', f1;
466+
END
467+
$$ LANGUAGE plpgsql;
468+
469+
CREATEFUNCTIONf(int) RETURNSintAS $$SELECT $1+1 $$ LANGUAGE sql;
470+
471+
CREATE PROCEDURE outer_p (f1int)
472+
AS $$
473+
BEGIN
474+
RAISE NOTICE'outer_p(%)', f1;
475+
CALL inner_p(f(f1));
476+
END
477+
$$ LANGUAGE plpgsql;
478+
479+
CREATEFUNCTIONouter_f (f1int) RETURNS void
480+
AS $$
481+
BEGIN
482+
RAISE NOTICE'outer_f(%)', f1;
483+
CALL inner_p(f(f1));
484+
END
485+
$$ LANGUAGE plpgsql;
486+
487+
CALL outer_p(42);
488+
SELECT outer_f(42);
489+
490+
DROPFUNCTION f(int);
491+
CREATEFUNCTIONf(int) RETURNSintAS $$SELECT $1+2 $$ LANGUAGE sql;
492+
493+
CALL outer_p(42);
494+
SELECT outer_f(42);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp