| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * partbounds.h |
| 4 | * |
| 5 | * Copyright (c) 2007-2019, 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 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 | * every datum, which is the index of the partition that accepts a given datum. |
| 50 | * In case of range partitioning, it stores one entry per distinct range |
| 51 | * datum, which is the index of the partition for which a given datum |
| 52 | * is an upper bound. In the case of hash partitioning, the number of the |
| 53 | * entries in the indexes array is same as the greatest modulus amongst all |
| 54 | * partitions. For a given partition key datum-tuple, the index of the |
| 55 | * partition which would accept that datum-tuple would be given by the entry |
| 56 | * pointed by remainder produced when hash value of the datum-tuple is divided |
| 57 | * by the greatest modulus. |
| 58 | */ |
| 59 | typedef struct PartitionBoundInfoData |
| 60 | { |
| 61 | char strategy; /* hash, list or range? */ |
| 62 | int ndatums; /* Length of the datums following array */ |
| 63 | Datum **datums; |
| 64 | PartitionRangeDatumKind **kind; /* The kind of each range bound datum; |
| 65 | * NULL for hash and list partitioned |
| 66 | * tables */ |
| 67 | int *indexes; /* Partition indexes */ |
| 68 | int null_index; /* Index of the null-accepting partition; -1 |
| 69 | * if there isn't one */ |
| 70 | int default_index; /* Index of the default partition; -1 if there |
| 71 | * isn't one */ |
| 72 | } PartitionBoundInfoData; |
| 73 | |
| 74 | #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1) |
| 75 | #define partition_bound_has_default(bi) ((bi)->default_index != -1) |
| 76 | |
| 77 | extern int get_hash_partition_greatest_modulus(PartitionBoundInfo b); |
| 78 | extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, |
| 79 | Oid *partcollation, |
| 80 | Datum *values, bool *isnull); |
| 81 | extern List *get_qual_from_partbound(Relation rel, Relation parent, |
| 82 | PartitionBoundSpec *spec); |
| 83 | extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs, |
| 84 | int nparts, PartitionKey key, int **mapping); |
| 85 | extern bool partition_bounds_equal(int partnatts, int16 *parttyplen, |
| 86 | bool *parttypbyval, PartitionBoundInfo b1, |
| 87 | PartitionBoundInfo b2); |
| 88 | extern PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src, |
| 89 | PartitionKey key); |
| 90 | extern bool partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts); |
| 91 | extern void check_new_partition_bound(char *relname, Relation parent, |
| 92 | PartitionBoundSpec *spec); |
| 93 | extern void check_default_partition_contents(Relation parent, |
| 94 | Relation defaultRel, |
| 95 | PartitionBoundSpec *new_spec); |
| 96 | |
| 97 | extern int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, |
| 98 | Oid *partcollation, |
| 99 | Datum *rb_datums, PartitionRangeDatumKind *rb_kind, |
| 100 | Datum *tuple_datums, int n_tuple_datums); |
| 101 | extern int partition_list_bsearch(FmgrInfo *partsupfunc, |
| 102 | Oid *partcollation, |
| 103 | PartitionBoundInfo boundinfo, |
| 104 | Datum value, bool *is_equal); |
| 105 | extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc, |
| 106 | Oid *partcollation, |
| 107 | PartitionBoundInfo boundinfo, |
| 108 | int nvalues, Datum *values, bool *is_equal); |
| 109 | extern int partition_hash_bsearch(PartitionBoundInfo boundinfo, |
| 110 | int modulus, int remainder); |
| 111 | |
| 112 | #endif /* PARTBOUNDS_H */ |
| 113 | |