Commit 82d8ab6f authored by Tom Lane's avatar Tom Lane

Fix the plan-invalidation mechanism to treat regclass constants that refer to

a relation as a reason to invalidate a plan when the relation changes.  This
handles scenarios such as dropping/recreating a sequence that is referenced by
nextval('seq') in a cached plan.  Rather than teach plancache.c all about
digging through plan trees to find regclass Consts, we charge the planner's
setrefs.c with making a list of the relation OIDs on which each plan depends.
That way the list can be built cheaply during a plan tree traversal that has
to happen anyway.  Per bug #3662 and subsequent discussion.
parent 68b08b25
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.382 2007/09/03 18:46:30 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.383 2007/10/11 18:05:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -83,6 +83,7 @@ _copyPlannedStmt(PlannedStmt *from) ...@@ -83,6 +83,7 @@ _copyPlannedStmt(PlannedStmt *from)
COPY_BITMAPSET_FIELD(rewindPlanIDs); COPY_BITMAPSET_FIELD(rewindPlanIDs);
COPY_NODE_FIELD(returningLists); COPY_NODE_FIELD(returningLists);
COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(rowMarks);
COPY_NODE_FIELD(relationOids);
COPY_SCALAR_FIELD(nParamExec); COPY_SCALAR_FIELD(nParamExec);
return newnode; return newnode;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.314 2007/08/31 01:44:05 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.315 2007/10/11 18:05:27 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -250,6 +250,7 @@ _outPlannedStmt(StringInfo str, PlannedStmt *node) ...@@ -250,6 +250,7 @@ _outPlannedStmt(StringInfo str, PlannedStmt *node)
WRITE_BITMAPSET_FIELD(rewindPlanIDs); WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(returningLists); WRITE_NODE_FIELD(returningLists);
WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(relationOids);
WRITE_INT_FIELD(nParamExec); WRITE_INT_FIELD(nParamExec);
} }
...@@ -1300,6 +1301,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node) ...@@ -1300,6 +1301,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
WRITE_NODE_FIELD(subrtables); WRITE_NODE_FIELD(subrtables);
WRITE_BITMAPSET_FIELD(rewindPlanIDs); WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(finalrtable); WRITE_NODE_FIELD(finalrtable);
WRITE_NODE_FIELD(relationOids);
} }
static void static void
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.222 2007/09/20 17:56:31 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.223 2007/10/11 18:05:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -134,6 +134,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) ...@@ -134,6 +134,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->subrtables = NIL; glob->subrtables = NIL;
glob->rewindPlanIDs = NULL; glob->rewindPlanIDs = NULL;
glob->finalrtable = NIL; glob->finalrtable = NIL;
glob->relationOids = NIL;
glob->transientPlan = false; glob->transientPlan = false;
/* Determine what fraction of the plan is likely to be scanned */ /* Determine what fraction of the plan is likely to be scanned */
...@@ -194,6 +195,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) ...@@ -194,6 +195,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->rewindPlanIDs = glob->rewindPlanIDs; result->rewindPlanIDs = glob->rewindPlanIDs;
result->returningLists = root->returningLists; result->returningLists = root->returningLists;
result->rowMarks = parse->rowMarks; result->rowMarks = parse->rowMarks;
result->relationOids = glob->relationOids;
result->nParamExec = list_length(glob->paramlist); result->nParamExec = list_length(glob->paramlist);
return result; return result;
...@@ -1184,7 +1186,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) ...@@ -1184,7 +1186,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
List *rlist; List *rlist;
Assert(parse->resultRelation); Assert(parse->resultRelation);
rlist = set_returning_clause_references(parse->returningList, rlist = set_returning_clause_references(root->glob,
parse->returningList,
result_plan, result_plan,
parse->resultRelation); parse->resultRelation);
root->returningLists = list_make1(rlist); root->returningLists = list_make1(rlist);
......
This diff is collapsed.
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.11 2007/09/20 17:56:31 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.12 2007/10/11 18:05:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -921,26 +921,17 @@ PlanCacheCallback(Datum arg, Oid relid) ...@@ -921,26 +921,17 @@ PlanCacheCallback(Datum arg, Oid relid)
foreach(lc2, plan->stmt_list) foreach(lc2, plan->stmt_list)
{ {
PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc2); PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc2);
ListCell *lc3;
Assert(!IsA(plannedstmt, Query)); Assert(!IsA(plannedstmt, Query));
if (!IsA(plannedstmt, PlannedStmt)) if (!IsA(plannedstmt, PlannedStmt))
continue; /* Ignore utility statements */ continue; /* Ignore utility statements */
foreach(lc3, plannedstmt->rtable) if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
list_member_oid(plannedstmt->relationOids, relid))
{ {
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc3); /* Invalidate the plan! */
plan->dead = true;
if (rte->rtekind != RTE_RELATION)
continue;
if (relid == rte->relid || relid == InvalidOid)
{
/* Invalidate the plan! */
plan->dead = true;
break; /* out of rangetable scan */
}
}
if (plan->dead)
break; /* out of stmt_list scan */ break; /* out of stmt_list scan */
}
} }
} }
else else
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.95 2007/09/20 17:56:32 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.96 2007/10/11 18:05:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -70,6 +70,8 @@ typedef struct PlannedStmt ...@@ -70,6 +70,8 @@ typedef struct PlannedStmt
List *rowMarks; /* a list of RowMarkClause's */ List *rowMarks; /* a list of RowMarkClause's */
List *relationOids; /* OIDs of relations the plan depends on */
int nParamExec; /* number of PARAM_EXEC Params used */ int nParamExec; /* number of PARAM_EXEC Params used */
} PlannedStmt; } PlannedStmt;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.146 2007/09/20 17:56:32 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.147 2007/10/11 18:05:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -72,6 +72,8 @@ typedef struct PlannerGlobal ...@@ -72,6 +72,8 @@ typedef struct PlannerGlobal
List *finalrtable; /* "flat" rangetable for executor */ List *finalrtable; /* "flat" rangetable for executor */
List *relationOids; /* OIDs of relations the plan depends on */
bool transientPlan; /* redo plan when TransactionXmin changes? */ bool transientPlan; /* redo plan when TransactionXmin changes? */
} PlannerGlobal; } PlannerGlobal;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.102 2007/10/04 20:44:47 tgl Exp $ * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.103 2007/10/11 18:05:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -96,7 +96,8 @@ extern RestrictInfo *build_implied_join_equality(Oid opno, ...@@ -96,7 +96,8 @@ extern RestrictInfo *build_implied_join_equality(Oid opno,
extern Plan *set_plan_references(PlannerGlobal *glob, extern Plan *set_plan_references(PlannerGlobal *glob,
Plan *plan, Plan *plan,
List *rtable); List *rtable);
extern List *set_returning_clause_references(List *rlist, extern List *set_returning_clause_references(PlannerGlobal *glob,
List *rlist,
Plan *topplan, Plan *topplan,
Index resultRelation); Index resultRelation);
extern void fix_opfuncids(Node *node); extern void fix_opfuncids(Node *node);
......
...@@ -202,3 +202,20 @@ drop schema s1 cascade; ...@@ -202,3 +202,20 @@ drop schema s1 cascade;
NOTICE: drop cascades to table s1.abc NOTICE: drop cascades to table s1.abc
drop schema s2 cascade; drop schema s2 cascade;
NOTICE: drop cascades to table abc NOTICE: drop cascades to table abc
-- Check that invalidation deals with regclass constants
create temp sequence seq;
prepare p2 as select nextval('seq');
execute p2;
nextval
---------
1
(1 row)
drop sequence seq;
create temp sequence seq;
execute p2;
nextval
---------
1
(1 row)
...@@ -123,3 +123,17 @@ execute p1; ...@@ -123,3 +123,17 @@ execute p1;
drop schema s1 cascade; drop schema s1 cascade;
drop schema s2 cascade; drop schema s2 cascade;
-- Check that invalidation deals with regclass constants
create temp sequence seq;
prepare p2 as select nextval('seq');
execute p2;
drop sequence seq;
create temp sequence seq;
execute p2;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment