diff options
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/inherit.c | 97 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 56 |
2 files changed, 145 insertions, 8 deletions
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c index 6dbffe121a5..3c11f5db5ad 100644 --- a/src/backend/optimizer/util/inherit.c +++ b/src/backend/optimizer/util/inherit.c @@ -25,6 +25,7 @@ #include "optimizer/inherit.h" #include "optimizer/optimizer.h" #include "optimizer/pathnode.h" +#include "optimizer/plancat.h" #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/prep.h" @@ -47,6 +48,10 @@ static void expand_single_inheritance_child(PlannerInfo *root, Index *childRTindex_p); static Bitmapset *translate_col_privs(const Bitmapset *parent_privs, List *translated_vars); +static Bitmapset *translate_col_privs_multilevel(PlannerInfo *root, + RelOptInfo *rel, + RelOptInfo *parent_rel, + Bitmapset *parent_cols); static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti); @@ -333,11 +338,6 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, root->partColsUpdated = has_partition_attrs(parentrel, parentrte->updatedCols, NULL); - /* - * There shouldn't be any generated columns in the partition key. - */ - Assert(!has_partition_attrs(parentrel, parentrte->extraUpdatedCols, NULL)); - /* Nothing further to do here if there are no partitions. */ if (partdesc->nparts == 0) return; @@ -556,15 +556,12 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, appinfo->translated_vars); childrte->updatedCols = translate_col_privs(parentrte->updatedCols, appinfo->translated_vars); - childrte->extraUpdatedCols = translate_col_privs(parentrte->extraUpdatedCols, - appinfo->translated_vars); } else { childrte->selectedCols = bms_copy(parentrte->selectedCols); childrte->insertedCols = bms_copy(parentrte->insertedCols); childrte->updatedCols = bms_copy(parentrte->updatedCols); - childrte->extraUpdatedCols = bms_copy(parentrte->extraUpdatedCols); } /* @@ -649,6 +646,52 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, } /* + * get_rel_all_updated_cols + * Returns the set of columns of a given "simple" relation that are + * updated by this query. + */ +Bitmapset * +get_rel_all_updated_cols(PlannerInfo *root, RelOptInfo *rel) +{ + Index relid; + RangeTblEntry *rte; + Bitmapset *updatedCols, + *extraUpdatedCols; + + Assert(root->parse->commandType == CMD_UPDATE); + Assert(IS_SIMPLE_REL(rel)); + + /* + * We obtain updatedCols for the query's result relation. Then, if + * necessary, we map it to the column numbers of the relation for which + * they were requested. + */ + relid = root->parse->resultRelation; + rte = planner_rt_fetch(relid, root); + + updatedCols = rte->updatedCols; + + if (rel->relid != relid) + { + RelOptInfo *top_parent_rel = find_base_rel(root, relid); + + Assert(IS_OTHER_REL(rel)); + + updatedCols = translate_col_privs_multilevel(root, rel, top_parent_rel, + updatedCols); + } + + /* + * Now we must check to see if there are any generated columns that depend + * on the updatedCols, and add them to the result. + */ + extraUpdatedCols = get_dependent_generated_columns(root, rel->relid, + updatedCols); + + return bms_union(updatedCols, extraUpdatedCols); +} + +/* * translate_col_privs * Translate a bitmapset representing per-column privileges from the * parent rel's attribute numbering to the child's. @@ -701,6 +744,44 @@ translate_col_privs(const Bitmapset *parent_privs, } /* + * translate_col_privs_multilevel + * Recursively translates the column numbers contained in 'parent_cols' + * to the column numbers of a descendant relation given by 'rel' + * + * Note that because this is based on translate_col_privs, it will expand + * a whole-row reference into all inherited columns. This is not an issue + * for current usages, but beware. + */ +static Bitmapset * +translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel, + RelOptInfo *parent_rel, + Bitmapset *parent_cols) +{ + AppendRelInfo *appinfo; + + /* Fast path for easy case. */ + if (parent_cols == NULL) + return NULL; + + Assert(root->append_rel_array != NULL); + appinfo = root->append_rel_array[rel->relid]; + Assert(appinfo != NULL); + + /* Recurse if immediate parent is not the top parent. */ + if (appinfo->parent_relid != parent_rel->relid) + { + RelOptInfo *next_parent = find_base_rel(root, appinfo->parent_relid); + + parent_cols = translate_col_privs_multilevel(root, next_parent, + parent_rel, + parent_cols); + } + + /* Now translate for this child. */ + return translate_col_privs(parent_cols, appinfo->translated_vars); +} + +/* * expand_appendrel_subquery * Add "other rel" RelOptInfos for the children of an appendrel baserel * diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c328a2f9129..419f2ac55fa 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -2198,6 +2198,11 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event) return result; } +/* + * has_stored_generated_columns + * + * Does table identified by RTI have any STORED GENERATED columns? + */ bool has_stored_generated_columns(PlannerInfo *root, Index rti) { @@ -2218,6 +2223,57 @@ has_stored_generated_columns(PlannerInfo *root, Index rti) } /* + * get_dependent_generated_columns + * + * Get the column numbers of any STORED GENERATED columns of the relation + * that depend on any column listed in target_cols. Both the input and + * result bitmapsets contain column numbers offset by + * FirstLowInvalidHeapAttributeNumber. + */ +Bitmapset * +get_dependent_generated_columns(PlannerInfo *root, Index rti, + Bitmapset *target_cols) +{ + Bitmapset *dependentCols = NULL; + RangeTblEntry *rte = planner_rt_fetch(rti, root); + Relation relation; + TupleDesc tupdesc; + TupleConstr *constr; + + /* Assume we already have adequate lock */ + relation = table_open(rte->relid, NoLock); + + tupdesc = RelationGetDescr(relation); + constr = tupdesc->constr; + + if (constr && constr->has_generated_stored) + { + for (int i = 0; i < constr->num_defval; i++) + { + AttrDefault *defval = &constr->defval[i]; + Node *expr; + Bitmapset *attrs_used = NULL; + + /* skip if not generated column */ + if (!TupleDescAttr(tupdesc, defval->adnum - 1)->attgenerated) + continue; + + /* identify columns this generated column depends on */ + expr = stringToNode(defval->adbin); + pull_varattnos(expr, 1, &attrs_used); + + if (bms_overlap(target_cols, attrs_used)) + dependentCols = bms_add_member(dependentCols, + defval->adnum - FirstLowInvalidHeapAttributeNumber); + } + } + + table_close(relation, NoLock); + + return dependentCols; +} + +/* * set_relation_partition_info * * Set partitioning scheme and related information for a partitioned table. |