Hi.
On 2018/04/06 7:35, Alvaro Herrera wrote:
> I seems pretty clear that putting get_matching_partitions() in
> catalog/partition.c is totally the wrong thing; it belongs wholly in
> partprune. I think the reason you put it there is that it requires
> access to a lot of internals that are static in partition.c. In the
> attached not yet cleaned version of the patch, I have moved a whole lot
> of what you added to partition.c to partprune.c; and for the functions
> and struct declarations that were required to make it work, I created
> catalog/partition_internal.h.
Yes, I really wanted for most of the new code that this patch adds to land
in the planner, especially after Robert's comments here:
https://www.postgresql.org/message-id/CA%2BTgmoabi-29Vs8H0xkjtYB%3DcU%2BGVCrNwPz7okpa3KsoLmdEUQ%40mail.gmail.com
It would've been nice if we'd gotten the "reorganizing partitioning code"
thread resolved sooner.
> I changed a lot of code also, but cosmetic changes only.
>
> I'll clean this up a bit more now, and try to commit shortly (or early
> tomorrow); wanted to share current status now in case I have to rush
> out.
Some comments on the code reorganizing part of the patch:
* Did you intentionally not put PartitionBoundInfoData and its accessor
macros in partition_internal.h. partprune.c would not need to include
partition.h if we do that.
* Also, I wonder why you left PartitionPruneContext in partition.h. Isn't
it better taken out to partprune.h?
I have done that in the attached.
* Why isn't gen_partprune_steps() in partprune.h? I see only
prune_append_rel_partitions() exported out of partprune.c, but the runtime
patch needs gen_partprune_steps() to be called from createplan.c.
* I don't see get_matching_partitions() exported either. Runtime pruning
patch needs that too.
Maybe you've thought something about these two items though.
Thanks,
Amit
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index d5e91b111d..f89c99f544 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -24,7 +24,6 @@
#include "catalog/indexing.h"
#include "catalog/objectaddress.h"
#include "catalog/partition.h"
-#include "catalog/partition_internal.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_inherits_fn.h"
diff --git a/src/backend/optimizer/util/partprune.c
b/src/backend/optimizer/util/partprune.c
index b0638d5aa6..93553b5d13 100644
--- a/src/backend/optimizer/util/partprune.c
+++ b/src/backend/optimizer/util/partprune.c
@@ -19,8 +19,6 @@
#include "access/hash.h"
#include "access/nbtree.h"
-#include "catalog/partition.h"
-#include "catalog/partition_internal.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_type.h"
@@ -35,6 +33,7 @@
#include "parser/parse_coerce.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
+#include "utils/array.h"
#include "utils/lsyscache.h"
/*
diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h
index 0bcaa36165..1c17553917 100644
--- a/src/include/catalog/partition.h
+++ b/src/include/catalog/partition.h
@@ -13,7 +13,7 @@
#ifndef PARTITION_H
#define PARTITION_H
-#include "fmgr.h"
+#include "catalog/partition_internal.h"
#include "executor/tuptable.h"
#include "nodes/execnodes.h"
#include "parser/parse_node.h"
@@ -23,65 +23,6 @@
#define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD)
/*
- * PartitionBoundInfoData encapsulates a set of partition bounds. It is
- * usually associated with partitioned tables as part of its partition
- * descriptor, but may also be used to represent a virtual partitioned
- * table such as a partitioned joinrel within the planner.
- *
- * A list partition datum that is known to be NULL is never put into the
- * datums array. Instead, it is tracked using the null_index field.
- *
- * In the case of range partitioning, ndatums will typically be far less than
- * 2 * nparts, because a partition's upper bound and the next partition's lower
- * bound are the same in most common cases, and we only store one of them (the
- * upper bound). In case of hash partitioning, ndatums will be same as the
- * number of partitions.
- *
- * For range and list partitioned tables, datums is an array of datum-tuples
- * with key->partnatts datums each. For hash partitioned tables, it is an
array
- * of datum-tuples with 2 datums, modulus and remainder, corresponding to a
- * given partition.
- *
- * The datums in datums array are arranged in increasing order as defined by
- * functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and
- * qsort_partition_hbound_cmp() for range, list and hash partitioned tables
- * respectively. For range and list partitions this simply means that the
- * datums in the datums array are arranged in increasing order as defined by
- * the partition key's operator classes and collations.
- *
- * In the case of list partitioning, the indexes array stores one entry for
- * every datum, which is the index of the partition that accepts a given datum.
- * In case of range partitioning, it stores one entry per distinct range
- * datum, which is the index of the partition for which a given datum
- * is an upper bound. In the case of hash partitioning, the number of the
- * entries in the indexes array is same as the greatest modulus amongst all
- * partitions. For a given partition key datum-tuple, the index of the
- * partition which would accept that datum-tuple would be given by the entry
- * pointed by remainder produced when hash value of the datum-tuple is divided
- * by the greatest modulus.
- */
-
-typedef struct PartitionBoundInfoData
-{
- char strategy; /* hash, list or range? */
- int ndatums; /* Length of the datums
following array */
- Datum **datums;
- PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
- * NULL
for hash and list partitioned
- *
tables */
- int *indexes; /* Partition indexes */
- int null_index; /* Index of the
null-accepting partition; -1
- * if there
isn't one */
- int default_index; /* Index of the default
partition; -1 if there
- * isn't one */
-} PartitionBoundInfoData;
-
-typedef struct PartitionBoundInfoData *PartitionBoundInfo;
-
-#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
-#define partition_bound_has_default(bi) ((bi)->default_index != -1)
-
-/*
* Information about partitions of a partitioned table.
*/
typedef struct PartitionDescData
@@ -93,28 +34,6 @@ typedef struct PartitionDescData
typedef struct PartitionDescData *PartitionDesc;
-/*
- * PartitionPruneContext
- *
- * Information about a partitioned table needed to perform partition pruning.
- */
-typedef struct PartitionPruneContext
-{
- /* Partition key information */
- char strategy;
- int partnatts;
- Oid *partopfamily;
- Oid *partopcintype;
- Oid *partcollation;
- FmgrInfo *partsupfunc;
-
- /* Number of partitions */
- int nparts;
-
- /* Partition boundary info */
- PartitionBoundInfo boundinfo;
-} PartitionPruneContext;
-
extern void RelationBuildPartitionDesc(Relation relation);
extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
bool *parttypbyval,
PartitionBoundInfo b1,
diff --git a/src/include/catalog/partition_internal.h
b/src/include/catalog/partition_internal.h
index b21d422e75..e3b9123a2e 100644
--- a/src/include/catalog/partition_internal.h
+++ b/src/include/catalog/partition_internal.h
@@ -11,6 +11,9 @@
#ifndef PARTITION_INTERNAL_H
#define PARTITION_INTERNAL_H
+#include "fmgr.h"
+#include "nodes/parsenodes.h"
+
/*
* When qsort'ing partition bounds after reading from the catalog, each bound
* is represented with one of the following structs.
@@ -40,6 +43,63 @@ typedef struct PartitionRangeBound
bool lower; /* this is the lower (vs upper)
bound */
} PartitionRangeBound;
+/*
+ * PartitionBoundInfoData encapsulates a set of partition bounds. It is
+ * usually associated with partitioned tables as part of its partition
+ * descriptor, but may also be used to represent a virtual partitioned
+ * table such as a partitioned joinrel within the planner.
+ *
+ * A list partition datum that is known to be NULL is never put into the
+ * datums array. Instead, it is tracked using the null_index field.
+ *
+ * In the case of range partitioning, ndatums will typically be far less than
+ * 2 * nparts, because a partition's upper bound and the next partition's lower
+ * bound are the same in most common cases, and we only store one of them (the
+ * upper bound). In case of hash partitioning, ndatums will be same as the
+ * number of partitions.
+ *
+ * For range and list partitioned tables, datums is an array of datum-tuples
+ * with key->partnatts datums each. For hash partitioned tables, it is an
array
+ * of datum-tuples with 2 datums, modulus and remainder, corresponding to a
+ * given partition.
+ *
+ * The datums in datums array are arranged in increasing order as defined by
+ * functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and
+ * qsort_partition_hbound_cmp() for range, list and hash partitioned tables
+ * respectively. For range and list partitions this simply means that the
+ * datums in the datums array are arranged in increasing order as defined by
+ * the partition key's operator classes and collations.
+ *
+ * In the case of list partitioning, the indexes array stores one entry for
+ * every datum, which is the index of the partition that accepts a given datum.
+ * In case of range partitioning, it stores one entry per distinct range
+ * datum, which is the index of the partition for which a given datum
+ * is an upper bound. In the case of hash partitioning, the number of the
+ * entries in the indexes array is same as the greatest modulus amongst all
+ * partitions. For a given partition key datum-tuple, the index of the
+ * partition which would accept that datum-tuple would be given by the entry
+ * pointed by remainder produced when hash value of the datum-tuple is divided
+ * by the greatest modulus.
+ */
+typedef struct PartitionBoundInfoData
+{
+ char strategy; /* hash, list or range? */
+ int ndatums; /* Length of the datums
following array */
+ Datum **datums;
+ PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
+ * NULL
for hash and list partitioned
+ *
tables */
+ int *indexes; /* Partition indexes */
+ int null_index; /* Index of the
null-accepting partition; -1
+ * if there
isn't one */
+ int default_index; /* Index of the default
partition; -1 if there
+ * isn't one */
+} PartitionBoundInfoData;
+
+typedef struct PartitionBoundInfoData *PartitionBoundInfo;
+
+#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
+#define partition_bound_has_default(bi) ((bi)->default_index != -1)
extern int get_hash_partition_greatest_modulus(PartitionBoundInfo b);
extern int partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation,
diff --git a/src/include/optimizer/partprune.h
b/src/include/optimizer/partprune.h
index 027016b32c..093ade24c3 100644
--- a/src/include/optimizer/partprune.h
+++ b/src/include/optimizer/partprune.h
@@ -14,8 +14,31 @@
#ifndef PARTPRUNE_H
#define PARTPRUNE_H
+#include "catalog/partition_internal.h"
#include "nodes/relation.h"
+/*
+ * PartitionPruneContext
+ *
+ * Information about a partitioned table needed to perform partition pruning.
+ */
+typedef struct PartitionPruneContext
+{
+ /* Partition key information */
+ char strategy;
+ int partnatts;
+ Oid *partopfamily;
+ Oid *partopcintype;
+ Oid *partcollation;
+ FmgrInfo *partsupfunc;
+
+ /* Number of partitions */
+ int nparts;
+
+ /* Partition boundary info */
+ PartitionBoundInfo boundinfo;
+} PartitionPruneContext;
+
extern Relids prune_append_rel_partitions(RelOptInfo *rel);
#endif /* PARTPRUNE_H */