Skip to content

Commit 0e24f25

Browse files
committed
WIP implement constraint cache
1 parent 27f2d54 commit 0e24f25

File tree

4 files changed

+170
-71
lines changed

4 files changed

+170
-71
lines changed

src/include/init.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include "utils/snapshot.h"
2222

2323

24+
/* Help user in case of emergency */
25+
#define INIT_ERROR_HINT "pg_pathman will be disabled to allow you to resolve this issue"
26+
27+
2428
/*
2529
* pg_pathman's initialization state structure.
2630
*/
@@ -35,6 +39,7 @@ typedef struct
3539

3640
extern HTAB *partitioned_rels;
3741
extern HTAB *parent_cache;
42+
extern HTAB *constraint_cache;
3843

3944
/* pg_pathman's initialization state */
4045
extern PathmanInitState pg_pathman_init_state;

src/include/relation_info.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "port/atomics.h"
1919
#include "storage/lock.h"
2020
#include "utils/datum.h"
21+
#include "nodes/primnodes.h"
2122

2223

2324
/* Range bound */
@@ -37,7 +38,7 @@ typedef struct
3738
#define IsMinusInfinity(i) ( (i)->is_infinite == MINUS_INFINITY )
3839

3940

40-
inline static Bound
41+
static inline Bound
4142
CopyBound(const Bound *src, bool byval, int typlen)
4243
{
4344
Bound bound = {
@@ -50,31 +51,31 @@ CopyBound(const Bound *src, bool byval, int typlen)
5051
return bound;
5152
}
5253

53-
inline static Bound
54+
static inline Bound
5455
MakeBound(Datum value)
5556
{
5657
Bound bound = { value, FINITE };
5758

5859
return bound;
5960
}
6061

61-
inline static Bound
62+
static inline Bound
6263
MakeBoundInf(int8 infinity_type)
6364
{
6465
Bound bound = { (Datum) 0, infinity_type };
6566

6667
return bound;
6768
}
6869

69-
inline static Datum
70+
static inline Datum
7071
BoundGetValue(const Bound *bound)
7172
{
7273
Assert(!IsInfinite(bound));
7374

7475
return bound->value;
7576
}
7677

77-
inline static int
78+
static inline int
7879
cmp_bounds(FmgrInfo *cmp_func, const Bound *b1, const Bound *b2)
7980
{
8081
if (IsMinusInfinity(b1) || IsPlusInfinity(b2))
@@ -149,6 +150,13 @@ typedef struct
149150
Oid parent_rel;
150151
} PartParentInfo;
151152

153+
typedef struct
154+
{
155+
Oid child_rel; /* key */
156+
Oid conid;
157+
Expr *constraint;
158+
} PartConstraintInfo;
159+
152160
/*
153161
* PartParentSearch
154162
* Represents status of a specific cached entry.
@@ -177,7 +185,7 @@ typedef enum
177185

178186
#define PrelIsValid(prel) ( (prel) && (prel)->valid )
179187

180-
inline static uint32
188+
static inline uint32
181189
PrelLastChild(const PartRelationInfo *prel)
182190
{
183191
Assert(PrelIsValid(prel));
@@ -201,18 +209,26 @@ const PartRelationInfo *get_pathman_relation_info_after_lock(Oid relid,
201209
bool unlock_if_not_found,
202210
LockAcquireResult *lock_result);
203211

212+
/* Global invalidation routines */
204213
void delay_pathman_shutdown(void);
205214
void delay_invalidation_parent_rel(Oid parent);
206215
void delay_invalidation_vague_rel(Oid vague_rel);
207216
void finish_delayed_invalidation(void);
208217

218+
/* Parent cache */
209219
void cache_parent_of_partition(Oid partition, Oid parent);
210220
Oid forget_parent_of_partition(Oid partition, PartParentSearch *status);
211221
Oid get_parent_of_partition(Oid partition, PartParentSearch *status);
212222

223+
/* Constraint cache */
224+
Oid forget_constraint_of_partition(Oid partition);
225+
Expr * get_constraint_of_partition(Oid partition, AttrNumber part_attno);
226+
227+
/* Safe casts for PartType */
213228
PartType DatumGetPartType(Datum datum);
214229
char * PartTypeToCString(PartType parttype);
215230

231+
/* PartRelationInfo checker */
216232
void shout_if_prel_is_invalid(Oid parent_oid,
217233
const PartRelationInfo *prel,
218234
PartType expected_part_type);

src/init.c

Lines changed: 16 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "access/htup_details.h"
2222
#include "access/sysattr.h"
2323
#include "catalog/indexing.h"
24-
#include "catalog/pg_constraint.h"
2524
#include "catalog/pg_extension.h"
2625
#include "catalog/pg_inherits.h"
2726
#include "catalog/pg_inherits_fn.h"
@@ -38,13 +37,6 @@
3837
#include "utils/syscache.h"
3938
#include "utils/typcache.h"
4039

41-
#if PG_VERSION_NUM >= 90600
42-
#include "catalog/pg_constraint_fn.h"
43-
#endif
44-
45-
46-
/* Help user in case of emergency */
47-
#define INIT_ERROR_HINT "pg_pathman will be disabled to allow you to resolve this issue"
4840

4941
/* Initial size of 'partitioned_rels' table */
5042
#define PART_RELS_SIZE 10
@@ -57,6 +49,9 @@ HTAB *partitioned_rels = NULL;
5749
/* Storage for PartParentInfos */
5850
HTAB *parent_cache = NULL;
5951

52+
/* Storage for partition constraints */
53+
HTAB *constraint_cache = NULL;
54+
6055
/* pg_pathman's init status */
6156
PathmanInitState pg_pathman_init_state;
6257

@@ -71,8 +66,6 @@ static void init_local_cache(void);
7166
static void fini_local_cache(void);
7267
static void read_pathman_config(void);
7368

74-
static Expr *get_partition_constraint_expr(Oid partition, AttrNumber part_attno);
75-
7669
static int cmp_range_entries(const void *p1, const void *p2, void *arg);
7770

7871
static bool validate_range_constraint(const Expr *expr,
@@ -312,6 +305,7 @@ init_local_cache(void)
312305
/* Destroy caches, just in case */
313306
hash_destroy(partitioned_rels);
314307
hash_destroy(parent_cache);
308+
hash_destroy(constraint_cache);
315309

316310
memset(&ctl, 0, sizeof(ctl));
317311
ctl.keysize = sizeof(Oid);
@@ -329,6 +323,15 @@ init_local_cache(void)
329323
parent_cache = hash_create("pg_pathman's partition parents cache",
330324
PART_RELS_SIZE * CHILD_FACTOR,
331325
&ctl, HASH_ELEM | HASH_BLOBS);
326+
327+
memset(&ctl, 0, sizeof(ctl));
328+
ctl.keysize = sizeof(Oid);
329+
ctl.entrysize = sizeof(PartConstraintInfo);
330+
ctl.hcxt = TopMemoryContext; /* place data to persistent mcxt */
331+
332+
constraint_cache = hash_create("pg_pathman's partition constraints cache",
333+
PART_RELS_SIZE * CHILD_FACTOR,
334+
&ctl, HASH_ELEM | HASH_BLOBS);
332335
}
333336

334337
/*
@@ -386,10 +389,10 @@ fill_prel_with_partitions(const Oid *partitions,
386389
/* Raise ERROR if there's no such column */
387390
if (part_attno == InvalidAttrNumber)
388391
elog(ERROR, "partition \"%s\" has no column \"%s\"",
389-
get_rel_name_or_relid(partitions[i]),
390-
part_column_name);
392+
get_rel_name_or_relid(partitions[i]), part_column_name);
391393

392-
con_expr = get_partition_constraint_expr(partitions[i], part_attno);
394+
/* Fetch constraint's expression tree */
395+
con_expr = get_constraint_of_partition(partitions[i], part_attno);
393396

394397
/* Perform a partitioning_type-dependent task */
395398
switch (prel->parttype)
@@ -863,58 +866,6 @@ read_pathman_config(void)
863866
heap_close(rel, AccessShareLock);
864867
}
865868

866-
/*
867-
* Get constraint expression tree for a partition.
868-
*
869-
* build_check_constraint_name_internal() is used to build conname.
870-
*/
871-
static Expr *
872-
get_partition_constraint_expr(Oid partition, AttrNumber part_attno)
873-
{
874-
Oid conid; /* constraint Oid */
875-
char *conname; /* constraint name */
876-
HeapTuple con_tuple;
877-
Datum conbin_datum;
878-
bool conbin_isnull;
879-
Expr *expr; /* expression tree for constraint */
880-
881-
conname = build_check_constraint_name_relid_internal(partition, part_attno);
882-
conid = get_relation_constraint_oid(partition, conname, true);
883-
if (conid == InvalidOid)
884-
{
885-
DisablePathman(); /* disable pg_pathman since config is broken */
886-
ereport(ERROR,
887-
(errmsg("constraint \"%s\" for partition \"%s\" does not exist",
888-
conname, get_rel_name_or_relid(partition)),
889-
errhint(INIT_ERROR_HINT)));
890-
}
891-
892-
con_tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conid));
893-
conbin_datum = SysCacheGetAttr(CONSTROID, con_tuple,
894-
Anum_pg_constraint_conbin,
895-
&conbin_isnull);
896-
if (conbin_isnull)
897-
{
898-
DisablePathman(); /* disable pg_pathman since config is broken */
899-
ereport(WARNING,
900-
(errmsg("constraint \"%s\" for partition \"%s\" has NULL conbin",
901-
conname, get_rel_name_or_relid(partition)),
902-
errhint(INIT_ERROR_HINT)));
903-
pfree(conname);
904-
905-
return NULL; /* could not parse */
906-
}
907-
pfree(conname);
908-
909-
/* Finally we get a constraint expression tree */
910-
expr = (Expr *) stringToNode(TextDatumGetCString(conbin_datum));
911-
912-
/* Don't foreget to release syscache tuple */
913-
ReleaseSysCache(con_tuple);
914-
915-
return expr;
916-
}
917-
918869
/* qsort comparison function for RangeEntries */
919870
static int
920871
cmp_range_entries(const void *p1, const void *p2, void *arg)

0 commit comments

Comments
 (0)