mirror of
https://git.postgresql.org/git/postgresql.git
synced 2026-02-18 12:26:59 +08:00
The 'cached-plan-inval' test suite, introduced in 525392d57 under src/test/modules/delay_execution, aimed to verify that cached plan invalidation triggers replanning after deferred locks are taken. However, its ExecutorStart_hook-based approach relies on lock timing assumptions that, in retrospect, are fragile. This instability was exposed by failures on BF animal trilobite, which builds with CLOBBER_CACHE_ALWAYS. One option was to dynamically disable the cache behavior that causes the test suite to fail by setting "debug_discard_caches = 0", but it seems better to remove the suite. The risk of future failures due to other cache flush hazards outweighs the benefit of catching real breakage in the backend behavior it tests. Reported-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/2990641.1740117879@sss.pgh.pa.us
96 lines
2.7 KiB
C
96 lines
2.7 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* delay_execution.c
|
|
* Test module to allow delay between parsing and execution of a query.
|
|
*
|
|
* The delay is implemented by taking and immediately releasing a specified
|
|
* advisory lock. If another process has previously taken that lock, the
|
|
* current process will be blocked until the lock is released; otherwise,
|
|
* there's no effect. This allows an isolationtester script to reliably
|
|
* test behaviors where some specified action happens in another backend
|
|
* between parsing and execution of any desired query.
|
|
*
|
|
* Copyright (c) 2020-2025, PostgreSQL Global Development Group
|
|
*
|
|
* IDENTIFICATION
|
|
* src/test/modules/delay_execution/delay_execution.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include <limits.h>
|
|
|
|
#include "optimizer/planner.h"
|
|
#include "utils/fmgrprotos.h"
|
|
#include "utils/guc.h"
|
|
#include "utils/inval.h"
|
|
|
|
|
|
PG_MODULE_MAGIC;
|
|
|
|
/* GUC: advisory lock ID to use. Zero disables the feature. */
|
|
static int post_planning_lock_id = 0;
|
|
|
|
/* Save previous planner hook user to be a good citizen */
|
|
static planner_hook_type prev_planner_hook = NULL;
|
|
|
|
|
|
/* planner_hook function to provide the desired delay */
|
|
static PlannedStmt *
|
|
delay_execution_planner(Query *parse, const char *query_string,
|
|
int cursorOptions, ParamListInfo boundParams)
|
|
{
|
|
PlannedStmt *result;
|
|
|
|
/* Invoke the planner, possibly via a previous hook user */
|
|
if (prev_planner_hook)
|
|
result = prev_planner_hook(parse, query_string, cursorOptions,
|
|
boundParams);
|
|
else
|
|
result = standard_planner(parse, query_string, cursorOptions,
|
|
boundParams);
|
|
|
|
/* If enabled, delay by taking and releasing the specified lock */
|
|
if (post_planning_lock_id != 0)
|
|
{
|
|
DirectFunctionCall1(pg_advisory_lock_int8,
|
|
Int64GetDatum((int64) post_planning_lock_id));
|
|
DirectFunctionCall1(pg_advisory_unlock_int8,
|
|
Int64GetDatum((int64) post_planning_lock_id));
|
|
|
|
/*
|
|
* Ensure that we notice any pending invalidations, since the advisory
|
|
* lock functions don't do this.
|
|
*/
|
|
AcceptInvalidationMessages();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Module load function */
|
|
void
|
|
_PG_init(void)
|
|
{
|
|
/* Set up the GUC to control which lock is used */
|
|
DefineCustomIntVariable("delay_execution.post_planning_lock_id",
|
|
"Sets the advisory lock ID to be locked/unlocked after planning.",
|
|
"Zero disables the delay.",
|
|
&post_planning_lock_id,
|
|
0,
|
|
0, INT_MAX,
|
|
PGC_USERSET,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
MarkGUCPrefixReserved("delay_execution");
|
|
|
|
/* Install our hook */
|
|
prev_planner_hook = planner_hook;
|
|
planner_hook = delay_execution_planner;
|
|
}
|