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

Commit6f0b632

Browse files
committed
Support testing of cases where table schemas change after planning.
We have various cases where we allow DDL on tables to be performed withless than full AccessExclusiveLock. This requires concurrent queriesto be able to cope with the DDL change mid-flight, but up to now we hadno repeatable way to test such cases. To improve that, invent a testmodule that allows halting a backend after planning and then resumingexecution once we've done desired actions in another session. (The sameapproach could be used to inject delays in other places, if there's asuitable hook available.)This commit includes a single test case, which is meant to exercise thepreviously-untestable ExecCreatePartitionPruneState code repaired bycommit7a980df. We'd probably not bother with this if that were theonly foreseen benefit, but I expect additional test cases will use thisinfrastructure in the future.Test module by Andy Fan, partition-addition test case by me.Discussion:https://postgr.es/m/20200802181131.GA27754@telsasoft.com
1 parent3df92bb commit6f0b632

File tree

6 files changed

+188
-0
lines changed

6 files changed

+188
-0
lines changed

‎src/test/modules/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global
77
SUBDIRS =\
88
brin\
99
commit_ts\
10+
delay_execution\
1011
dummy_index_am\
1112
dummy_seclabel\
1213
snapshot_too_old\
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Generated subdirectories
2+
/output_iso/
3+
/tmp_check_iso/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# src/test/modules/delay_execution/Makefile
2+
3+
PGFILEDESC = "delay_execution - allow delay between parsing and execution"
4+
5+
MODULE_big = delay_execution
6+
OBJS =\
7+
$(WIN32RES)\
8+
delay_execution.o
9+
10+
ISOLATION = partition-addition
11+
12+
ifdefUSE_PGXS
13+
PG_CONFIG = pg_config
14+
PGXS :=$(shell$(PG_CONFIG) --pgxs)
15+
include$(PGXS)
16+
else
17+
subdir = src/test/modules/delay_execution
18+
top_builddir = ../../../..
19+
include$(top_builddir)/src/Makefile.global
20+
include$(top_srcdir)/contrib/contrib-global.mk
21+
endif
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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, 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+
31+
PG_MODULE_MAGIC;
32+
33+
/* GUC: advisory lock ID to use. Zero disables the feature. */
34+
staticintpost_planning_lock_id=0;
35+
36+
/* Save previous planner hook user to be a good citizen */
37+
staticplanner_hook_typeprev_planner_hook=NULL;
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+
staticPlannedStmt*
46+
delay_execution_planner(Query*parse,constchar*query_string,
47+
intcursorOptions,ParamListInfoboundParams)
48+
{
49+
PlannedStmt*result;
50+
51+
/* Invoke the planner, possibly via a previous hook user */
52+
if (prev_planner_hook)
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+
{
62+
DirectFunctionCall1(pg_advisory_lock_int8,
63+
Int64GetDatum((int64)post_planning_lock_id));
64+
DirectFunctionCall1(pg_advisory_unlock_int8,
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+
*/
71+
AcceptInvalidationMessages();
72+
}
73+
74+
returnresult;
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.",
85+
&post_planning_lock_id,
86+
0,
87+
0,INT_MAX,
88+
PGC_USERSET,
89+
0,
90+
NULL,
91+
NULL,
92+
NULL);
93+
94+
/* Install our hook */
95+
prev_planner_hook=planner_hook;
96+
planner_hook=delay_execution_planner;
97+
}
98+
99+
/* Module unload function (pro forma, not used currently) */
100+
void
101+
_PG_fini(void)
102+
{
103+
planner_hook=prev_planner_hook;
104+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Parsed test spec with 2 sessions
2+
3+
starting permutation: s2lock s1exec s2addp s2unlock
4+
step s2lock: SELECT pg_advisory_lock(12345);
5+
pg_advisory_lock
6+
7+
8+
step s1exec: LOAD 'delay_execution';
9+
SET delay_execution.post_planning_lock_id = 12345;
10+
SELECT * FROM foo WHERE a <> 1 AND a <> (SELECT 3); <waiting ...>
11+
step s2addp: CREATE TABLE foo2 (LIKE foo);
12+
ALTER TABLE foo ATTACH PARTITION foo2 FOR VALUES IN (2);
13+
INSERT INTO foo VALUES (2, 'ADD2');
14+
step s2unlock: SELECT pg_advisory_unlock(12345);
15+
pg_advisory_unlock
16+
17+
t
18+
step s1exec: <... completed>
19+
a b
20+
21+
4 GHI
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Test addition of a partition with less-than-exclusive locking.
2+
3+
setup
4+
{
5+
CREATETABLEfoo (aint,btext)PARTITIONBYLIST(a);
6+
CREATETABLEfoo1PARTITIONOFfooFORVALUESIN (1);
7+
CREATETABLEfoo3PARTITIONOFfooFORVALUESIN (3);
8+
CREATETABLEfoo4PARTITIONOFfooFORVALUESIN (4);
9+
INSERTINTOfooVALUES (1,'ABC');
10+
INSERTINTOfooVALUES (3,'DEF');
11+
INSERTINTOfooVALUES (4,'GHI');
12+
}
13+
14+
teardown
15+
{
16+
DROPTABLEfoo;
17+
}
18+
19+
# The SELECT will be planned with just the three partitions shown above,
20+
# of which we expect foo1 to be pruned at planning and foo3 at execution.
21+
# Then we'll block, and by the time the query is actually executed,
22+
# partition foo2 will also exist. We expect that not to be scanned.
23+
# This test is specifically designed to check ExecCreatePartitionPruneState's
24+
# code for matching up the partition lists in such cases.
25+
26+
session"s1"
27+
step"s1exec"{LOAD'delay_execution';
28+
SETdelay_execution.post_planning_lock_id=12345;
29+
SELECT*FROMfooWHEREa<>1ANDa<> (SELECT3); }
30+
31+
session"s2"
32+
step"s2lock"{SELECTpg_advisory_lock(12345); }
33+
step"s2unlock"{SELECTpg_advisory_unlock(12345); }
34+
step"s2addp"{CREATETABLEfoo2 (LIKEfoo);
35+
ALTERTABLEfooATTACHPARTITIONfoo2FORVALUESIN (2);
36+
INSERTINTOfooVALUES (2,'ADD2'); }
37+
38+
permutation"s2lock""s1exec""s2addp""s2unlock"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp