1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2007-2025, PostgreSQL Global Development Group
7 * src/include/partitioning/partbounds.h
9 *-------------------------------------------------------------------------
15 #include "parser/parse_node.h"
16 #include "partitioning/partdefs.h"
18 struct RelOptInfo
; /* avoid including pathnodes.h here */
22 * PartitionBoundInfoData encapsulates a set of partition bounds. It is
23 * usually associated with partitioned tables as part of its partition
24 * descriptor, but may also be used to represent a virtual partitioned
25 * table such as a partitioned joinrel within the planner.
27 * A list partition datum that is known to be NULL is never put into the
28 * datums array. Instead, it is tracked using the null_index field.
30 * In the case of range partitioning, ndatums will typically be far less than
31 * 2 * nparts, because a partition's upper bound and the next partition's lower
32 * bound are the same in most common cases, and we only store one of them (the
33 * upper bound). In case of hash partitioning, ndatums will be the same as the
34 * number of partitions.
36 * For range and list partitioned tables, datums is an array of datum-tuples
37 * with key->partnatts datums each. For hash partitioned tables, it is an array
38 * of datum-tuples with 2 datums, modulus and remainder, corresponding to a
41 * The datums in datums array are arranged in increasing order as defined by
42 * functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and
43 * qsort_partition_hbound_cmp() for range, list and hash partitioned tables
44 * respectively. For range and list partitions this simply means that the
45 * datums in the datums array are arranged in increasing order as defined by
46 * the partition key's operator classes and collations.
48 * In the case of list partitioning, the indexes array stores one entry for
49 * each datum-array entry, which is the index of the partition that accepts
50 * rows matching that datum. So nindexes == ndatums.
52 * In the case of range partitioning, the indexes array stores one entry per
53 * distinct range datum, which is the index of the partition for which that
54 * datum is an upper bound (or -1 for a "gap" that has no partition). It is
55 * convenient to have an extra -1 entry representing values above the last
56 * range datum, so nindexes == ndatums + 1.
58 * In the case of hash partitioning, the number of entries in the indexes
59 * array is the same as the greatest modulus amongst all partitions (which
60 * is a multiple of all partition moduli), so nindexes == greatest modulus.
61 * The indexes array is indexed according to the hash key's remainder modulo
62 * the greatest modulus, and it contains either the partition index accepting
63 * that remainder, or -1 if there is no partition for that remainder.
65 * For LIST partitioned tables, we track the partition indexes of partitions
66 * which are possibly "interleaved" partitions. A partition is considered
67 * interleaved if it allows multiple values and there exists at least one
68 * other partition which could contain a value that lies between those values.
69 * For example, if a partition exists FOR VALUES IN(3,5) and another partition
70 * exists FOR VALUES IN (4), then the IN(3,5) partition is an interleaved
71 * partition. The same is possible with DEFAULT partitions since they can
72 * contain any value that does not belong in another partition. This field
73 * only serves as proof that a particular partition is not interleaved, not
74 * proof that it is interleaved. When we're uncertain, we marked the
75 * partition as interleaved. The interleaved_parts field is only ever set for
76 * RELOPT_BASEREL and RELOPT_OTHER_MEMBER_REL, it is always left NULL for join
79 typedef struct PartitionBoundInfoData
81 PartitionStrategy strategy
; /* hash, list or range? */
82 int ndatums
; /* Length of the datums[] array */
84 PartitionRangeDatumKind
**kind
; /* The kind of each range bound datum;
85 * NULL for hash and list partitioned
87 Bitmapset
*interleaved_parts
; /* Partition indexes of partitions which
88 * may be interleaved. See above. This is
89 * only set for LIST partitioned tables */
90 int nindexes
; /* Length of the indexes[] array */
91 int *indexes
; /* Partition indexes */
92 int null_index
; /* Index of the null-accepting partition; -1
93 * if there isn't one */
94 int default_index
; /* Index of the default partition; -1 if there
96 } PartitionBoundInfoData
;
98 #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
99 #define partition_bound_has_default(bi) ((bi)->default_index != -1)
101 extern int get_hash_partition_greatest_modulus(PartitionBoundInfo bound
);
102 extern uint64
compute_partition_hash_value(int partnatts
, FmgrInfo
*partsupfunc
,
103 const Oid
*partcollation
,
104 const Datum
*values
, const bool *isnull
);
105 extern List
*get_qual_from_partbound(Relation parent
,
106 PartitionBoundSpec
*spec
);
107 extern PartitionBoundInfo
partition_bounds_create(PartitionBoundSpec
**boundspecs
,
108 int nparts
, PartitionKey key
, int **mapping
);
109 extern bool partition_bounds_equal(int partnatts
, int16
*parttyplen
,
110 bool *parttypbyval
, PartitionBoundInfo b1
,
111 PartitionBoundInfo b2
);
112 extern PartitionBoundInfo
partition_bounds_copy(PartitionBoundInfo src
,
114 extern PartitionBoundInfo
partition_bounds_merge(int partnatts
,
115 FmgrInfo
*partsupfunc
,
117 struct RelOptInfo
*outer_rel
,
118 struct RelOptInfo
*inner_rel
,
122 extern bool partitions_are_ordered(PartitionBoundInfo boundinfo
,
123 Bitmapset
*live_parts
);
124 extern void check_new_partition_bound(char *relname
, Relation parent
,
125 PartitionBoundSpec
*spec
,
127 extern void check_default_partition_contents(Relation parent
,
128 Relation default_rel
,
129 PartitionBoundSpec
*new_spec
);
131 extern int32
partition_rbound_datum_cmp(FmgrInfo
*partsupfunc
,
133 Datum
*rb_datums
, PartitionRangeDatumKind
*rb_kind
,
134 Datum
*tuple_datums
, int n_tuple_datums
);
135 extern int partition_list_bsearch(FmgrInfo
*partsupfunc
,
137 PartitionBoundInfo boundinfo
,
138 Datum value
, bool *is_equal
);
139 extern int partition_range_datum_bsearch(FmgrInfo
*partsupfunc
,
141 PartitionBoundInfo boundinfo
,
142 int nvalues
, Datum
*values
, bool *is_equal
);
143 extern int partition_hash_bsearch(PartitionBoundInfo boundinfo
,
144 int modulus
, int remainder
);
146 #endif /* PARTBOUNDS_H */