]> granicus.if.org Git - postgresql/commitdiff
Minor preparatory refactoring for UPDATE row movement.
authorRobert Haas <rhaas@postgresql.org>
Thu, 4 Jan 2018 21:25:49 +0000 (16:25 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 4 Jan 2018 21:25:49 +0000 (16:25 -0500)
Generalize is_partition_attr to has_partition_attrs and make it
accessible from outside tablecmds.c.  Change map_partition_varattnos
to clarify that it can be used for mapping between any two relations
in a partitioning hierarchy, not just parent -> child.

Amit Khandekar, reviewed by Amit Langote, David Rowley, and me.
Some comment changes by me.

Discussion: http://postgr.es/m/CAJ3gD9fWfxgKC+PfJZF3hkgAcNOy-LpfPxVYitDEXKHjeieWQQ@mail.gmail.com

src/backend/catalog/partition.c
src/backend/commands/tablecmds.c
src/include/catalog/partition.h

index ac9a2bda2ed17cae32790f4c5584b57a81894eb2..8adc4ee9771cea886cebc01c2560bc7dbe97095a 100644 (file)
@@ -1446,10 +1446,13 @@ get_qual_from_partbound(Relation rel, Relation parent,
 
 /*
  * map_partition_varattnos - maps varattno of any Vars in expr from the
- * parent attno to partition attno.
+ * attno's of 'from_rel' to the attno's of 'to_rel' partition, each of which
+ * may be either a leaf partition or a partitioned table, but both of which
+ * must be from the same partitioning hierarchy.
  *
- * We must allow for cases where physical attnos of a partition can be
- * different from the parent's.
+ * Even though all of the same column names must be present in all relations
+ * in the hierarchy, and they must also have the same types, the attnos may
+ * be different.
  *
  * If found_whole_row is not NULL, *found_whole_row returns whether a
  * whole-row variable was found in the input expression.
@@ -1459,8 +1462,8 @@ get_qual_from_partbound(Relation rel, Relation parent,
  * are working on Lists, so it's less messy to do the casts internally.
  */
 List *
-map_partition_varattnos(List *expr, int target_varno,
-                                               Relation partrel, Relation parent,
+map_partition_varattnos(List *expr, int fromrel_varno,
+                                               Relation to_rel, Relation from_rel,
                                                bool *found_whole_row)
 {
        bool            my_found_whole_row = false;
@@ -1469,14 +1472,14 @@ map_partition_varattnos(List *expr, int target_varno,
        {
                AttrNumber *part_attnos;
 
-               part_attnos = convert_tuples_by_name_map(RelationGetDescr(partrel),
-                                                                                                RelationGetDescr(parent),
+               part_attnos = convert_tuples_by_name_map(RelationGetDescr(to_rel),
+                                                                                                RelationGetDescr(from_rel),
                                                                                                 gettext_noop("could not convert row type"));
                expr = (List *) map_variable_attnos((Node *) expr,
-                                                                                       target_varno, 0,
+                                                                                       fromrel_varno, 0,
                                                                                        part_attnos,
-                                                                                       RelationGetDescr(parent)->natts,
-                                                                                       RelationGetForm(partrel)->reltype,
+                                                                                       RelationGetDescr(from_rel)->natts,
+                                                                                       RelationGetForm(to_rel)->reltype,
                                                                                        &my_found_whole_row);
        }
 
@@ -2598,6 +2601,70 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
        return part_index;
 }
 
+/*
+ * Checks if any of the 'attnums' is a partition key attribute for rel
+ *
+ * Sets *used_in_expr if any of the 'attnums' is found to be referenced in some
+ * partition key expression.  It's possible for a column to be both used
+ * directly and as part of an expression; if that happens, *used_in_expr may
+ * end up as either true or false.  That's OK for current uses of this
+ * function, because *used_in_expr is only used to tailor the error message
+ * text.
+ */
+bool
+has_partition_attrs(Relation rel, Bitmapset *attnums,
+                                       bool *used_in_expr)
+{
+       PartitionKey key;
+       int                     partnatts;
+       List       *partexprs;
+       ListCell   *partexprs_item;
+       int                     i;
+
+       if (attnums == NULL || rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+               return false;
+
+       key = RelationGetPartitionKey(rel);
+       partnatts = get_partition_natts(key);
+       partexprs = get_partition_exprs(key);
+
+       partexprs_item = list_head(partexprs);
+       for (i = 0; i < partnatts; i++)
+       {
+               AttrNumber      partattno = get_partition_col_attnum(key, i);
+
+               if (partattno != 0)
+               {
+                       if (bms_is_member(partattno - FirstLowInvalidHeapAttributeNumber,
+                                                         attnums))
+                       {
+                               if (used_in_expr)
+                                       *used_in_expr = false;
+                               return true;
+                       }
+               }
+               else
+               {
+                       /* Arbitrary expression */
+                       Node       *expr = (Node *) lfirst(partexprs_item);
+                       Bitmapset  *expr_attrs = NULL;
+
+                       /* Find all attributes referenced */
+                       pull_varattnos(expr, 1, &expr_attrs);
+                       partexprs_item = lnext(partexprs_item);
+
+                       if (bms_overlap(attnums, expr_attrs))
+                       {
+                               if (used_in_expr)
+                                       *used_in_expr = true;
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
 /*
  * qsort_partition_hbound_cmp
  *
index 62cf81e95a5e9c00deabdc7b5e7da6e8cb44d0a3..f2a928b823a2a9fdc74f5b3457a36e0d67420ce7 100644 (file)
@@ -468,7 +468,6 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
                                                                Oid oldRelOid, void *arg);
 static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
                                                                 Oid oldrelid, void *arg);
-static bool is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr);
 static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
 static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
                                          List **partexprs, Oid *partopclass, Oid *partcollation, char strategy);
@@ -6491,68 +6490,6 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
                cmd->subtype = AT_DropColumnRecurse;
 }
 
-/*
- * Checks if attnum is a partition attribute for rel
- *
- * Sets *used_in_expr if attnum is found to be referenced in some partition
- * key expression.  It's possible for a column to be both used directly and
- * as part of an expression; if that happens, *used_in_expr may end up as
- * either true or false.  That's OK for current uses of this function, because
- * *used_in_expr is only used to tailor the error message text.
- */
-static bool
-is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr)
-{
-       PartitionKey key;
-       int                     partnatts;
-       List       *partexprs;
-       ListCell   *partexprs_item;
-       int                     i;
-
-       if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
-               return false;
-
-       key = RelationGetPartitionKey(rel);
-       partnatts = get_partition_natts(key);
-       partexprs = get_partition_exprs(key);
-
-       partexprs_item = list_head(partexprs);
-       for (i = 0; i < partnatts; i++)
-       {
-               AttrNumber      partattno = get_partition_col_attnum(key, i);
-
-               if (partattno != 0)
-               {
-                       if (attnum == partattno)
-                       {
-                               if (used_in_expr)
-                                       *used_in_expr = false;
-                               return true;
-                       }
-               }
-               else
-               {
-                       /* Arbitrary expression */
-                       Node       *expr = (Node *) lfirst(partexprs_item);
-                       Bitmapset  *expr_attrs = NULL;
-
-                       /* Find all attributes referenced */
-                       pull_varattnos(expr, 1, &expr_attrs);
-                       partexprs_item = lnext(partexprs_item);
-
-                       if (bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber,
-                                                         expr_attrs))
-                       {
-                               if (used_in_expr)
-                                       *used_in_expr = true;
-                               return true;
-                       }
-               }
-       }
-
-       return false;
-}
-
 /*
  * Return value is the address of the dropped column.
  */
@@ -6613,7 +6550,9 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
                                                colName)));
 
        /* Don't drop columns used in the partition key */
-       if (is_partition_attr(rel, attnum, &is_expr))
+       if (has_partition_attrs(rel,
+                                                       bms_make_singleton(attnum - FirstLowInvalidHeapAttributeNumber),
+                                                       &is_expr))
        {
                if (!is_expr)
                        ereport(ERROR,
@@ -8837,7 +8776,9 @@ ATPrepAlterColumnType(List **wqueue,
                                                colName)));
 
        /* Don't alter columns used in the partition key */
-       if (is_partition_attr(rel, attnum, &is_expr))
+       if (has_partition_attrs(rel,
+                                                       bms_make_singleton(attnum - FirstLowInvalidHeapAttributeNumber),
+                                                       &is_expr))
        {
                if (!is_expr)
                        ereport(ERROR,
index ea0f549c9a4cfb7bd0a46af69dc2f2b28edfba68..2faf0ca26e9a361ac6b60b1a8f9e75abacecedf5 100644 (file)
@@ -54,11 +54,13 @@ extern void check_new_partition_bound(char *relname, Relation parent,
 extern Oid     get_partition_parent(Oid relid);
 extern List *get_qual_from_partbound(Relation rel, Relation parent,
                                                PartitionBoundSpec *spec);
-extern List *map_partition_varattnos(List *expr, int target_varno,
-                                               Relation partrel, Relation parent,
+extern List *map_partition_varattnos(List *expr, int fromrel_varno,
+                                               Relation to_rel, Relation from_rel,
                                                bool *found_whole_row);
 extern List *RelationGetPartitionQual(Relation rel);
 extern Expr *get_partition_qual_relid(Oid relid);
+extern bool has_partition_attrs(Relation rel, Bitmapset *attnums,
+                                       bool *used_in_expr);
 
 extern Oid     get_default_oid_from_partdesc(PartitionDesc partdesc);
 extern Oid     get_default_partition_oid(Oid parentId);