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