* and output columns by name. (Dropped columns are ignored in both input and
* output.) This is normally a subroutine for convert_tuples_by_name in
* tupconvert.c, but can be used standalone.
+ *
+ * If 'missing_ok' is true, a column from 'outdesc' not being present in
+ * 'indesc' is not flagged as an error; AttrMap.attnums[] entry for such an
+ * outdesc column will be 0 in that case.
*/
AttrMap *
build_attrmap_by_name(TupleDesc indesc,
- TupleDesc outdesc)
+ TupleDesc outdesc,
+ bool missing_ok)
{
AttrMap *attrMap;
int outnatts;
break;
}
}
- if (attrMap->attnums[i] == 0)
+ if (attrMap->attnums[i] == 0 && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("could not convert row type"),
*/
AttrMap *
build_attrmap_by_name_if_req(TupleDesc indesc,
- TupleDesc outdesc)
+ TupleDesc outdesc,
+ bool missing_ok)
{
AttrMap *attrMap;
/* Verify compatibility and prepare attribute-number map */
- attrMap = build_attrmap_by_name(indesc, outdesc);
+ attrMap = build_attrmap_by_name(indesc, outdesc, missing_ok);
/* Check if the map has a one-to-one match */
if (check_attrmap_match(indesc, outdesc, attrMap))
int n = outdesc->natts;
/* Verify compatibility and prepare attribute-number map */
- attrMap = build_attrmap_by_name_if_req(indesc, outdesc);
+ attrMap = build_attrmap_by_name_if_req(indesc, outdesc, false);
if (attrMap == NULL)
{
bool found_whole_row;
part_attmap = build_attrmap_by_name(RelationGetDescr(to_rel),
- RelationGetDescr(from_rel));
+ RelationGetDescr(from_rel),
+ false);
expr = (List *) map_variable_attnos((Node *) expr,
fromrel_varno, 0,
part_attmap,
childidxs = RelationGetIndexList(childrel);
attmap =
build_attrmap_by_name(RelationGetDescr(childrel),
- parentDesc);
+ parentDesc,
+ false);
foreach(cell, childidxs)
{
}
attmap = build_attrmap_by_name(RelationGetDescr(rel),
- RelationGetDescr(parent));
+ RelationGetDescr(parent),
+ false);
idxstmt =
generateClonedIndexStmt(NULL, idxRel,
attmap, &constraintOid);
* definition to match the partition's column layout.
*/
map = build_attrmap_by_name_if_req(RelationGetDescr(partRel),
- RelationGetDescr(pkrel));
+ RelationGetDescr(pkrel),
+ false);
if (map)
{
mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks);
CheckTableNotInUse(partition, "ALTER TABLE");
attmap = build_attrmap_by_name(RelationGetDescr(partition),
- RelationGetDescr(rel));
+ RelationGetDescr(rel),
+ false);
for (int j = 0; j < numfks; j++)
mapped_fkattnum[j] = attmap->attnums[fkattnum[j] - 1];
trigrel = table_open(TriggerRelationId, RowExclusiveLock);
attmap = build_attrmap_by_name(RelationGetDescr(partitionRel),
- RelationGetDescr(parentRel));
+ RelationGetDescr(parentRel),
+ false);
foreach(cell, clone)
{
Oid constrOid = lfirst_oid(cell);
* different. This map is used to convert them.
*/
attmap = build_attrmap_by_name(RelationGetDescr(partRel),
- RelationGetDescr(parentRel));
+ RelationGetDescr(parentRel),
+ false);
partFKs = copyObject(RelationGetFKeyList(partRel));
cmd = copyObject(cmd);
attmap = build_attrmap_by_name(RelationGetDescr(childrel),
- RelationGetDescr(rel));
+ RelationGetDescr(rel),
+ false);
((ColumnDef *) cmd->def)->cooked_default =
map_variable_attnos(def->cooked_default,
1, 0,
/* construct an indexinfo to compare existing indexes against */
info = BuildIndexInfo(idxRel);
attmap = build_attrmap_by_name(RelationGetDescr(attachrel),
- RelationGetDescr(rel));
+ RelationGetDescr(rel),
+ false);
constraintOid = get_relation_idx_constraint_oid(RelationGetRelid(rel), idx);
/*
childInfo = BuildIndexInfo(partIdx);
parentInfo = BuildIndexInfo(parentIdx);
attmap = build_attrmap_by_name(RelationGetDescr(partTbl),
- RelationGetDescr(parentTbl));
+ RelationGetDescr(parentTbl),
+ false);
if (!CompareIndexInfo(childInfo, parentInfo,
partIdx->rd_indcollation,
parentIdx->rd_indcollation,
old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
/* a reverse map */
- map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc);
+ map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc, false);
/*
* Partition-specific slot's tupdesc can't be changed, so allocate a
tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = build_attrmap_by_name_if_req(orig_tupdesc,
- tupdesc);
+ tupdesc,
+ false);
/*
* Partition-specific slot's tupdesc can't be changed, so
tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = build_attrmap_by_name_if_req(old_tupdesc,
- tupdesc);
+ tupdesc,
+ false);
/*
* Partition-specific slot's tupdesc can't be changed, so
tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = build_attrmap_by_name_if_req(old_tupdesc,
- tupdesc);
+ tupdesc,
+ false);
/*
* Partition-specific slot's tupdesc can't be changed,
*/
part_attmap =
build_attrmap_by_name(RelationGetDescr(partrel),
- RelationGetDescr(firstResultRel));
+ RelationGetDescr(firstResultRel),
+ false);
wcoList = (List *)
map_variable_attnos((Node *) wcoList,
firstVarno, 0,
if (part_attmap == NULL)
part_attmap =
build_attrmap_by_name(RelationGetDescr(partrel),
- RelationGetDescr(firstResultRel));
+ RelationGetDescr(firstResultRel),
+ false);
returningList = (List *)
map_variable_attnos((Node *) returningList,
firstVarno, 0,
if (part_attmap == NULL)
part_attmap =
build_attrmap_by_name(RelationGetDescr(partrel),
- RelationGetDescr(firstResultRel));
+ RelationGetDescr(firstResultRel),
+ false);
onconflset = (List *)
map_variable_attnos((Node *) onconflset,
INNER_VAR, 0,
if (part_attmap == NULL)
part_attmap =
build_attrmap_by_name(RelationGetDescr(partrel),
- RelationGetDescr(firstResultRel));
+ RelationGetDescr(firstResultRel),
+ false);
if (unlikely(!leaf_part_rri->ri_projectNewInfoValid))
ExecInitMergeTupleSlots(mtstate, leaf_part_rri);
* routing.
*/
pd->tupmap = build_attrmap_by_name_if_req(RelationGetDescr(parent_pd->reldesc),
- tupdesc);
+ tupdesc,
+ false);
pd->tupslot = pd->tupmap ?
MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual) : NULL;
}
* have a failure since both tables are locked.
*/
attmap = build_attrmap_by_name(RelationGetDescr(childrel),
- tupleDesc);
+ tupleDesc,
+ false);
/*
* Process defaults, if required.
/* Map must live as long as the session does. */
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
- entry->attrmap = build_attrmap_by_name_if_req(indesc, outdesc);
+ entry->attrmap = build_attrmap_by_name_if_req(indesc, outdesc, false);
MemoryContextSwitchTo(oldctx);
RelationClose(ancestor);
/* Conversion routines to build mappings */
extern AttrMap *build_attrmap_by_name(TupleDesc indesc,
- TupleDesc outdesc);
+ TupleDesc outdesc,
+ bool missing_ok);
extern AttrMap *build_attrmap_by_name_if_req(TupleDesc indesc,
- TupleDesc outdesc);
+ TupleDesc outdesc,
+ bool missing_ok);
extern AttrMap *build_attrmap_by_position(TupleDesc indesc,
TupleDesc outdesc,
const char *msg);