diff --git a/init.sql b/init.sql index fdb774db..7dab67d8 100644 --- a/init.sql +++ b/init.sql @@ -111,7 +111,7 @@ ALTER TABLE @extschema@.pathman_config ENABLE ROW LEVEL SECURITY; ALTER TABLE @extschema@.pathman_config_params ENABLE ROW LEVEL SECURITY; /* - * Invalidate relcache every time someone changes parameters config. + * Invalidate relcache every time someone changes parameters config or pathman_config */ CREATE OR REPLACE FUNCTION @extschema@.pathman_config_params_trigger_func() RETURNS TRIGGER AS 'pg_pathman', 'pathman_config_params_trigger_func' @@ -121,6 +121,10 @@ CREATE TRIGGER pathman_config_params_trigger AFTER INSERT OR UPDATE OR DELETE ON @extschema@.pathman_config_params FOR EACH ROW EXECUTE PROCEDURE @extschema@.pathman_config_params_trigger_func(); +CREATE TRIGGER pathman_config_trigger +AFTER INSERT OR UPDATE OR DELETE ON @extschema@.pathman_config +FOR EACH ROW EXECUTE PROCEDURE @extschema@.pathman_config_params_trigger_func(); + /* * Enable dump of config tables with pg_dump. */ diff --git a/pg_pathman--1.4--1.5.sql b/pg_pathman--1.4--1.5.sql index 11406476..2aa02bf9 100644 --- a/pg_pathman--1.4--1.5.sql +++ b/pg_pathman--1.4--1.5.sql @@ -52,6 +52,10 @@ ALTER TABLE @extschema@.pathman_config ADD CONSTRAINT pathman_config_interval_ch parttype, range_interval)); +CREATE TRIGGER pathman_config_trigger +AFTER INSERT OR UPDATE OR DELETE ON @extschema@.pathman_config +FOR EACH ROW EXECUTE PROCEDURE @extschema@.pathman_config_params_trigger_func(); + /* * Get parsed and analyzed expression. */ diff --git a/src/hooks.c b/src/hooks.c index 656efe9f..90d84dc4 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -874,7 +874,7 @@ pathman_relcache_hook(Datum arg, Oid relid) else if (relid >= FirstNormalObjectId) { /* Invalidate PartBoundInfo entry if needed */ - forget_bounds_of_partition(relid); + forget_bounds_of_rel(relid); /* Invalidate PartParentInfo entry if needed */ forget_parent_of_partition(relid); diff --git a/src/include/relation_info.h b/src/include/relation_info.h index 6b9ffa92..5b23cd3b 100644 --- a/src/include/relation_info.h +++ b/src/include/relation_info.h @@ -367,7 +367,7 @@ void shout_if_prel_is_invalid(const Oid parent_oid, const PartType expected_part_type); /* Bounds cache */ -void forget_bounds_of_partition(Oid partition); +void forget_bounds_of_rel(Oid partition); PartBoundInfo *get_bounds_of_partition(Oid partition, const PartRelationInfo *prel); Expr *get_partition_constraint_expr(Oid partition, bool raise_error); void invalidate_bounds_cache(void); diff --git a/src/pl_funcs.c b/src/pl_funcs.c index 06b1cf56..7ca2ec0a 100644 --- a/src/pl_funcs.c +++ b/src/pl_funcs.c @@ -904,14 +904,16 @@ pathman_config_params_trigger_func(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; Oid pathman_config_params; + Oid pathman_config; Oid partrel; Datum partrel_datum; bool partrel_isnull; /* Fetch Oid of PATHMAN_CONFIG_PARAMS */ pathman_config_params = get_pathman_config_params_relid(true); + pathman_config = get_pathman_config_relid(true); - /* Handle "pg_pathman.enabled = t" case */ + /* Handle "pg_pathman.enabled = f" case */ if (!OidIsValid(pathman_config_params)) goto pathman_config_params_trigger_func_return; @@ -925,12 +927,17 @@ pathman_config_params_trigger_func(PG_FUNCTION_ARGS) trigdata->tg_trigger->tgname); /* Handle wrong relation */ - if (RelationGetRelid(trigdata->tg_relation) != pathman_config_params) - elog(ERROR, "%s: must be fired for relation \"%s\"", + if (RelationGetRelid(trigdata->tg_relation) != pathman_config_params && + RelationGetRelid(trigdata->tg_relation) != pathman_config) + elog(ERROR, "%s: must be fired for relation \"%s\" or \"%s\"", trigdata->tg_trigger->tgname, - get_rel_name(pathman_config_params)); + get_rel_name(pathman_config_params), + get_rel_name(pathman_config)); - /* Extract partitioned relation's Oid */ + /* + * Extract partitioned relation's Oid. + * Hacky: 1 is attrnum of relid for both pathman_config and pathman_config_params + */ partrel_datum = heap_getattr(trigdata->tg_trigtuple, Anum_pathman_config_params_partrel, RelationGetDescr(trigdata->tg_relation), diff --git a/src/relation_info.c b/src/relation_info.c index 9bb8d0db..d524c168 100644 --- a/src/relation_info.c +++ b/src/relation_info.c @@ -160,6 +160,8 @@ static void fill_pbin_with_bounds(PartBoundInfo *pbin, static int cmp_range_entries(const void *p1, const void *p2, void *arg); +static void forget_bounds_of_partition(Oid partition); + static bool query_contains_subqueries(Node *node, void *context); @@ -929,7 +931,7 @@ PrelExpressionAttributesMap(const PartRelationInfo *prel, */ /* Remove partition's constraint from cache */ -void +static void forget_bounds_of_partition(Oid partition) { PartBoundInfo *pbin; @@ -953,6 +955,42 @@ forget_bounds_of_partition(Oid partition) HASH_REMOVE, NULL); } + +} + +/* + * Remove rel's constraint from cache, if relid is partition; + * Remove all children constraints, if it is parent. + */ +void +forget_bounds_of_rel(Oid relid) +{ + PartStatusInfo *psin; + + forget_bounds_of_partition(relid); + + /* + * If it was the parent who got invalidated, purge children's bounds. + * We assume here that if bounds_cache has something, parent must be also + * in status_cache. Fragile, but seems better then blowing out full bounds + * cache or digging pathman_config on each relcache invalidation. + */ + + /* Find status cache entry for this relation */ + psin = pathman_cache_search_relid(status_cache, + relid, HASH_FIND, + NULL); + if (psin != NULL && psin->prel != NULL) + { + uint32 i; + PartRelationInfo *prel = psin->prel; + Oid *children = PrelGetChildrenArray(prel); + + for (i = 0; i < PrelChildrenCount(prel); i++) + { + forget_bounds_of_partition(children[i]); + } + } } /* Return partition's constraint as expression tree */