summaryrefslogtreecommitdiffstats
path: root/src/include/partitioning
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:17:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:17:33 +0000
commit5e45211a64149b3c659b90ff2de6fa982a5a93ed (patch)
tree739caf8c461053357daa9f162bef34516c7bf452 /src/include/partitioning
parentInitial commit. (diff)
downloadpostgresql-15-5e45211a64149b3c659b90ff2de6fa982a5a93ed.tar.xz
postgresql-15-5e45211a64149b3c659b90ff2de6fa982a5a93ed.zip
Adding upstream version 15.5.upstream/15.5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/include/partitioning')
-rw-r--r--src/include/partitioning/partbounds.h146
-rw-r--r--src/include/partitioning/partdefs.h26
-rw-r--r--src/include/partitioning/partdesc.h50
-rw-r--r--src/include/partitioning/partprune.h81
4 files changed, 303 insertions, 0 deletions
diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h
new file mode 100644
index 0000000..b1e3f1b
--- /dev/null
+++ b/src/include/partitioning/partbounds.h
@@ -0,0 +1,146 @@
+/*-------------------------------------------------------------------------
+ *
+ * partbounds.h
+ *
+ * Copyright (c) 2007-2022, 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.
+ *
+ * For LIST partitioned tables, we track the partition indexes of partitions
+ * which are possibly "interleaved" partitions. A partition is considered
+ * interleaved if it allows multiple values and there exists at least one
+ * other partition which could contain a value that lies between those values.
+ * For example, if a partition exists FOR VALUES IN(3,5) and another partition
+ * exists FOR VALUES IN (4), then the IN(3,5) partition is an interleaved
+ * partition. The same is possible with DEFAULT partitions since they can
+ * contain any value that does not belong in another partition. This field
+ * only serves as proof that a particular partition is not interleaved, not
+ * proof that it is interleaved. When we're uncertain, we marked the
+ * partition as interleaved. The interleaved_parts field is only ever set for
+ * RELOPT_BASEREL and RELOPT_OTHER_MEMBER_REL, it is always left NULL for join
+ * relations.
+ */
+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 */
+ Bitmapset *interleaved_parts; /* Partition indexes of partitions which
+ * may be interleaved. See above. This is
+ * only set for 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 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,
+ Bitmapset *live_parts);
+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..aed62ea
--- /dev/null
+++ b/src/include/partitioning/partdefs.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdefs.h
+ * Base definitions for partitioned table handling
+ *
+ * Copyright (c) 2007-2022, 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..ae1afe3
--- /dev/null
+++ b/src/include/partitioning/partdesc.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdesc.h
+ *
+ * Copyright (c) 1996-2022, 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..90684ef
--- /dev/null
+++ b/src/include/partitioning/partprune.h
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+ *
+ * partprune.h
+ * prototypes for partprune.c
+ *
+ *
+ * Portions Copyright (c) 1996-2022, 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.
+ * exprcontext ExprContext to use when evaluating pruning expressions
+ * 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;
+ ExprContext *exprcontext;
+ 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 */