diff options
Diffstat (limited to 'src/include/partitioning')
-rw-r--r-- | src/include/partitioning/partbounds.h | 128 | ||||
-rw-r--r-- | src/include/partitioning/partdefs.h | 26 | ||||
-rw-r--r-- | src/include/partitioning/partdesc.h | 50 | ||||
-rw-r--r-- | src/include/partitioning/partprune.h | 79 |
4 files changed, 283 insertions, 0 deletions
diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h new file mode 100644 index 0000000..ebf3ff1 --- /dev/null +++ b/src/include/partitioning/partbounds.h @@ -0,0 +1,128 @@ +/*------------------------------------------------------------------------- + * + * partbounds.h + * + * Copyright (c) 2007-2021, PostgreSQL Global Development Group + * + * src/include/partitioning/partbounds.h + * + *------------------------------------------------------------------------- + */ +#ifndef PARTBOUNDS_H +#define PARTBOUNDS_H + +#include "fmgr.h" +#include "parser/parse_node.h" +#include "partitioning/partdefs.h" + +struct RelOptInfo; /* avoid including pathnodes.h here */ + + +/* + * PartitionBoundInfoData encapsulates a set of partition bounds. It is + * usually associated with partitioned tables as part of its partition + * descriptor, but may also be used to represent a virtual partitioned + * table such as a partitioned joinrel within the planner. + * + * A list partition datum that is known to be NULL is never put into the + * datums array. Instead, it is tracked using the null_index field. + * + * In the case of range partitioning, ndatums will typically be far less than + * 2 * nparts, because a partition's upper bound and the next partition's lower + * bound are the same in most common cases, and we only store one of them (the + * upper bound). In case of hash partitioning, ndatums will be the same as the + * number of partitions. + * + * For range and list partitioned tables, datums is an array of datum-tuples + * with key->partnatts datums each. For hash partitioned tables, it is an array + * of datum-tuples with 2 datums, modulus and remainder, corresponding to a + * given partition. + * + * The datums in datums array are arranged in increasing order as defined by + * functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and + * qsort_partition_hbound_cmp() for range, list and hash partitioned tables + * respectively. For range and list partitions this simply means that the + * datums in the datums array are arranged in increasing order as defined by + * the partition key's operator classes and collations. + * + * In the case of list partitioning, the indexes array stores one entry for + * each datum-array entry, which is the index of the partition that accepts + * rows matching that datum. So nindexes == ndatums. + * + * In the case of range partitioning, the indexes array stores one entry per + * distinct range datum, which is the index of the partition for which that + * datum is an upper bound (or -1 for a "gap" that has no partition). It is + * convenient to have an extra -1 entry representing values above the last + * range datum, so nindexes == ndatums + 1. + * + * In the case of hash partitioning, the number of entries in the indexes + * array is the same as the greatest modulus amongst all partitions (which + * is a multiple of all partition moduli), so nindexes == greatest modulus. + * The indexes array is indexed according to the hash key's remainder modulo + * the greatest modulus, and it contains either the partition index accepting + * that remainder, or -1 if there is no partition for that remainder. + */ +typedef struct PartitionBoundInfoData +{ + char strategy; /* hash, list or range? */ + int ndatums; /* Length of the datums[] array */ + Datum **datums; + PartitionRangeDatumKind **kind; /* The kind of each range bound datum; + * NULL for hash and list partitioned + * tables */ + int nindexes; /* Length of the indexes[] array */ + int *indexes; /* Partition indexes */ + int null_index; /* Index of the null-accepting partition; -1 + * if there isn't one */ + int default_index; /* Index of the default partition; -1 if there + * isn't one */ +} PartitionBoundInfoData; + +#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1) +#define partition_bound_has_default(bi) ((bi)->default_index != -1) + +extern int get_hash_partition_greatest_modulus(PartitionBoundInfo b); +extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, + Oid *partcollation, + Datum *values, bool *isnull); +extern List *get_qual_from_partbound(Relation rel, Relation parent, + PartitionBoundSpec *spec); +extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs, + int nparts, PartitionKey key, int **mapping); +extern bool partition_bounds_equal(int partnatts, int16 *parttyplen, + bool *parttypbyval, PartitionBoundInfo b1, + PartitionBoundInfo b2); +extern PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src, + PartitionKey key); +extern PartitionBoundInfo partition_bounds_merge(int partnatts, + FmgrInfo *partsupfunc, + Oid *partcollation, + struct RelOptInfo *outer_rel, + struct RelOptInfo *inner_rel, + JoinType jointype, + List **outer_parts, + List **inner_parts); +extern bool partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts); +extern void check_new_partition_bound(char *relname, Relation parent, + PartitionBoundSpec *spec, + ParseState *pstate); +extern void check_default_partition_contents(Relation parent, + Relation defaultRel, + PartitionBoundSpec *new_spec); + +extern int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, + Oid *partcollation, + Datum *rb_datums, PartitionRangeDatumKind *rb_kind, + Datum *tuple_datums, int n_tuple_datums); +extern int partition_list_bsearch(FmgrInfo *partsupfunc, + Oid *partcollation, + PartitionBoundInfo boundinfo, + Datum value, bool *is_equal); +extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc, + Oid *partcollation, + PartitionBoundInfo boundinfo, + int nvalues, Datum *values, bool *is_equal); +extern int partition_hash_bsearch(PartitionBoundInfo boundinfo, + int modulus, int remainder); + +#endif /* PARTBOUNDS_H */ diff --git a/src/include/partitioning/partdefs.h b/src/include/partitioning/partdefs.h new file mode 100644 index 0000000..d742b96 --- /dev/null +++ b/src/include/partitioning/partdefs.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * partdefs.h + * Base definitions for partitioned table handling + * + * Copyright (c) 2007-2021, PostgreSQL Global Development Group + * + * src/include/partitioning/partdefs.h + * + *------------------------------------------------------------------------- + */ +#ifndef PARTDEFS_H +#define PARTDEFS_H + + +typedef struct PartitionBoundInfoData *PartitionBoundInfo; + +typedef struct PartitionKeyData *PartitionKey; + +typedef struct PartitionBoundSpec PartitionBoundSpec; + +typedef struct PartitionDescData *PartitionDesc; + +typedef struct PartitionDirectoryData *PartitionDirectory; + +#endif /* PARTDEFS_H */ diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h new file mode 100644 index 0000000..0792f48 --- /dev/null +++ b/src/include/partitioning/partdesc.h @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------- + * + * partdesc.h + * + * Copyright (c) 1996-2021, PostgreSQL Global Development Group + * + * src/include/partitioning/partdesc.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PARTDESC_H +#define PARTDESC_H + +#include "partitioning/partdefs.h" +#include "utils/relcache.h" + +/* + * Information about partitions of a partitioned table. + * + * For partitioned tables where detached partitions exist, we only cache + * descriptors that include all partitions, including detached; when we're + * requested a descriptor without the detached partitions, we create one + * afresh each time. (The reason for this is that the set of detached + * partitions that are visible to each caller depends on the snapshot it has, + * so it's pretty much impossible to evict a descriptor from cache at the + * right time.) + */ +typedef struct PartitionDescData +{ + int nparts; /* Number of partitions */ + bool detached_exist; /* Are there any detached partitions? */ + Oid *oids; /* Array of 'nparts' elements containing + * partition OIDs in order of the their bounds */ + bool *is_leaf; /* Array of 'nparts' elements storing whether + * the corresponding 'oids' element belongs to + * a leaf partition or not */ + PartitionBoundInfo boundinfo; /* collection of partition bounds */ +} PartitionDescData; + + +extern PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached); + +extern PartitionDirectory CreatePartitionDirectory(MemoryContext mcxt, bool omit_detached); +extern PartitionDesc PartitionDirectoryLookup(PartitionDirectory, Relation); +extern void DestroyPartitionDirectory(PartitionDirectory pdir); + +extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc); + +#endif /* PARTCACHE_H */ diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h new file mode 100644 index 0000000..5f51e73 --- /dev/null +++ b/src/include/partitioning/partprune.h @@ -0,0 +1,79 @@ +/*------------------------------------------------------------------------- + * + * partprune.h + * prototypes for partprune.c + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/partitioning/partprune.h + * + *------------------------------------------------------------------------- + */ +#ifndef PARTPRUNE_H +#define PARTPRUNE_H + +#include "nodes/execnodes.h" +#include "partitioning/partdefs.h" + +struct PlannerInfo; /* avoid including pathnodes.h here */ +struct RelOptInfo; + + +/* + * PartitionPruneContext + * Stores information needed at runtime for pruning computations + * related to a single partitioned table. + * + * strategy Partition strategy, e.g. LIST, RANGE, HASH. + * partnatts Number of columns in the partition key. + * nparts Number of partitions in this partitioned table. + * boundinfo Partition boundary info for the partitioned table. + * partcollation Array of partnatts elements, storing the collations of the + * partition key columns. + * partsupfunc Array of FmgrInfos for the comparison or hashing functions + * associated with the partition keys (partnatts elements). + * (This points into the partrel's partition key, typically.) + * stepcmpfuncs Array of FmgrInfos for the comparison or hashing function + * for each pruning step and partition key. + * ppccontext Memory context holding this PartitionPruneContext's + * subsidiary data, such as the FmgrInfos. + * planstate Points to the parent plan node's PlanState when called + * during execution; NULL when called from the planner. + * exprstates Array of ExprStates, indexed as per PruneCxtStateIdx; one + * for each partition key in each pruning step. Allocated if + * planstate is non-NULL, otherwise NULL. + */ +typedef struct PartitionPruneContext +{ + char strategy; + int partnatts; + int nparts; + PartitionBoundInfo boundinfo; + Oid *partcollation; + FmgrInfo *partsupfunc; + FmgrInfo *stepcmpfuncs; + MemoryContext ppccontext; + PlanState *planstate; + ExprState **exprstates; +} PartitionPruneContext; + +/* + * PruneCxtStateIdx() computes the correct index into the stepcmpfuncs[] + * and exprstates[] arrays for step step_id and partition key column keyno. + * (Note: there is code that assumes the entries for a given step are + * sequential, so this is not chosen freely.) + */ +#define PruneCxtStateIdx(partnatts, step_id, keyno) \ + ((partnatts) * (step_id) + (keyno)) + +extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root, + struct RelOptInfo *parentrel, + List *subpaths, + List *prunequal); +extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel); +extern Bitmapset *get_matching_partitions(PartitionPruneContext *context, + List *pruning_steps); + +#endif /* PARTPRUNE_H */ |