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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy