0001_merge_v23e_onconflict_work.patch
application/octet-stream
Filename: 0001_merge_v23e_onconflict_work.patch
Type: application/octet-stream
Part: 1
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/heap.c | 1 | 1 |
| src/backend/catalog/partition.c | 45 | 17 |
| src/backend/commands/tablecmds.c | 9 | 6 |
| src/backend/executor/execPartition.c | 7 | 7 |
| src/backend/optimizer/prep/preptlist.c | 12 | 13 |
| src/backend/optimizer/prep/prepunion.c | 72 | 10 |
| src/include/catalog/partition.h | 1 | 1 |
| src/include/optimizer/prep.h | 10 | 0 |
commit 86580b5d2c9b75c356393340a41fb22ba7ca4203
Author: Pavan Deolasee <pavan.deolasee@gmail.com>
Date: Tue Mar 20 10:56:33 2018 +0530
Apply patch(es) from ON CONFLICT DO NOTHING work
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3d80ff9e5b..13489162df 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -1776,7 +1776,7 @@ heap_drop_with_catalog(Oid relid)
elog(ERROR, "cache lookup failed for relation %u", relid);
if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
{
- parentOid = get_partition_parent(relid);
+ parentOid = get_partition_parent(relid, false);
LockRelationOid(parentOid, AccessExclusiveLock);
/*
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 786c05df73..8dc73ae092 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -192,6 +192,7 @@ static int get_partition_bound_num_indexes(PartitionBoundInfo b);
static int get_greatest_modulus(PartitionBoundInfo b);
static uint64 compute_hash_value(int partnatts, FmgrInfo *partsupfunc,
Datum *values, bool *isnull);
+static Oid get_partition_parent_recurse(Relation inhRel, Oid relid, bool getroot);
/*
* RelationBuildPartitionDesc
@@ -1384,24 +1385,43 @@ check_default_allows_bound(Relation parent, Relation default_rel,
/*
* get_partition_parent
+ * Obtain direct parent or topmost ancestor of given relation
*
- * Returns inheritance parent of a partition by scanning pg_inherits
+ * Returns direct inheritance parent of a partition by scanning pg_inherits;
+ * or, if 'getroot' is true, the topmost parent in the inheritance hierarchy.
*
* Note: Because this function assumes that the relation whose OID is passed
* as an argument will have precisely one parent, it should only be called
* when it is known that the relation is a partition.
*/
Oid
-get_partition_parent(Oid relid)
+get_partition_parent(Oid relid, bool getroot)
+{
+ Relation inhRel;
+ Oid parentOid;
+
+ inhRel = heap_open(InheritsRelationId, AccessShareLock);
+
+ parentOid = get_partition_parent_recurse(inhRel, relid, getroot);
+ if (parentOid == InvalidOid)
+ elog(ERROR, "could not find parent of relation %u", relid);
+
+ heap_close(inhRel, AccessShareLock);
+
+ return parentOid;
+}
+
+/*
+ * get_partition_parent_recurse
+ * Recursive part of get_partition_parent
+ */
+static Oid
+get_partition_parent_recurse(Relation inhRel, Oid relid, bool getroot)
{
- Form_pg_inherits form;
- Relation catalogRelation;
SysScanDesc scan;
ScanKeyData key[2];
HeapTuple tuple;
- Oid result;
-
- catalogRelation = heap_open(InheritsRelationId, AccessShareLock);
+ Oid result = InvalidOid;
ScanKeyInit(&key[0],
Anum_pg_inherits_inhrelid,
@@ -1412,18 +1432,26 @@ get_partition_parent(Oid relid)
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(1));
- scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
+ /* Obtain the direct parent, and release resources before recursing */
+ scan = systable_beginscan(inhRel, InheritsRelidSeqnoIndexId, true,
NULL, 2, key);
-
tuple = systable_getnext(scan);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "could not find tuple for parent of relation %u", relid);
-
- form = (Form_pg_inherits) GETSTRUCT(tuple);
- result = form->inhparent;
-
+ if (HeapTupleIsValid(tuple))
+ result = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
systable_endscan(scan);
- heap_close(catalogRelation, AccessShareLock);
+
+ /*
+ * If we were asked to recurse, do so now. Except that if we didn't get a
+ * valid parent, then the 'relid' argument was already the topmost parent,
+ * so return that.
+ */
+ if (getroot)
+ {
+ if (OidIsValid(result))
+ return get_partition_parent_recurse(inhRel, result, getroot);
+ else
+ return relid;
+ }
return result;
}
@@ -2505,7 +2533,7 @@ generate_partition_qual(Relation rel)
return copyObject(rel->rd_partcheck);
/* Grab at least an AccessShareLock on the parent table */
- parent = heap_open(get_partition_parent(RelationGetRelid(rel)),
+ parent = heap_open(get_partition_parent(RelationGetRelid(rel), false),
AccessShareLock);
/* Get pg_class.relpartbound */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 218224a156..6003afdd03 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1292,7 +1292,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
*/
if (is_partition && relOid != oldRelOid)
{
- state->partParentOid = get_partition_parent(relOid);
+ state->partParentOid = get_partition_parent(relOid, false);
if (OidIsValid(state->partParentOid))
LockRelationOid(state->partParentOid, AccessExclusiveLock);
}
@@ -5843,7 +5843,8 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
/* If rel is partition, shouldn't drop NOT NULL if parent has the same */
if (rel->rd_rel->relispartition)
{
- Oid parentId = get_partition_parent(RelationGetRelid(rel));
+ Oid parentId = get_partition_parent(RelationGetRelid(rel),
+ false);
Relation parent = heap_open(parentId, AccessShareLock);
TupleDesc tupDesc = RelationGetDescr(parent);
AttrNumber parent_attnum;
@@ -14360,7 +14361,7 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
if (!has_superclass(idxid))
continue;
- Assert((IndexGetRelation(get_partition_parent(idxid), false) ==
+ Assert((IndexGetRelation(get_partition_parent(idxid, false), false) ==
RelationGetRelid(rel)));
idx = index_open(idxid, AccessExclusiveLock);
@@ -14489,7 +14490,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name)
/* Silently do nothing if already in the right state */
currParent = !has_superclass(partIdxId) ? InvalidOid :
- get_partition_parent(partIdxId);
+ get_partition_parent(partIdxId, false);
if (currParent != RelationGetRelid(parentIdx))
{
IndexInfo *childInfo;
@@ -14722,8 +14723,10 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl)
/* make sure we see the validation we just did */
CommandCounterIncrement();
- parentIdxId = get_partition_parent(RelationGetRelid(partedIdx));
- parentTblId = get_partition_parent(RelationGetRelid(partedTbl));
+ parentIdxId = get_partition_parent(RelationGetRelid(partedIdx),
+ false);
+ parentTblId = get_partition_parent(RelationGetRelid(partedTbl),
+ false);
parentIdx = relation_open(parentIdxId, AccessExclusiveLock);
parentTbl = relation_open(parentTblId, AccessExclusiveLock);
Assert(!parentIdx->rd_index->indisvalid);
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index ce9a4e16cf..4147121575 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -19,6 +19,7 @@
#include "executor/executor.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
+#include "optimizer/prep.h"
#include "utils/lsyscache.h"
#include "utils/rls.h"
#include "utils/ruleutils.h"
@@ -64,6 +65,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
int num_update_rri = 0,
update_rri_index = 0;
PartitionTupleRouting *proute;
+ int nparts;
/*
* Get the information about the partition tree after locking all the
@@ -74,14 +76,12 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
proute->partition_dispatch_info =
RelationGetPartitionDispatchInfo(rel, &proute->num_dispatch,
&leaf_parts);
- proute->num_partitions = list_length(leaf_parts);
- proute->partitions = (ResultRelInfo **) palloc(proute->num_partitions *
- sizeof(ResultRelInfo *));
+ proute->num_partitions = nparts = list_length(leaf_parts);
+ proute->partitions =
+ (ResultRelInfo **) palloc(nparts * sizeof(ResultRelInfo *));
proute->parent_child_tupconv_maps =
- (TupleConversionMap **) palloc0(proute->num_partitions *
- sizeof(TupleConversionMap *));
- proute->partition_oids = (Oid *) palloc(proute->num_partitions *
- sizeof(Oid));
+ (TupleConversionMap **) palloc0(nparts * sizeof(TupleConversionMap *));
+ proute->partition_oids = (Oid *) palloc(nparts * sizeof(Oid));
/* Set up details specific to the type of tuple routing we are doing. */
if (mtstate && mtstate->operation == CMD_UPDATE)
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 8603feef2b..e2995e6592 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -53,8 +53,6 @@
#include "utils/rel.h"
-static List *expand_targetlist(List *tlist, int command_type,
- Index result_relation, Relation rel);
/*
@@ -116,7 +114,8 @@ preprocess_targetlist(PlannerInfo *root)
tlist = parse->targetList;
if (command_type == CMD_INSERT || command_type == CMD_UPDATE)
tlist = expand_targetlist(tlist, command_type,
- result_relation, target_relation);
+ result_relation,
+ RelationGetDescr(target_relation));
/*
* Add necessary junk columns for rowmarked rels. These values are needed
@@ -230,7 +229,7 @@ preprocess_targetlist(PlannerInfo *root)
expand_targetlist(parse->onConflict->onConflictSet,
CMD_UPDATE,
result_relation,
- target_relation);
+ RelationGetDescr(target_relation));
if (target_relation)
heap_close(target_relation, NoLock);
@@ -247,13 +246,13 @@ preprocess_targetlist(PlannerInfo *root)
/*
* expand_targetlist
- * Given a target list as generated by the parser and a result relation,
- * add targetlist entries for any missing attributes, and ensure the
- * non-junk attributes appear in proper field order.
+ * Given a target list as generated by the parser and a result relation's
+ * tuple descriptor, add targetlist entries for any missing attributes, and
+ * ensure the non-junk attributes appear in proper field order.
*/
-static List *
+List *
expand_targetlist(List *tlist, int command_type,
- Index result_relation, Relation rel)
+ Index result_relation, TupleDesc tupdesc)
{
List *new_tlist = NIL;
ListCell *tlist_item;
@@ -266,14 +265,14 @@ expand_targetlist(List *tlist, int command_type,
* The rewriter should have already ensured that the TLEs are in correct
* order; but we have to insert TLEs for any missing attributes.
*
- * Scan the tuple description in the relation's relcache entry to make
- * sure we have all the user attributes in the right order.
+ * Scan the tuple description to make sure we have all the user attributes
+ * in the right order.
*/
- numattrs = RelationGetNumberOfAttributes(rel);
+ numattrs = tupdesc->natts;
for (attrno = 1; attrno <= numattrs; attrno++)
{
- Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1);
+ Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
TargetEntry *new_tle = NULL;
if (tlist_item != NULL)
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index f087369f75..8bba97be74 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -112,8 +112,9 @@ static void expand_single_inheritance_child(PlannerInfo *root,
PlanRowMark *top_parentrc, Relation childrel,
List **appinfos, RangeTblEntry **childrte_p,
Index *childRTindex_p);
-static void make_inh_translation_list(Relation oldrelation,
- Relation newrelation,
+static void make_inh_translation_list(TupleDesc old_tupdesc,
+ TupleDesc new_tupdesc,
+ char *new_rel_name,
Index newvarno,
List **translated_vars);
static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
@@ -1764,7 +1765,10 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
appinfo->child_relid = childRTindex;
appinfo->parent_reltype = parentrel->rd_rel->reltype;
appinfo->child_reltype = childrel->rd_rel->reltype;
- make_inh_translation_list(parentrel, childrel, childRTindex,
+ make_inh_translation_list(RelationGetDescr(parentrel),
+ RelationGetDescr(childrel),
+ RelationGetRelationName(childrel),
+ childRTindex,
&appinfo->translated_vars);
appinfo->parent_reloid = parentOID;
*appinfos = lappend(*appinfos, appinfo);
@@ -1828,16 +1832,18 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
* For paranoia's sake, we match type/collation as well as attribute name.
*/
static void
-make_inh_translation_list(Relation oldrelation, Relation newrelation,
+make_inh_translation_list(TupleDesc old_tupdesc, TupleDesc new_tupdesc,
+ char *new_rel_name,
Index newvarno,
List **translated_vars)
{
List *vars = NIL;
- TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
- TupleDesc new_tupdesc = RelationGetDescr(newrelation);
int oldnatts = old_tupdesc->natts;
int newnatts = new_tupdesc->natts;
int old_attno;
+ bool equal_tupdescs;
+
+ equal_tupdescs = equalTupleDescs(old_tupdesc, new_tupdesc);
for (old_attno = 0; old_attno < oldnatts; old_attno++)
{
@@ -1864,7 +1870,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
* When we are generating the "translation list" for the parent table
* of an inheritance set, no need to search for matches.
*/
- if (oldrelation == newrelation)
+ if (equal_tupdescs)
{
vars = lappend(vars, makeVar(newvarno,
(AttrNumber) (old_attno + 1),
@@ -1901,16 +1907,16 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
}
if (new_attno >= newnatts)
elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
- attname, RelationGetRelationName(newrelation));
+ attname, new_rel_name);
}
/* Found it, check type and collation match */
if (atttypid != att->atttypid || atttypmod != att->atttypmod)
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
- attname, RelationGetRelationName(newrelation));
+ attname, new_rel_name);
if (attcollation != att->attcollation)
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
- attname, RelationGetRelationName(newrelation));
+ attname, new_rel_name);
vars = lappend(vars, makeVar(newvarno,
(AttrNumber) (new_attno + 1),
@@ -2408,6 +2414,15 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
if (tle->resjunk)
continue; /* ignore junk items */
+ /*
+ * XXX ugly hack: must ignore dummy tlist entry added by
+ * expand_targetlist() for dropped columns in the parent table or we
+ * fail because there is no translation. Must find a better way to
+ * deal with this case, though.
+ */
+ if (IsA(tle->expr, Const) && ((Const *) tle->expr)->constisnull)
+ continue;
+
/* Look up the translation of this column: it must be a Var */
if (tle->resno <= 0 ||
tle->resno > list_length(context->translated_vars))
@@ -2446,6 +2461,10 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
if (tle->resjunk)
continue; /* ignore junk items */
+ /* XXX ugly hack; see above */
+ if (IsA(tle->expr, Const) && ((Const *) tle->expr)->constisnull)
+ continue;
+
if (tle->resno == attrno)
new_tlist = lappend(new_tlist, tle);
else if (tle->resno > attrno)
@@ -2460,6 +2479,10 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
if (!tle->resjunk)
continue; /* here, ignore non-junk items */
+ /* XXX ugly hack; see above */
+ if (IsA(tle->expr, Const) && ((Const *) tle->expr)->constisnull)
+ continue;
+
tle->resno = attrno;
new_tlist = lappend(new_tlist, tle);
attrno++;
@@ -2468,6 +2491,45 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
return new_tlist;
}
+/*
+ * Given a targetlist for the parentRel of the given varno, adjust it to be in
+ * the correct order and to contain all the needed elements for the given
+ * partition.
+ */
+List *
+adjust_and_expand_partition_tlist(TupleDesc parentDesc,
+ TupleDesc partitionDesc,
+ char *partitionRelname,
+ int parentVarno,
+ List *targetlist)
+{
+ AppendRelInfo appinfo;
+ List *result_tl;
+
+ /*
+ * Fist, fix the target entries' resnos, by using inheritance translation.
+ */
+ appinfo.type = T_AppendRelInfo;
+ appinfo.parent_relid = parentVarno;
+ appinfo.parent_reltype = InvalidOid; // parentRel->rd_rel->reltype;
+ appinfo.child_relid = -1;
+ appinfo.child_reltype = InvalidOid; // partrel->rd_rel->reltype;
+ appinfo.parent_reloid = 1; // dummy parentRel->rd_id;
+ make_inh_translation_list(parentDesc, partitionDesc, partitionRelname,
+ 1, /* dummy */
+ &appinfo.translated_vars);
+ result_tl = adjust_inherited_tlist((List *) targetlist, &appinfo);
+
+ /*
+ * Add any attributes that are missing in the source list, such
+ * as dropped columns in the partition.
+ */
+ result_tl = expand_targetlist(result_tl, CMD_UPDATE,
+ parentVarno, partitionDesc);
+
+ return result_tl;
+}
+
/*
* adjust_appendrel_attrs_multilevel
* Apply Var translations from a toplevel appendrel parent down to a child.
diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h
index 2faf0ca26e..70ddb225a1 100644
--- a/src/include/catalog/partition.h
+++ b/src/include/catalog/partition.h
@@ -51,7 +51,7 @@ extern PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src,
extern void check_new_partition_bound(char *relname, Relation parent,
PartitionBoundSpec *spec);
-extern Oid get_partition_parent(Oid relid);
+extern Oid get_partition_parent(Oid relid, bool getroot);
extern List *get_qual_from_partbound(Relation rel, Relation parent,
PartitionBoundSpec *spec);
extern List *map_partition_varattnos(List *expr, int fromrel_varno,
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 38608770a2..7074bae79a 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.h
@@ -14,6 +14,7 @@
#ifndef PREP_H
#define PREP_H
+#include "access/tupdesc.h"
#include "nodes/plannodes.h"
#include "nodes/relation.h"
@@ -42,6 +43,9 @@ extern List *preprocess_targetlist(PlannerInfo *root);
extern PlanRowMark *get_plan_rowmark(List *rowmarks, Index rtindex);
+extern List *expand_targetlist(List *tlist, int command_type,
+ Index result_relation, TupleDesc tupdesc);
+
/*
* prototypes for prepunion.c
*/
@@ -65,4 +69,10 @@ extern SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
extern Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
Relids child_relids, Relids top_parent_relids);
+extern List *adjust_and_expand_partition_tlist(TupleDesc parentDesc,
+ TupleDesc partitionDesc,
+ char *partitionRelname,
+ int parentVarno,
+ List *targetlist);
+
#endif /* PREP_H */