Skip to content

Commit 85fc5cc

Browse files
committed
Blow out cached bounds of all children when parent is invalidated.
A concrete example where leaving them is not ok is - Range partition table - Delete entry from pathman_config (psin was blown, but bounds not) - Now hash partition table; bounds cache with uninitialized hash_idx is used. While here, also spawn relcache inval message on delete from pathman_config, not only from pathman_config_params.
1 parent 10e6c71 commit 85fc5cc

File tree

6 files changed

+62
-9
lines changed

6 files changed

+62
-9
lines changed

Diff for: init.sql

+5-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ ALTER TABLE @[email protected]_config ENABLE ROW LEVEL SECURITY;
111111
ALTER TABLE @[email protected]_config_params ENABLE ROW LEVEL SECURITY;
112112

113113
/*
114-
* Invalidate relcache every time someone changes parameters config.
114+
* Invalidate relcache every time someone changes parameters config or pathman_config
115115
*/
116116
CREATE OR REPLACE FUNCTION @[email protected]_config_params_trigger_func()
117117
RETURNS TRIGGER AS 'pg_pathman', 'pathman_config_params_trigger_func'
@@ -121,6 +121,10 @@ CREATE TRIGGER pathman_config_params_trigger
121121
AFTER INSERT OR UPDATE OR DELETE ON @[email protected]_config_params
122122
FOR EACH ROW EXECUTE PROCEDURE @[email protected]_config_params_trigger_func();
123123

124+
CREATE TRIGGER pathman_config_trigger
125+
AFTER INSERT OR UPDATE OR DELETE ON @[email protected]_config
126+
FOR EACH ROW EXECUTE PROCEDURE @[email protected]_config_params_trigger_func();
127+
124128
/*
125129
* Enable dump of config tables with pg_dump.
126130
*/

Diff for: pg_pathman--1.4--1.5.sql

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ ALTER TABLE @[email protected]_config ADD CONSTRAINT pathman_config_interval_ch
5252
parttype,
5353
range_interval));
5454

55+
CREATE TRIGGER pathman_config_trigger
56+
AFTER INSERT OR UPDATE OR DELETE ON @[email protected]_config
57+
FOR EACH ROW EXECUTE PROCEDURE @[email protected]_config_params_trigger_func();
58+
5559
/*
5660
* Get parsed and analyzed expression.
5761
*/

Diff for: src/hooks.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ pathman_relcache_hook(Datum arg, Oid relid)
874874
else if (relid >= FirstNormalObjectId)
875875
{
876876
/* Invalidate PartBoundInfo entry if needed */
877-
forget_bounds_of_partition(relid);
877+
forget_bounds_of_rel(relid);
878878

879879
/* Invalidate PartParentInfo entry if needed */
880880
forget_parent_of_partition(relid);

Diff for: src/include/relation_info.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ void shout_if_prel_is_invalid(const Oid parent_oid,
367367
const PartType expected_part_type);
368368

369369
/* Bounds cache */
370-
void forget_bounds_of_partition(Oid partition);
370+
void forget_bounds_of_rel(Oid partition);
371371
PartBoundInfo *get_bounds_of_partition(Oid partition, const PartRelationInfo *prel);
372372
Expr *get_partition_constraint_expr(Oid partition, bool raise_error);
373373
void invalidate_bounds_cache(void);

Diff for: src/pl_funcs.c

+12-5
Original file line numberDiff line numberDiff line change
@@ -904,14 +904,16 @@ pathman_config_params_trigger_func(PG_FUNCTION_ARGS)
904904
{
905905
TriggerData *trigdata = (TriggerData *) fcinfo->context;
906906
Oid pathman_config_params;
907+
Oid pathman_config;
907908
Oid partrel;
908909
Datum partrel_datum;
909910
bool partrel_isnull;
910911

911912
/* Fetch Oid of PATHMAN_CONFIG_PARAMS */
912913
pathman_config_params = get_pathman_config_params_relid(true);
914+
pathman_config = get_pathman_config_relid(true);
913915

914-
/* Handle "pg_pathman.enabled = t" case */
916+
/* Handle "pg_pathman.enabled = f" case */
915917
if (!OidIsValid(pathman_config_params))
916918
goto pathman_config_params_trigger_func_return;
917919

@@ -925,12 +927,17 @@ pathman_config_params_trigger_func(PG_FUNCTION_ARGS)
925927
trigdata->tg_trigger->tgname);
926928

927929
/* Handle wrong relation */
928-
if (RelationGetRelid(trigdata->tg_relation) != pathman_config_params)
929-
elog(ERROR, "%s: must be fired for relation \"%s\"",
930+
if (RelationGetRelid(trigdata->tg_relation) != pathman_config_params &&
931+
RelationGetRelid(trigdata->tg_relation) != pathman_config)
932+
elog(ERROR, "%s: must be fired for relation \"%s\" or \"%s\"",
930933
trigdata->tg_trigger->tgname,
931-
get_rel_name(pathman_config_params));
934+
get_rel_name(pathman_config_params),
935+
get_rel_name(pathman_config));
932936

933-
/* Extract partitioned relation's Oid */
937+
/*
938+
* Extract partitioned relation's Oid.
939+
* Hacky: 1 is attrnum of relid for both pathman_config and pathman_config_params
940+
*/
934941
partrel_datum = heap_getattr(trigdata->tg_trigtuple,
935942
Anum_pathman_config_params_partrel,
936943
RelationGetDescr(trigdata->tg_relation),

Diff for: src/relation_info.c

+39-1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ static void fill_pbin_with_bounds(PartBoundInfo *pbin,
160160

161161
static int cmp_range_entries(const void *p1, const void *p2, void *arg);
162162

163+
static void forget_bounds_of_partition(Oid partition);
164+
163165
static bool query_contains_subqueries(Node *node, void *context);
164166

165167

@@ -929,7 +931,7 @@ PrelExpressionAttributesMap(const PartRelationInfo *prel,
929931
*/
930932

931933
/* Remove partition's constraint from cache */
932-
void
934+
static void
933935
forget_bounds_of_partition(Oid partition)
934936
{
935937
PartBoundInfo *pbin;
@@ -953,6 +955,42 @@ forget_bounds_of_partition(Oid partition)
953955
HASH_REMOVE,
954956
NULL);
955957
}
958+
959+
}
960+
961+
/*
962+
* Remove rel's constraint from cache, if relid is partition;
963+
* Remove all children constraints, if it is parent.
964+
*/
965+
void
966+
forget_bounds_of_rel(Oid relid)
967+
{
968+
PartStatusInfo *psin;
969+
970+
forget_bounds_of_partition(relid);
971+
972+
/*
973+
* If it was the parent who got invalidated, purge children's bounds.
974+
* We assume here that if bounds_cache has something, parent must be also
975+
* in status_cache. Fragile, but seems better then blowing out full bounds
976+
* cache or digging pathman_config on each relcache invalidation.
977+
*/
978+
979+
/* Find status cache entry for this relation */
980+
psin = pathman_cache_search_relid(status_cache,
981+
relid, HASH_FIND,
982+
NULL);
983+
if (psin != NULL && psin->prel != NULL)
984+
{
985+
uint32 i;
986+
PartRelationInfo *prel = psin->prel;
987+
Oid *children = PrelGetChildrenArray(prel);
988+
989+
for (i = 0; i < PrelChildrenCount(prel); i++)
990+
{
991+
forget_bounds_of_partition(children[i]);
992+
}
993+
}
956994
}
957995

958996
/* Return partition's constraint as expression tree */

0 commit comments

Comments
 (0)