diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2018-04-14 21:12:14 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2018-04-14 21:12:14 -0300 |
commit | da6f3e45ddb68ab3161076e120e7c32cfd46d1db (patch) | |
tree | ce5b30869c67d8be6a86fd6f8f0ba95b5ed61e73 /src/backend/executor/execPartition.c | |
parent | b39fd897e0398a6bdc6552daa7cacdf9c0e46d7e (diff) | |
download | postgresql-da6f3e45ddb68ab3161076e120e7c32cfd46d1db.tar.gz postgresql-da6f3e45ddb68ab3161076e120e7c32cfd46d1db.zip |
Reorganize partitioning code
There's been a massive addition of partitioning code in PostgreSQL 11,
with little oversight on its placement, resulting in a
catalog/partition.c with poorly defined boundaries and responsibilities.
This commit tries to set a couple of distinct modules to separate things
a little bit. There are no code changes here, only code movement.
There are three new files:
src/backend/utils/cache/partcache.c
src/include/partitioning/partdefs.h
src/include/utils/partcache.h
The previous arrangement of #including catalog/partition.h almost
everywhere is no more.
Authors: Amit Langote and Álvaro Herrera
Discussion: https://postgr.es/m/98e8d509-790a-128c-be7f-e48a5b2d8d97@lab.ntt.co.jp
https://postgr.es/m/11aa0c50-316b-18bb-722d-c23814f39059@lab.ntt.co.jp
https://postgr.es/m/143ed9a4-6038-76d4-9a55-502035815e68@lab.ntt.co.jp
https://postgr.es/m/20180413193503.nynq7bnmgh6vs5vm@alvherre.pgsql
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 11139f743d1..218645d43b8 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -11,9 +11,9 @@ * *------------------------------------------------------------------------- */ - #include "postgres.h" +#include "catalog/partition.h" #include "catalog/pg_inherits.h" #include "catalog/pg_type.h" #include "executor/execPartition.h" @@ -22,10 +22,15 @@ #include "mb/pg_wchar.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "partitioning/partbounds.h" +#include "partitioning/partprune.h" #include "utils/lsyscache.h" +#include "utils/partcache.h" +#include "utils/rel.h" #include "utils/rls.h" #include "utils/ruleutils.h" + static PartitionDispatch *RelationGetPartitionDispatchInfo(Relation rel, int *num_parted, List **leaf_part_oids); static void get_partition_dispatch_recurse(Relation rel, Relation parent, @@ -35,6 +40,8 @@ static void FormPartitionKeyDatum(PartitionDispatch pd, EState *estate, Datum *values, bool *isnull); +static int get_partition_for_tuple(Relation relation, Datum *values, + bool *isnull); static char *ExecBuildSlotPartitionKeyDescription(Relation rel, Datum *values, bool *isnull, @@ -1023,6 +1030,110 @@ FormPartitionKeyDatum(PartitionDispatch pd, } /* + * get_partition_for_tuple + * Finds partition of relation which accepts the partition key specified + * in values and isnull + * + * Return value is index of the partition (>= 0 and < partdesc->nparts) if one + * found or -1 if none found. + */ +int +get_partition_for_tuple(Relation relation, Datum *values, bool *isnull) +{ + int bound_offset; + int part_index = -1; + PartitionKey key = RelationGetPartitionKey(relation); + PartitionDesc partdesc = RelationGetPartitionDesc(relation); + + /* Route as appropriate based on partitioning strategy. */ + switch (key->strategy) + { + case PARTITION_STRATEGY_HASH: + { + PartitionBoundInfo boundinfo = partdesc->boundinfo; + int greatest_modulus = get_hash_partition_greatest_modulus(boundinfo); + uint64 rowHash = compute_hash_value(key->partnatts, + key->partsupfunc, + values, isnull); + + part_index = boundinfo->indexes[rowHash % greatest_modulus]; + } + break; + + case PARTITION_STRATEGY_LIST: + if (isnull[0]) + { + if (partition_bound_accepts_nulls(partdesc->boundinfo)) + part_index = partdesc->boundinfo->null_index; + } + else + { + bool equal = false; + + bound_offset = partition_list_bsearch(key->partsupfunc, + key->partcollation, + partdesc->boundinfo, + values[0], &equal); + if (bound_offset >= 0 && equal) + part_index = partdesc->boundinfo->indexes[bound_offset]; + } + break; + + case PARTITION_STRATEGY_RANGE: + { + bool equal = false, + range_partkey_has_null = false; + int i; + + /* + * No range includes NULL, so this will be accepted by the + * default partition if there is one, and otherwise rejected. + */ + for (i = 0; i < key->partnatts; i++) + { + if (isnull[i]) + { + range_partkey_has_null = true; + break; + } + } + + if (!range_partkey_has_null) + { + bound_offset = partition_range_datum_bsearch(key->partsupfunc, + key->partcollation, + partdesc->boundinfo, + key->partnatts, + values, + &equal); + + /* + * The bound at bound_offset is less than or equal to the + * tuple value, so the bound at offset+1 is the upper + * bound of the partition we're looking for, if there + * actually exists one. + */ + part_index = partdesc->boundinfo->indexes[bound_offset + 1]; + } + } + break; + + default: + elog(ERROR, "unexpected partition strategy: %d", + (int) key->strategy); + } + + /* + * part_index < 0 means we failed to find a partition of this parent. Use + * the default partition, if there is one. + */ + if (part_index < 0) + part_index = partdesc->boundinfo->default_index; + + return part_index; +} + +/* * ExecBuildSlotPartitionKeyDescription * * This works very much like BuildIndexValueDescription() and is currently |