Skip to content

Commit f9fa69a

Browse files
committed
Rewrite pathman_ddl_trigger_func(), store RangeEntry's min & max in TopMemoryContext if needed, update FreeChildrenArray & FreeRangesArray
1 parent 7d31d32 commit f9fa69a

File tree

4 files changed

+120
-50
lines changed

4 files changed

+120
-50
lines changed

init.sql

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,22 @@ CREATE OR REPLACE FUNCTION @extschema@.pathman_ddl_trigger_func()
197197
RETURNS event_trigger AS
198198
$$
199199
DECLARE
200-
obj record;
200+
obj record;
201+
pg_class_oid oid;
202+
201203
BEGIN
202-
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() as events
203-
JOIN @extschema@.pathman_config as cfg
204-
ON partrel::oid = events.objid
205-
LOOP
206-
IF obj.object_type = 'table' THEN
207-
EXECUTE 'DELETE FROM @extschema@.pathman_config WHERE partrel = $1'
208-
USING obj.objid;
209-
END IF;
210-
END LOOP;
204+
pg_class_oid = 'pg_class'::regclass;
205+
206+
/* Handle 'DROP TABLE' events */
207+
WITH to_be_deleted AS (
208+
SELECT cfg.partrel AS rel
209+
FROM pg_event_trigger_dropped_objects() AS events
210+
JOIN @extschema@.pathman_config AS cfg
211+
ON cfg.partrel::oid = events.objid
212+
WHERE events.classid = pg_class_oid
213+
)
214+
DELETE FROM @extschema@.pathman_config
215+
WHERE partrel IN (SELECT rel FROM to_be_deleted);
211216
END
212217
$$
213218
LANGUAGE plpgsql;

src/init.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "executor/spi.h"
2828
#include "miscadmin.h"
2929
#include "optimizer/clauses.h"
30+
#include "utils/datum.h"
3031
#include "utils/inval.h"
3132
#include "utils/fmgroids.h"
3233
#include "utils/syscache.h"
@@ -66,7 +67,9 @@ static bool validate_hash_constraint(const Expr *expr,
6667
const PartRelationInfo *prel,
6768
uint32 *part_hash);
6869

69-
static bool read_opexpr_const(const OpExpr *opexpr, AttrNumber varattno, Datum *val);
70+
static bool read_opexpr_const(const OpExpr *opexpr,
71+
const PartRelationInfo *prel,
72+
Datum *val);
7073

7174
static int oid_cmp(const void *p1, const void *p2);
7275

