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

Commit1cd9356

Browse files
committed
Fix caching of foreign-key-checking queries so that when a replan is needed,
we regenerate the SQL query text not merely the plan derived from it. Thisis needed to handle contingencies such as renaming of a table or columnused in an FK. Pre-8.3, such cases worked despite the lack of replanning(because the cached plan needn't actually change), so this is a regression.Per bug #4417 from Benjamin Bihler.
1 parent448950b commit1cd9356

File tree

5 files changed

+103
-7
lines changed

5 files changed

+103
-7
lines changed

‎src/backend/executor/spi.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.197 2008/07/18 20:26:06 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.198 2008/09/15 23:37:39 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1367,6 +1367,36 @@ SPI_is_cursor_plan(SPIPlanPtr plan)
13671367
return false;
13681368
}
13691369

1370+
/*
1371+
* SPI_plan_is_valid --- test whether a SPI plan is currently valid
1372+
* (that is, not marked as being in need of revalidation).
1373+
*
1374+
* See notes for CachedPlanIsValid before using this.
1375+
*/
1376+
bool
1377+
SPI_plan_is_valid(SPIPlanPtrplan)
1378+
{
1379+
Assert(plan->magic==_SPI_PLAN_MAGIC);
1380+
if (plan->saved)
1381+
{
1382+
ListCell*lc;
1383+
1384+
foreach(lc,plan->plancache_list)
1385+
{
1386+
CachedPlanSource*plansource= (CachedPlanSource*)lfirst(lc);
1387+
1388+
if (!CachedPlanIsValid(plansource))
1389+
return false;
1390+
}
1391+
return true;
1392+
}
1393+
else
1394+
{
1395+
/* An unsaved plan is assumed valid for its (short) lifetime */
1396+
return true;
1397+
}
1398+
}
1399+
13701400
/*
13711401
* SPI_result_code_string --- convert any SPI return code to a string
13721402
*

‎src/backend/utils/adt/ri_triggers.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
1717
*
18-
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.109 2008/05/19 04:14:24 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.110 2008/09/15 23:37:39 tgl Exp $
1919
*
2020
* ----------
2121
*/
@@ -3615,6 +3615,7 @@ static SPIPlanPtr
36153615
ri_FetchPreparedPlan(RI_QueryKey*key)
36163616
{
36173617
RI_QueryHashEntry*entry;
3618+
SPIPlanPtrplan;
36183619

36193620
/*
36203621
* On the first call initialize the hashtable
@@ -3630,7 +3631,30 @@ ri_FetchPreparedPlan(RI_QueryKey *key)
36303631
HASH_FIND,NULL);
36313632
if (entry==NULL)
36323633
returnNULL;
3633-
returnentry->plan;
3634+
3635+
/*
3636+
* Check whether the plan is still valid. If it isn't, we don't want
3637+
* to simply rely on plancache.c to regenerate it; rather we should
3638+
* start from scratch and rebuild the query text too. This is to cover
3639+
* cases such as table/column renames. We depend on the plancache
3640+
* machinery to detect possible invalidations, though.
3641+
*
3642+
* CAUTION: this check is only trustworthy if the caller has already
3643+
* locked both FK and PK rels.
3644+
*/
3645+
plan=entry->plan;
3646+
if (plan&&SPI_plan_is_valid(plan))
3647+
returnplan;
3648+
3649+
/*
3650+
* Otherwise we might as well flush the cached plan now, to free a
3651+
* little memory space before we make a new one.
3652+
*/
3653+
entry->plan=NULL;
3654+
if (plan)
3655+
SPI_freeplan(plan);
3656+
3657+
returnNULL;
36343658
}
36353659

36363660

@@ -3653,11 +3677,13 @@ ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan)
36533677
ri_InitHashTables();
36543678

36553679
/*
3656-
* Add the new plan.
3680+
* Add the new plan. We might be overwriting an entry previously
3681+
* found invalid by ri_FetchPreparedPlan.
36573682
*/
36583683
entry= (RI_QueryHashEntry*)hash_search(ri_query_cache,
36593684
(void*)key,
36603685
HASH_ENTER,&found);
3686+
Assert(!found||entry->plan==NULL);
36613687
entry->plan=plan;
36623688
}
36633689

‎src/backend/utils/cache/plancache.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* Portions Copyright (c) 1994, Regents of the University of California
3636
*
3737
* IDENTIFICATION
38-
* $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.21 2008/09/09 18:58:08 tgl Exp $
38+
* $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.22 2008/09/15 23:37:39 tgl Exp $
3939
*
4040
*-------------------------------------------------------------------------
4141
*/
@@ -571,6 +571,44 @@ ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
571571
MemoryContextDelete(plan->context);
572572
}
573573

574+
/*
575+
* CachedPlanIsValid: test whether the plan within a CachedPlanSource is
576+
* currently valid (that is, not marked as being in need of revalidation).
577+
*
578+
* This result is only trustworthy (ie, free from race conditions) if
579+
* the caller has acquired locks on all the relations used in the plan.
580+
*/
581+
bool
582+
CachedPlanIsValid(CachedPlanSource*plansource)
583+
{
584+
CachedPlan*plan;
585+
586+
/* Validity check that we were given a CachedPlanSource */
587+
Assert(list_member_ptr(cached_plans_list,plansource));
588+
589+
plan=plansource->plan;
590+
if (plan&& !plan->dead)
591+
{
592+
/*
593+
* Plan must have positive refcount because it is referenced by
594+
* plansource; so no need to fear it disappears under us here.
595+
*/
596+
Assert(plan->refcount>0);
597+
598+
/*
599+
* Although we don't want to acquire locks here, it still seems
600+
* useful to check for expiration of a transient plan.
601+
*/
602+
if (TransactionIdIsValid(plan->saved_xmin)&&
603+
!TransactionIdEquals(plan->saved_xmin,TransactionXmin))
604+
plan->dead= true;
605+
else
606+
return true;
607+
}
608+
609+
return false;
610+
}
611+
574612
/*
575613
* AcquireExecutorLocks: acquire locks needed for execution of a fully-planned
576614
* cached plan; or release them if acquire is false.

‎src/include/executor/spi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.66 2008/04/01 03:09:30 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.67 2008/09/15 23:37:40 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -118,6 +118,7 @@ extern intSPI_freeplan(SPIPlanPtr plan);
118118
externOidSPI_getargtypeid(SPIPlanPtrplan,intargIndex);
119119
externintSPI_getargcount(SPIPlanPtrplan);
120120
externboolSPI_is_cursor_plan(SPIPlanPtrplan);
121+
externboolSPI_plan_is_valid(SPIPlanPtrplan);
121122
externconstchar*SPI_result_code_string(intcode);
122123

123124
externHeapTupleSPI_copytuple(HeapTupletuple);

‎src/include/utils/plancache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.13 2008/09/09 18:58:09 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.14 2008/09/15 23:37:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -109,6 +109,7 @@ extern void DropCachedPlan(CachedPlanSource *plansource);
109109
externCachedPlan*RevalidateCachedPlan(CachedPlanSource*plansource,
110110
booluseResOwner);
111111
externvoidReleaseCachedPlan(CachedPlan*plan,booluseResOwner);
112+
externboolCachedPlanIsValid(CachedPlanSource*plansource);
112113
externTupleDescPlanCacheComputeResultDesc(List*stmt_list);
113114

114115
externvoidResetPlanCache(void);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp