Skip to content

Commit 79466c6

Browse files
committed
PartitionFilter: invalidate PartRelationInfo on partition creation, fix invalidate_pathman_relation_info()
1 parent f9fa69a commit 79466c6

File tree

8 files changed

+163
-92
lines changed

8 files changed

+163
-92
lines changed

src/hooks.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
452452
if (post_parse_analyze_hook_next)
453453
post_parse_analyze_hook_next(pstate, query);
454454

455+
/* Finish delayed invalidation jobs */
456+
if (IsPathmanReady())
457+
finish_delayed_invalidation();
458+
455459
/* Load config if pg_pathman exists & it's still necessary */
456460
if (IsPathmanEnabled() &&
457461
initialization_needed &&
@@ -461,10 +465,6 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
461465
load_config(); /* perform main cache initialization */
462466
}
463467

464-
/* Finish delayed invalidation jobs */
465-
if (IsPathmanReady())
466-
finish_delayed_invalidation();
467-
468468
inheritance_disabled_relids = NIL;
469469
inheritance_enabled_relids = NIL;
470470
}
@@ -495,6 +495,9 @@ pathman_relcache_hook(Datum arg, Oid relid)
495495
PartParentSearch search;
496496
Oid partitioned_table;
497497

498+
if (!IsPathmanReady())
499+
return;
500+
498501
/* Invalidate PartParentInfo cache if needed */
499502
partitioned_table = forget_parent_of_partition(relid, &search);
500503

@@ -516,6 +519,9 @@ pathman_relcache_hook(Datum arg, Oid relid)
516519
{
517520
elog(DEBUG2, "Invalidation message for relation %u [%u]",
518521
relid, MyProcPid);
522+
523+
if (relid == get_pathman_config_relid())
524+
delay_pathman_shutdown();
519525
}
520526
break;
521527

src/init.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ static int oid_cmp(const void *p1, const void *p2);
7878
* Create local PartRelationInfo cache & load pg_pathman's config.
7979
*/
8080
void
81-
load_config()
81+
load_config(void)
8282
{
83+
/* cache PATHMAN_CONFIG relation Oid */
84+
pathman_config_relid = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
85+
8386
init_local_config(); /* create 'relations' hash table */
8487
read_pathman_config(); /* read PATHMAN_CONFIG table & fill cache */
8588

@@ -88,6 +91,34 @@ load_config()
8891
elog(DEBUG2, "pg_pathman's config has been loaded successfully");
8992
}
9093

