1 /*-------------------------------------------------------------------------
2  *
3  * partbounds.h
4  *
5  * Copyright (c) 2007-2018, PostgreSQL Global Development Group
6  *
7  * src/include/partitioning/partbounds.h
8  *
9  *-------------------------------------------------------------------------
10  */
11 #ifndef PARTBOUNDS_H
12 #define PARTBOUNDS_H
13 
14 #include "fmgr.h"
15 #include "nodes/parsenodes.h"
16 #include "nodes/pg_list.h"
17 #include "partitioning/partdefs.h"
18 #include "utils/relcache.h"
19 
20 
21 /*
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.
26  *
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.
29  *
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.
35  *
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
39  * given partition.
40  *
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.
47  *
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.
51  *
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.
57  *
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.
64  */
65 typedef struct PartitionBoundInfoData
66 {
67 	char		strategy;		/* hash, list or range? */
68 	int			ndatums;		/* Length of the datums[] array */
69 	Datum	  **datums;
70 	PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
71 									 * NULL for hash and list partitioned
72 									 * tables */
73 	int		   *indexes;		/* Partition indexes */
74 	int			null_index;		/* Index of the null-accepting partition; -1
75 								 * if there isn't one */
76 	int			default_index;	/* Index of the default partition; -1 if there
77 								 * isn't one */
78 	int			nindexes;		/* Length of the indexes[] array */
79 } PartitionBoundInfoData;
80 
81 #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
82 #define partition_bound_has_default(bi) ((bi)->default_index != -1)
83 
84 /*
85  * When qsort'ing partition bounds after reading from the catalog, each bound
86  * is represented with one of the following structs.
87  */
88 
89 /* One bound of a hash partition */
90 typedef struct PartitionHashBound
91 {
92 	int			modulus;
93 	int			remainder;
94 	int			index;
95 } PartitionHashBound;
96 
97 /* One value coming from some (index'th) list partition */
98 typedef struct PartitionListValue
99 {
100 	int			index;
101 	Datum		value;
102 } PartitionListValue;
103 
104 /* One bound of a range partition */
105 typedef struct PartitionRangeBound
106 {
107 	int			index;
108 	Datum	   *datums;			/* range bound datums */
109 	PartitionRangeDatumKind *kind;	/* the kind of each datum */
110 	bool		lower;			/* this is the lower (vs upper) bound */
111 } PartitionRangeBound;
112 
113 extern int	get_hash_partition_greatest_modulus(PartitionBoundInfo b);
114 extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc,
115 							 Datum *values, bool *isnull);
116 extern List *get_qual_from_partbound(Relation rel, Relation parent,
117 						PartitionBoundSpec *spec);
118 extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
119 					   bool *parttypbyval, PartitionBoundInfo b1,
120 					   PartitionBoundInfo b2);
121 extern PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src,
122 					  PartitionKey key);
123 extern void check_new_partition_bound(char *relname, Relation parent,
124 						  PartitionBoundSpec *spec);
125 extern void check_default_partition_contents(Relation parent,
126 								 Relation defaultRel,
127 								 PartitionBoundSpec *new_spec);
128 
129 extern PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index,
130 						  List *datums, bool lower);
131 extern int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2,
132 					 int remainder2);
133 extern int32 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc,
134 					 Oid *partcollation, Datum *datums1,
135 					 PartitionRangeDatumKind *kind1, bool lower1,
136 					 PartitionRangeBound *b2);
137 extern int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc,
138 						   Oid *partcollation,
139 						   Datum *rb_datums, PartitionRangeDatumKind *rb_kind,
140 						   Datum *tuple_datums, int n_tuple_datums);
141 extern int partition_list_bsearch(FmgrInfo *partsupfunc,
142 					   Oid *partcollation,
143 					   PartitionBoundInfo boundinfo,
144 					   Datum value, bool *is_equal);
145 extern int partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc,
146 						Oid *partcollation,
147 						PartitionBoundInfo boundinfo,
148 						PartitionRangeBound *probe, bool *is_equal);
149 extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc,
150 							  Oid *partcollation,
151 							  PartitionBoundInfo boundinfo,
152 							  int nvalues, Datum *values, bool *is_equal);
153 extern int partition_hash_bsearch(PartitionBoundInfo boundinfo,
154 					   int modulus, int remainder);
155 
156 #endif							/* PARTBOUNDS_H */
157