@@ -219,6 +222,7 @@ fill_prel_with_partitions(const Oid *partitions,
219222
/* Finalize 'prel' for a RANGE-partitioned table */
220223
if (prel->parttype == PT_RANGE)
221224
{
225+
MemoryContext old_mcxt;
222226
TypeCacheEntry *tce = lookup_type_cache(prel->atttype,
223227
TYPECACHE_CMP_PROC_FINFO);
224228

@@ -230,6 +234,21 @@ fill_prel_with_partitions(const Oid *partitions,
230234
/* Initialize 'prel->children' array */
231235
for (i = 0; i < PrelChildrenCount(prel); i++)
232236
prel->children[i] = prel->ranges[i].child_oid;
237+
238+
/* Copy all min & max Datums to the persistent mcxt */
239+
old_mcxt = MemoryContextSwitchTo(TopMemoryContext);
240+
for (i = 0; i < PrelChildrenCount(prel); i++)
241+
{
242+
prel->ranges[i].max = datumCopy(prel->ranges[i].max,
243+
prel->attbyval,
244+
prel->attlen);
245+
246+
prel->ranges[i].min = datumCopy(prel->ranges[i].min,
247+
prel->attbyval,
248+
prel->attlen);
249+
}
250+
MemoryContextSwitchTo(old_mcxt);
251+
233252
}
234253

235254
#ifdef USE_ASSERT_CHECKING
@@ -596,7 +615,7 @@ validate_range_constraint(const Expr *expr,
596615
if (BTGreaterEqualStrategyNumber == get_op_opfamily_strategy(opexpr->opno,
597616
tce->btree_opf))
598617
{
599-
if (!read_opexpr_const(opexpr, prel->attnum, min))
618+
if (!read_opexpr_const(opexpr, prel, min))
600619
return false;
601620
}
602621
else
@@ -607,7 +626,7 @@ validate_range_constraint(const Expr *expr,
607626
if (BTLessStrategyNumber == get_op_opfamily_strategy(opexpr->opno,
608627
tce->btree_opf))
609628
{
610-
if (!read_opexpr_const(opexpr, prel->attnum, max))
629+
if (!read_opexpr_const(opexpr, prel, max))
611630
return false;
612631
}
613632
else
@@ -620,19 +639,38 @@ validate_range_constraint(const Expr *expr,
620639
* Reads const value from expressions of kind: VAR >= CONST or VAR < CONST
621640
*/
622641
static bool
623-
read_opexpr_const(const OpExpr *opexpr, AttrNumber varattno, Datum *val)
642+
read_opexpr_const(const OpExpr *opexpr,
643+
const PartRelationInfo *prel,
644+
Datum *val)
624645
{
625-
const Node *left = linitial(opexpr->args);
626-
const Node *right = lsecond(opexpr->args);
646+
const Node *left;
647+
const Node *right;
648+
const Const *constant;
649+
650+
if (list_length(opexpr->args) != 2)
651+
return false;
652+
653+
left = linitial(opexpr->args);
654+
right = lsecond(opexpr->args);
627655

628656
if (!IsA(left, Var) || !IsA(right, Const))
629657
return false;
630-
if (((Var *) left)->varoattno != varattno)
658+
if (((Var *) left)->varoattno != prel->attnum)
631659
return false;
632660
if (((Const *) right)->constisnull)
633661
return false;
634662

635-
*val = ((Const *) right)->constvalue;
663+
constant = (Const *) right;
664+
665+
/* Check that types match */
666+
if (prel->atttype != constant->consttype)
667+
{
668+
elog(WARNING, "Constant type in some check constraint does "
669+
"not match the partitioned column's type");
670+
return false;
671+
}
672+
673+
*val = constant->constvalue;
636674

637675
return true;
638676
}

src/pathman.h

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

59-
#define PATHMAN_CONFIG_partrel_idx "pathman_config_partrel_idx"
60-
6159

6260
/*
6361
* pg_pathman's global state.

src/relation_info.c

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,58 @@ static Oid get_parent_of_partition_internal(Oid partition,
5151
static bool perform_parent_refresh(Oid parent);
5252

5353

54-
#define FreeChildrenArray(prel) \
55-
do { \
56-
uint32 i; \
57-
/* Remove relevant PartParentInfos */ \
58-
if ((prel)->children) \
59-
{ \
60-
for (i = 0; i < PrelChildrenCount(prel); i++) \
61-
{ \
62-
Oid child = (prel)->children[i]; \
63-
/* If it's *always been* relid's partition, free cache */ \
64-
if (relid == get_parent_of_partition(child, NULL)) \
65-
forget_parent_of_partition(child, NULL); \
66-
} \
67-
pfree((prel)->children); \
68-
(prel)->children = NULL; \
69-
} \
70-
} while (0)
54+
/*
55+
* Useful static functions for freeing memory.
56+
*/
7157

72-
#define FreeRangesArray(prel) \
73-
do { \
74-
if ((prel)->ranges) pfree((prel)->ranges); \
75-
(prel)->ranges = NULL; \
76-
} while (0)
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+
}
77106

78107

79108
/*
@@ -103,17 +132,17 @@ refresh_pathman_relation_info(Oid relid,
103132
"Creating new record for relation %u in pg_pathman's cache [%u]",
104133
relid, MyProcPid);
105134

106-
/* First we assume that this entry is invalid */
107-
prel->valid = false;
108-
109135
/* Clear outdated resources */
110-
if (found)
136+
if (found && PrelIsValid(prel))
111137
{
112138
/* Free these arrays iff they're not NULL */
113139
FreeChildrenArray(prel);
114140
FreeRangesArray(prel);
115141
}
116142

143+
/* First we assume that this entry is invalid */
144+
prel->valid = false;
145+
117146
/* Make both arrays point to NULL */
118147
prel->children = NULL;
119148
prel->ranges = NULL;
@@ -180,14 +209,14 @@ invalidate_pathman_relation_info(Oid relid, bool *found)
180209
FreeChildrenArray(prel);
181210
FreeRangesArray(prel);
182211
}
183-
else
212+
/* not found => we create a new one */
213+
else if (!found)
184214
{
185215
prel->children = NULL;
186216
prel->ranges = NULL;
187217
}
188218

189-
if (prel)
190-
prel->valid = false; /* now cache entry is invalid */
219+
prel->valid = false; /* now cache entry is invalid */
191220

192221
elog(DEBUG2,
193222
"Invalidating record for relation %u in pg_pathman's cache [%u]",
@@ -240,7 +269,7 @@ remove_pathman_relation_info(Oid relid)
240269
PartRelationInfo *prel = hash_search(partitioned_rels,
241270
(const void *) &relid,
242271
HASH_FIND, NULL);
243-
if (prel)
272+
if (prel && PrelIsValid(prel))
244273
{
245274
/* Free these arrays iff they're not NULL */
246275
FreeChildrenArray(prel);

0 commit comments

Comments
 (0)