94+
/*
95+
* Destroy local caches & free memory.
96+
*/
97+
void
98+
unload_config(void)
99+
{
100+
HASH_SEQ_STATUS status;
101+
PartRelationInfo *prel;
102+
103+
hash_seq_init(&status, partitioned_rels);
104+
while((prel = (PartRelationInfo *) hash_seq_search(&status)) != NULL)
105+
{
106+
if (PrelIsValid(prel))
107+
{
108+
FreeChildrenArray(prel);
109+
FreeRangesArray(prel);
110+
}
111+
}
112+
113+
/* Now we can safely destroy hash tables */
114+
hash_destroy(partitioned_rels);
115+
hash_destroy(parent_cache);
116+
partitioned_rels = NULL;
117+
parent_cache = NULL;
118+
119+
initialization_needed = true;
120+
}
121+
91122
/*
92123
* Estimate shmem amount needed for pg_pathman to run.
93124
*/
@@ -105,12 +136,6 @@ init_local_config(void)
105136
{
106137
HASHCTL ctl;
107138

108-
if (partitioned_rels)
109-
{
110-
elog(DEBUG2, "pg_pathman's partitioned relations table already exists");
111-
return;
112-
}
113-
114139
memset(&ctl, 0, sizeof(ctl));
115140
ctl.keysize = sizeof(Oid);
116141
ctl.entrysize = sizeof(PartRelationInfo);
@@ -392,24 +417,20 @@ bool
392417
pathman_config_contains_relation(Oid relid, Datum *values, bool *isnull,
393418
TransactionId *xmin)
394419
{
395-
Oid pathman_config;
396420
Relation rel;
397421
HeapScanDesc scan;
398422
ScanKeyData key[1];
399423
Snapshot snapshot;
400424
HeapTuple htup;
401425
bool contains_rel = false;
402426

403-
/* Get PATHMAN_CONFIG table Oid */
404-
pathman_config = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
405-
406427
ScanKeyInit(&key[0],
407428
Anum_pathman_config_partrel,
408429
BTEqualStrategyNumber, F_OIDEQ,
409430
ObjectIdGetDatum(relid));
410431

411-
/* Open relation with latest snapshot available */
412-
rel = heap_open(pathman_config, AccessShareLock);
432+
/* Open PATHMAN_CONFIG with latest snapshot available */
433+
rel = heap_open(get_pathman_config_relid(), AccessShareLock);
413434

414435
/* Check that 'partrel' column is if regclass type */
415436
Assert(RelationGetDescr(rel)->
@@ -471,17 +492,13 @@ pathman_config_contains_relation(Oid relid, Datum *values, bool *isnull,
471492
static void
472493
read_pathman_config(void)
473494
{
474-
Oid pathman_config;
475495
Relation rel;
476496
HeapScanDesc scan;
477497
Snapshot snapshot;
478498
HeapTuple htup;
479499

480-
/* Get PATHMAN_CONFIG table Oid */
481-
pathman_config = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
482-
483-
/* Open relation with latest snapshot available */
484-
rel = heap_open(pathman_config, AccessShareLock);
500+
/* Open PATHMAN_CONFIG with latest snapshot available */
501+
rel = heap_open(get_pathman_config_relid(), AccessShareLock);
485502

486503
/* Check that 'partrel' column is if regclass type */
487504
Assert(RelationGetDescr(rel)->

src/init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Size estimate_pathman_shmem_size(void);
2828
void init_local_config(void);
2929
void init_shmem_config(void);
3030
void load_config(void);
31+
void unload_config(void);
3132

3233
void fill_prel_with_partitions(const Oid *partitions,
3334
const uint32 parts_count,

src/partition_filter.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ partition_filter_exec(CustomScanState *node)
207207
selected_partid = create_partitions(state->partitioned_table,
208208
state->temp_const.constvalue,
209209
state->temp_const.consttype);
210+
211+
/* get_pathman_relation_info() will refresh this entry */
212+
invalidate_pathman_relation_info(state->partitioned_table, NULL);
210213
}
211214
else
212215
selected_partid = parts[0];

src/pathman.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
/* type modifier (typmod) for 'range_interval' */
5757
#define PATHMAN_CONFIG_interval_typmod -1
5858

59+
extern Oid pathman_config_relid;
60+
61+
Oid get_pathman_config_relid(void);
62+
5963

6064
/*
6165
* pg_pathman's global state.

src/pg_pathman.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ List *inheritance_disabled_relids = NIL;
5050
List *inheritance_enabled_relids = NIL;
5151
bool pg_pathman_enable = true;
5252
PathmanState *pmstate;
53+
Oid pathman_config_relid = InvalidOid;
5354

5455

5556
/* pg module functions */
@@ -2075,3 +2076,9 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
20752076
}
20762077
}
20772078
}
2079+
2080+
Oid
2081+
get_pathman_config_relid(void)
2082+
{
2083+
return pathman_config_relid;
2084+
}

src/relation_info.c

Lines changed: 43 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
#include "utils/snapmgr.h"
2727

2828

29-
static List *delayed_invalidation_parent_rels = NIL;
30-
static List *delayed_invalidation_vague_rels = NIL;
29+
static List *delayed_invalidation_parent_rels = NIL;
30+
static List *delayed_invalidation_vague_rels = NIL;
31+
static bool delayed_shutdown = false;
3132

3233
/* Add unique Oid to list, allocate in TopMemoryContext */
3334
#define list_add_unique(list, oid) \
@@ -51,60 +52,6 @@ static Oid get_parent_of_partition_internal(Oid partition,
5152
static bool perform_parent_refresh(Oid parent);
5253

5354

54-
/*
55-
* Useful static functions for freeing memory.
56-
*/
57-
58-
static inline void
59-
FreeChildrenArray(PartRelationInfo *prel)
60-
{
61-
uint32 i;
62-
63-
Assert(PrelIsValid(prel));
64-
65-
/* Remove relevant PartParentInfos */
66-
if ((prel)->children)
67-
{
68-
for (i = 0; i < PrelChildrenCount(prel); i++)
69-
{
70-
Oid child = (prel)->children[i];
71-
72-
/* If it's *always been* relid's partition, free cache */
73-
if (prel->key == get_parent_of_partition(child, NULL))
74-
forget_parent_of_partition(child, NULL);
75-
}
76-
77-
pfree((prel)->children);
78-
(prel)->children = NULL;
79-
}
80-
}
81-
82-
static inline void
83-
FreeRangesArray(PartRelationInfo *prel)
84-
{
85-
uint32 i;
86-
87-
Assert(PrelIsValid(prel));
88-
89-
/* Remove RangeEntries array */
90-
if ((prel)->ranges)
91-
{
92-
/* Remove persistent entries if not byVal */
93-
if (!(prel)->attbyval)
94-
{
95-
for (i = 0; i < PrelChildrenCount(prel); i++)
96-
{
97-
pfree(DatumGetPointer((prel)->ranges[i].min));
98-
pfree(DatumGetPointer((prel)->ranges[i].max));
99-
}
100-
}
101-
102-
pfree((prel)->ranges);
103-
(prel)->ranges = NULL;
104-
}
105-
}
106-
107-
10855
/*
10956
* refresh\invalidate\get\remove PartRelationInfo functions.
11057
*/
@@ -132,6 +79,12 @@ refresh_pathman_relation_info(Oid relid,
13279
"Creating new record for relation %u in pg_pathman's cache [%u]",
13380
relid, MyProcPid);
13481

82+
/*
83+
* NOTE: Trick clang analyzer (first access without NULL pointer check).
84+
* Access to field 'valid' results in a dereference of a null pointer.
85+
*/
86+
prel->cmp_proc = InvalidOid;
87+
13588
/* Clear outdated resources */
13689
if (found && PrelIsValid(prel))
13790
{
@@ -199,24 +152,33 @@ refresh_pathman_relation_info(Oid relid,
199152
void
200153
invalidate_pathman_relation_info(Oid relid, bool *found)
201154
{
202-
PartRelationInfo *prel = hash_search(partitioned_rels,
203-
(const void *) &relid,
204-
(found ? HASH_FIND : HASH_ENTER),
205-
found);
155+
bool prel_found;
156+
HASHACTION action = found ? HASH_FIND : HASH_ENTER;
157+
PartRelationInfo *prel;
206158

207-
if(found && PrelIsValid(prel))
159+
prel = hash_search(partitioned_rels,
160+
(const void *) &relid,
161+
action, &prel_found);
162+
163+
if ((action == HASH_FIND ||
164+
(action == HASH_ENTER && prel_found)) && PrelIsValid(prel))
208165
{
209166
FreeChildrenArray(prel);
210167
FreeRangesArray(prel);
168+
169+
prel->valid = false; /* now cache entry is invalid */
211170
}
212-
/* not found => we create a new one */
213-
else if (!found)
171+
/* Handle invalid PartRelationInfo */
172+
else if (prel)
214173
{
215174
prel->children = NULL;
216175
prel->ranges = NULL;
176+
177+
prel->valid = false; /* now cache entry is invalid */
217178
}
218179

219-
prel->valid = false; /* now cache entry is invalid */
180+
/* Set 'found' if necessary */
181+
if (found) *found = prel_found;
220182

221183
elog(DEBUG2,
222184
"Invalidating record for relation %u in pg_pathman's cache [%u]",
@@ -291,6 +253,13 @@ remove_pathman_relation_info(Oid relid)
291253
* Functions for delayed invalidation.
292254
*/
293255

256+
/* Add new delayed pathman shutdown job (DROP EXTENSION) */
257+
void
258+
delay_pathman_shutdown(void)
259+
{
260+
delayed_shutdown = true;
261+
}
262+
294263
/* Add new delayed invalidation job for a [ex-]parent relation */
295264
void
296265
delay_invalidation_parent_rel(Oid parent)
@@ -311,17 +280,23 @@ finish_delayed_invalidation(void)
311280
{
312281
/* Exit early if there's nothing to do */
313282
if (delayed_invalidation_parent_rels == NIL &&
314-
delayed_invalidation_vague_rels == NIL)
283+
delayed_invalidation_vague_rels == NIL &&
284+
delayed_shutdown == false)
315285
{
316286
return;
317287
}
318288

319289
/* Check that current state is transactional */
320290
if (IsTransactionState())
321291
{
322-
ListCell *lc;
292+
ListCell *lc;
323293

324-
//elog(WARNING, "invalidating...");
294+
if (delayed_shutdown)
295+
{
296+
delayed_shutdown = false;
297+
unload_config();
298+
return;
299+
}
325300

326301
/* Process relations that are (or were) definitely partitioned */
327302
foreach (lc, delayed_invalidation_parent_rels)
@@ -541,8 +516,7 @@ perform_parent_refresh(Oid parent)
541516
parttype = DatumGetPartType(values[Anum_pathman_config_parttype - 1]);
542517
attname = DatumGetTextP(values[Anum_pathman_config_attname - 1]);
543518

544-
if (!refresh_pathman_relation_info(parent, parttype,
545-
text_to_cstring(attname)))
519+
if (!refresh_pathman_relation_info(parent, parttype, text_to_cstring(attname)))
546520
return false;
547521
}
548522
else

0 commit comments

Comments
 (0)