mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
Minor preparatory refactoring for UPDATE row movement.
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
This commit is contained in:
parent
ac3ff8b1d8
commit
ef6087ee5f
@ -1446,10 +1446,13 @@ get_qual_from_partbound(Relation rel, Relation parent,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* map_partition_varattnos - maps varattno of any Vars in expr from the
|
* 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
|
* Even though all of the same column names must be present in all relations
|
||||||
* different from the parent's.
|
* 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
|
* If found_whole_row is not NULL, *found_whole_row returns whether a
|
||||||
* whole-row variable was found in the input expression.
|
* 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.
|
* are working on Lists, so it's less messy to do the casts internally.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
map_partition_varattnos(List *expr, int target_varno,
|
map_partition_varattnos(List *expr, int fromrel_varno,
|
||||||
Relation partrel, Relation parent,
|
Relation to_rel, Relation from_rel,
|
||||||
bool *found_whole_row)
|
bool *found_whole_row)
|
||||||
{
|
{
|
||||||
bool my_found_whole_row = false;
|
bool my_found_whole_row = false;
|
||||||
@ -1469,14 +1472,14 @@ map_partition_varattnos(List *expr, int target_varno,
|
|||||||
{
|
{
|
||||||
AttrNumber *part_attnos;
|
AttrNumber *part_attnos;
|
||||||
|
|
||||||
part_attnos = convert_tuples_by_name_map(RelationGetDescr(partrel),
|
part_attnos = convert_tuples_by_name_map(RelationGetDescr(to_rel),
|
||||||
RelationGetDescr(parent),
|
RelationGetDescr(from_rel),
|
||||||
gettext_noop("could not convert row type"));
|
gettext_noop("could not convert row type"));
|
||||||
expr = (List *) map_variable_attnos((Node *) expr,
|
expr = (List *) map_variable_attnos((Node *) expr,
|
||||||
target_varno, 0,
|
fromrel_varno, 0,
|
||||||
part_attnos,
|
part_attnos,
|
||||||
RelationGetDescr(parent)->natts,
|
RelationGetDescr(from_rel)->natts,
|
||||||
RelationGetForm(partrel)->reltype,
|
RelationGetForm(to_rel)->reltype,
|
||||||
&my_found_whole_row);
|
&my_found_whole_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2598,6 +2601,70 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
|
|||||||
return part_index;
|
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
|
* qsort_partition_hbound_cmp
|
||||||
*
|
*
|
||||||
|
@ -468,7 +468,6 @@ static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
|
|||||||
Oid oldRelOid, void *arg);
|
Oid oldRelOid, void *arg);
|
||||||
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
|
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
|
||||||
Oid oldrelid, void *arg);
|
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 PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
|
||||||
static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
|
static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
|
||||||
List **partexprs, Oid *partopclass, Oid *partcollation, char strategy);
|
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;
|
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.
|
* Return value is the address of the dropped column.
|
||||||
*/
|
*/
|
||||||
@ -6613,7 +6550,9 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
|
|||||||
colName)));
|
colName)));
|
||||||
|
|
||||||
/* Don't drop columns used in the partition key */
|
/* 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)
|
if (!is_expr)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -8837,7 +8776,9 @@ ATPrepAlterColumnType(List **wqueue,
|
|||||||
colName)));
|
colName)));
|
||||||
|
|
||||||
/* Don't alter columns used in the partition key */
|
/* 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)
|
if (!is_expr)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
|
@ -54,11 +54,13 @@ extern void check_new_partition_bound(char *relname, Relation parent,
|
|||||||
extern Oid get_partition_parent(Oid relid);
|
extern Oid get_partition_parent(Oid relid);
|
||||||
extern List *get_qual_from_partbound(Relation rel, Relation parent,
|
extern List *get_qual_from_partbound(Relation rel, Relation parent,
|
||||||
PartitionBoundSpec *spec);
|
PartitionBoundSpec *spec);
|
||||||
extern List *map_partition_varattnos(List *expr, int target_varno,
|
extern List *map_partition_varattnos(List *expr, int fromrel_varno,
|
||||||
Relation partrel, Relation parent,
|
Relation to_rel, Relation from_rel,
|
||||||
bool *found_whole_row);
|
bool *found_whole_row);
|
||||||
extern List *RelationGetPartitionQual(Relation rel);
|
extern List *RelationGetPartitionQual(Relation rel);
|
||||||
extern Expr *get_partition_qual_relid(Oid relid);
|
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_oid_from_partdesc(PartitionDesc partdesc);
|
||||||
extern Oid get_default_partition_oid(Oid parentId);
|
extern Oid get_default_partition_oid(Oid parentId);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user