PostgreSQL Source Code  git master
delay_execution.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * delay_execution.c
4  * Test module to allow delay between parsing and execution of a query.
5  *
6  * The delay is implemented by taking and immediately releasing a specified
7  * advisory lock. If another process has previously taken that lock, the
8  * current process will be blocked until the lock is released; otherwise,
9  * there's no effect. This allows an isolationtester script to reliably
10  * test behaviors where some specified action happens in another backend
11  * between parsing and execution of any desired query.
12  *
13  * Copyright (c) 2020-2021, PostgreSQL Global Development Group
14  *
15  * IDENTIFICATION
16  * src/test/modules/delay_execution/delay_execution.c
17  *
18  *-------------------------------------------------------------------------
19  */
20 
21 #include "postgres.h"
22 
23 #include <limits.h>
24 
25 #include "optimizer/planner.h"
26 #include "utils/builtins.h"
27 #include "utils/guc.h"
28 #include "utils/inval.h"
29 
30 
32 
33 /* GUC: advisory lock ID to use. Zero disables the feature. */
34 static int post_planning_lock_id = 0;
35 
36 /* Save previous planner hook user to be a good citizen */
38 
39 /* Module load/unload functions */
40 void _PG_init(void);
41 void _PG_fini(void);
42 
43 
44 /* planner_hook function to provide the desired delay */
45 static PlannedStmt *
46 delay_execution_planner(Query *parse, const char *query_string,
47  int cursorOptions, ParamListInfo boundParams)
48 {
49  PlannedStmt *result;
50 
51  /* Invoke the planner, possibly via a previous hook user */
53  result = prev_planner_hook(parse, query_string, cursorOptions,
54  boundParams);
55  else
56  result = standard_planner(parse, query_string, cursorOptions,
57  boundParams);
58 
59  /* If enabled, delay by taking and releasing the specified lock */
60  if (post_planning_lock_id != 0)
61  {
65  Int64GetDatum((int64) post_planning_lock_id));
66 
67  /*
68  * Ensure that we notice any pending invalidations, since the advisory
69  * lock functions don't do this.
70  */
72  }
73 
74  return result;
75 }
76 
77 /* Module load function */
78 void
79 _PG_init(void)
80 {
81  /* Set up the GUC to control which lock is used */
82  DefineCustomIntVariable("delay_execution.post_planning_lock_id",
83  "Sets the advisory lock ID to be locked/unlocked after planning.",
84  "Zero disables the delay.",
86  0,
87  0, INT_MAX,
89  0,
90  NULL,
91  NULL,
92  NULL);
93 
94  /* Install our hook */
97 }
98 
99 /* Module unload function (pro forma, not used currently) */
100 void
101 _PG_fini(void)
102 {
104 }
void DefineCustomIntVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, int minValue, int maxValue, GucContext context, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, GucShowHook show_hook)
Definition: guc.c:8991
void AcceptInvalidationMessages(void)
Definition: inval.c:687
static PlannedStmt * delay_execution_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
PlannedStmt *(* planner_hook_type)(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: planner.h:26
static planner_hook_type prev_planner_hook
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void _PG_init(void)
PG_MODULE_MAGIC
planner_hook_type planner_hook
Definition: planner.c:74
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1700
static int post_planning_lock_id
void _PG_fini(void)
Datum pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:829
PlannedStmt * standard_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: planner.c:278
Datum pg_advisory_lock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:683
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648