From 48f8b82974fd36d807b524abbb7b8d605a50ca94 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 21 Nov 2019 13:23:16 +0900 Subject: [PATCH v1] Rework attribute mappings --- src/backend/access/common/Makefile | 1 + src/backend/access/common/attmap.c | 51 ++++++++++++++++ src/backend/access/common/tupconvert.c | 61 ++++++++++--------- src/backend/catalog/index.c | 10 ++-- src/backend/catalog/partition.c | 7 +-- src/backend/commands/indexcmds.c | 12 ++-- src/backend/commands/tablecmds.c | 69 +++++++++++----------- src/backend/executor/execMain.c | 8 +-- src/backend/executor/execPartition.c | 41 ++++++------- src/backend/parser/parse_utilcmd.c | 18 +++--- src/backend/replication/logical/relation.c | 10 ++-- src/backend/replication/logical/worker.c | 9 ++- src/backend/rewrite/rewriteManip.c | 12 ++-- src/include/access/attmap.h | 42 +++++++++++++ src/include/access/tupconvert.h | 16 ++--- src/include/catalog/index.h | 2 +- src/include/parser/parse_utilcmd.h | 3 +- src/include/replication/logicalrelation.h | 2 +- src/include/rewrite/rewriteManip.h | 3 +- 19 files changed, 236 insertions(+), 141 deletions(-) create mode 100644 src/backend/access/common/attmap.c create mode 100644 src/include/access/attmap.h diff --git a/src/backend/access/common/Makefile b/src/backend/access/common/Makefile index 6c9c6f3256..fd74e14024 100644 --- a/src/backend/access/common/Makefile +++ b/src/backend/access/common/Makefile @@ -13,6 +13,7 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = \ + attmap.o \ bufmask.o \ detoast.o \ heaptuple.o \ diff --git a/src/backend/access/common/attmap.c b/src/backend/access/common/attmap.c new file mode 100644 index 0000000000..06df1dcfa4 --- /dev/null +++ b/src/backend/access/common/attmap.c @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------- + * + * attmap.c + * Attribute mapping support. + * + * This file provides utility routines to build and managed attribute + * mappings which are used when working on inheritance and partition trees + * for cloned object creation or tuple attribute comparison for runtime + * operations. + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/access/common/attmap.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/attmap.h" + +/* + * make_attrmap + * + * Utility routine to allocate an attribute map in the current memory + * context. + */ +AttrMap * +make_attrmap(int maplen) +{ + AttrMap *res; + + res = (AttrMap *) palloc0(sizeof(AttrMap)); + res->maplen = maplen; + res->attnums = (AttrNumber *) palloc0(sizeof(AttrNumber) * maplen); + return res; +} + +/* + * free_attrmap + * + * Utility routine to release an attribute map. + */ +void +free_attrmap(AttrMap *map) +{ + pfree(map->attnums); + pfree(map); +} diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c index 0ec9cd5870..94b90d6115 100644 --- a/src/backend/access/common/tupconvert.c +++ b/src/backend/access/common/tupconvert.c @@ -67,7 +67,7 @@ convert_tuples_by_position(TupleDesc indesc, const char *msg) { TupleConversionMap *map; - AttrNumber *attrMap; + AttrMap *attrMap; int nincols; int noutcols; int n; @@ -77,7 +77,13 @@ convert_tuples_by_position(TupleDesc indesc, /* Verify compatibility and prepare attribute-number map */ n = outdesc->natts; - attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber)); + + /* + * The length is computed as the number of attributes of the expected + * rowtype as it includes dropped attributes in its count. + */ + attrMap = make_attrmap(n); + j = 0; /* j is next physical input attribute */ nincols = noutcols = 0; /* these count non-dropped attributes */ same = true; @@ -88,7 +94,7 @@ convert_tuples_by_position(TupleDesc indesc, int32 atttypmod; if (att->attisdropped) - continue; /* attrMap[i] is already 0 */ + continue; /* attrMap->attnums[i] is already 0 */ noutcols++; atttypid = att->atttypid; atttypmod = att->atttypmod; @@ -110,11 +116,11 @@ convert_tuples_by_position(TupleDesc indesc, format_type_with_typemod(atttypid, atttypmod), noutcols))); - attrMap[i] = (AttrNumber) (j + 1); + attrMap->attnums[i] = (AttrNumber) (j + 1); j++; break; } - if (attrMap[i] == 0) + if (attrMap->attnums[i] == 0) same = false; /* we'll complain below */ } @@ -147,7 +153,7 @@ convert_tuples_by_position(TupleDesc indesc, Form_pg_attribute inatt; Form_pg_attribute outatt; - if (attrMap[i] == (i + 1)) + if (attrMap->attnums[i] == (i + 1)) continue; /* @@ -157,7 +163,7 @@ convert_tuples_by_position(TupleDesc indesc, */ inatt = TupleDescAttr(indesc, i); outatt = TupleDescAttr(outdesc, i); - if (attrMap[i] == 0 && + if (attrMap->attnums[i] == 0 && inatt->attisdropped && inatt->attlen == outatt->attlen && inatt->attalign == outatt->attalign) @@ -173,7 +179,7 @@ convert_tuples_by_position(TupleDesc indesc, if (same) { /* Runtime conversion is not needed */ - pfree(attrMap); + free_attrmap(attrMap); return NULL; } @@ -206,7 +212,7 @@ convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc) { TupleConversionMap *map; - AttrNumber *attrMap; + AttrMap *attrMap; int n = outdesc->natts; /* Verify compatibility and prepare attribute-number map */ @@ -241,11 +247,11 @@ convert_tuples_by_name(TupleDesc indesc, * output.) This is normally a subroutine for convert_tuples_by_name, but can * be used standalone. */ -AttrNumber * +AttrMap * convert_tuples_by_name_map(TupleDesc indesc, TupleDesc outdesc) { - AttrNumber *attrMap; + AttrMap *attrMap; int outnatts; int innatts; int i; @@ -254,7 +260,7 @@ convert_tuples_by_name_map(TupleDesc indesc, outnatts = outdesc->natts; innatts = indesc->natts; - attrMap = (AttrNumber *) palloc0(outnatts * sizeof(AttrNumber)); + attrMap = make_attrmap(outnatts); for (i = 0; i < outnatts; i++) { Form_pg_attribute outatt = TupleDescAttr(outdesc, i); @@ -264,7 +270,7 @@ convert_tuples_by_name_map(TupleDesc indesc, int j; if (outatt->attisdropped) - continue; /* attrMap[i] is already 0 */ + continue; /* attrMap->attnums[i] is already 0 */ attname = NameStr(outatt->attname); atttypid = outatt->atttypid; atttypmod = outatt->atttypmod; @@ -302,11 +308,11 @@ convert_tuples_by_name_map(TupleDesc indesc, attname, format_type_be(outdesc->tdtypeid), format_type_be(indesc->tdtypeid)))); - attrMap[i] = inatt->attnum; + attrMap->attnums[i] = inatt->attnum; break; } } - if (attrMap[i] == 0) + if (attrMap->attnums[i] == 0) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("could not convert row type"), @@ -323,11 +329,11 @@ convert_tuples_by_name_map(TupleDesc indesc, * conversion not required. This is a convenience routine for * convert_tuples_by_name() and other functions. */ -AttrNumber * +AttrMap * convert_tuples_by_name_map_if_req(TupleDesc indesc, TupleDesc outdesc) { - AttrNumber *attrMap; + AttrMap *attrMap; int n = outdesc->natts; int i; bool same; @@ -347,7 +353,7 @@ convert_tuples_by_name_map_if_req(TupleDesc indesc, Form_pg_attribute inatt; Form_pg_attribute outatt; - if (attrMap[i] == (i + 1)) + if (attrMap->attnums[i] == (i + 1)) continue; /* @@ -357,7 +363,7 @@ convert_tuples_by_name_map_if_req(TupleDesc indesc, */ inatt = TupleDescAttr(indesc, i); outatt = TupleDescAttr(outdesc, i); - if (attrMap[i] == 0 && + if (attrMap->attnums[i] == 0 && inatt->attisdropped && inatt->attlen == outatt->attlen && inatt->attalign == outatt->attalign) @@ -373,7 +379,7 @@ convert_tuples_by_name_map_if_req(TupleDesc indesc, if (same) { /* Runtime conversion is not needed */ - pfree(attrMap); + free_attrmap(attrMap); return NULL; } else @@ -386,7 +392,7 @@ convert_tuples_by_name_map_if_req(TupleDesc indesc, HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map) { - AttrNumber *attrMap = map->attrMap; + AttrMap *attrMap = map->attrMap; Datum *invalues = map->invalues; bool *inisnull = map->inisnull; Datum *outvalues = map->outvalues; @@ -404,9 +410,10 @@ execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map) /* * Transpose into proper fields of the new tuple. */ - for (i = 0; i < outnatts; i++) + Assert(attrMap->maplen == outnatts); + for (i = 0; i < attrMap->maplen; i++) { - int j = attrMap[i]; + int j = attrMap->attnums[i]; outvalues[i] = invalues[j]; outisnull[i] = inisnull[j]; @@ -422,7 +429,7 @@ execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map) * Perform conversion of a tuple slot according to the map. */ TupleTableSlot * -execute_attr_map_slot(AttrNumber *attrMap, +execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot) { @@ -454,9 +461,9 @@ execute_attr_map_slot(AttrNumber *attrMap, /* Transpose into proper fields of the out slot. */ for (i = 0; i < outnatts; i++) { - int j = attrMap[i] - 1; + int j = attrMap->attnums[i] - 1; - /* attrMap[i] == 0 means it's a NULL datum. */ + /* attrMap->attnums[i] == 0 means it's a NULL datum. */ if (j == -1) { outvalues[i] = (Datum) 0; @@ -481,7 +488,7 @@ void free_conversion_map(TupleConversionMap *map) { /* indesc and outdesc are not ours to free */ - pfree(map->attrMap); + free_attrmap(map->attrMap); pfree(map->invalues); pfree(map->inisnull); pfree(map->outvalues); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 67f637de11..05cab83d7f 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2338,7 +2338,7 @@ bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Oid *collations1, Oid *collations2, Oid *opfamilies1, Oid *opfamilies2, - AttrNumber *attmap, int maplen) + AttrMap *attmap) { int i; @@ -2365,12 +2365,12 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, */ for (i = 0; i < info1->ii_NumIndexAttrs; i++) { - if (maplen < info2->ii_IndexAttrNumbers[i]) + if (attmap->maplen < info2->ii_IndexAttrNumbers[i]) elog(ERROR, "incorrect attribute map"); /* ignore expressions at this stage */ if ((info1->ii_IndexAttrNumbers[i] != InvalidAttrNumber) && - (attmap[info2->ii_IndexAttrNumbers[i] - 1] != + (attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] != info1->ii_IndexAttrNumbers[i])) return false; @@ -2396,7 +2396,7 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Node *mapped; mapped = map_variable_attnos((Node *) info2->ii_Expressions, - 1, 0, attmap, maplen, + 1, 0, attmap, InvalidOid, &found_whole_row); if (found_whole_row) { @@ -2420,7 +2420,7 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Node *mapped; mapped = map_variable_attnos((Node *) info2->ii_Predicate, - 1, 0, attmap, maplen, + 1, 0, attmap, InvalidOid, &found_whole_row); if (found_whole_row) { diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 5dfa4499fd..2b14e9f31a 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -206,14 +206,13 @@ map_partition_varattnos(List *expr, int fromrel_varno, if (expr != NIL) { - AttrNumber *part_attnos; + AttrMap *part_attmap; - part_attnos = convert_tuples_by_name_map(RelationGetDescr(to_rel), + part_attmap = convert_tuples_by_name_map(RelationGetDescr(to_rel), RelationGetDescr(from_rel)); expr = (List *) map_variable_attnos((Node *) expr, fromrel_varno, 0, - part_attnos, - RelationGetDescr(from_rel)->natts, + part_attmap, RelationGetForm(to_rel)->reltype, &my_found_whole_row); } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 374e2d0efe..d9b61f9875 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1060,9 +1060,8 @@ DefineIndex(Oid relationId, Relation childrel; List *childidxs; ListCell *cell; - AttrNumber *attmap; + AttrMap *attmap; bool found = false; - int maplen; childrel = table_open(childRelid, lockmode); @@ -1089,7 +1088,6 @@ DefineIndex(Oid relationId, attmap = convert_tuples_by_name_map(RelationGetDescr(childrel), parentDesc); - maplen = parentDesc->natts; foreach(cell, childidxs) { @@ -1108,7 +1106,7 @@ DefineIndex(Oid relationId, collationObjectId, cldidx->rd_opfamily, opfamOids, - attmap, maplen)) + attmap)) { Oid cldConstrOid = InvalidOid; @@ -1193,7 +1191,7 @@ DefineIndex(Oid relationId, { ielem->expr = map_variable_attnos((Node *) ielem->expr, - 1, 0, attmap, maplen, + 1, 0, attmap, InvalidOid, &found_whole_row); if (found_whole_row) @@ -1202,7 +1200,7 @@ DefineIndex(Oid relationId, } childStmt->whereClause = map_variable_attnos(stmt->whereClause, 1, 0, - attmap, maplen, + attmap, InvalidOid, &found_whole_row); if (found_whole_row) elog(ERROR, "cannot convert whole-row table reference"); @@ -1217,7 +1215,7 @@ DefineIndex(Oid relationId, pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_DONE, i + 1); - pfree(attmap); + free_attrmap(attmap); } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 45aae5955d..abbb7c0044 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1072,7 +1072,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, foreach(cell, idxlist) { Relation idxRel = index_open(lfirst_oid(cell), AccessShareLock); - AttrNumber *attmap; + AttrMap *attmap; IndexStmt *idxstmt; Oid constraintOid; @@ -1094,10 +1094,10 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, attmap = convert_tuples_by_name_map(RelationGetDescr(rel), RelationGetDescr(parent)); + idxstmt = generateClonedIndexStmt(NULL, idxRel, - attmap, RelationGetDescr(parent)->natts, - &constraintOid); + attmap, &constraintOid); DefineIndex(RelationGetRelid(rel), idxstmt, InvalidOid, @@ -2156,7 +2156,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, Relation relation; TupleDesc tupleDesc; TupleConstr *constr; - AttrNumber *newattno; + AttrMap *newattmap; AttrNumber parent_attno; /* caller already got lock */ @@ -2237,12 +2237,11 @@ MergeAttributes(List *schema, List *supers, char relpersistence, constr = tupleDesc->constr; /* - * newattno[] will contain the child-table attribute numbers for the - * attributes of this parent table. (They are not the same for - * parents after the first one, nor if we have dropped columns.) + * newattmap->attnums[] will contain the child-table attribute numbers + * for the attributes of this parent table. (They are not the same + * for parents after the first one, nor if we have dropped columns.) */ - newattno = (AttrNumber *) - palloc0(tupleDesc->natts * sizeof(AttrNumber)); + newattmap = make_attrmap(tupleDesc->natts); for (parent_attno = 1; parent_attno <= tupleDesc->natts; parent_attno++) @@ -2257,7 +2256,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, * Ignore dropped columns in the parent. */ if (attribute->attisdropped) - continue; /* leave newattno entry as zero */ + continue; /* leave newattmap->attnums entry as zero */ /* * Does it conflict with some previously inherited column? @@ -2315,7 +2314,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, /* Merge of NOT NULL constraints = OR 'em together */ def->is_not_null |= attribute->attnotnull; /* Default and other constraints are handled below */ - newattno[parent_attno - 1] = exist_attno; + newattmap->attnums[parent_attno - 1] = exist_attno; /* Check for GENERATED conflicts */ if (def->generated != attribute->attgenerated) @@ -2346,7 +2345,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, def->constraints = NIL; def->location = -1; inhSchema = lappend(inhSchema, def); - newattno[parent_attno - 1] = ++child_attno; + newattmap->attnums[parent_attno - 1] = ++child_attno; } /* @@ -2394,7 +2393,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, /* * Now copy the CHECK constraints of this parent, adjusting attnos - * using the completed newattno[] map. Identically named constraints + * using the completed newattmap map. Identically named constraints * are merged if possible, else we throw error. */ if (constr && constr->num_check > 0) @@ -2415,7 +2414,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, /* Adjust Vars to match new table's column numbering */ expr = map_variable_attnos(stringToNode(check[i].ccbin), 1, 0, - newattno, tupleDesc->natts, + newattmap, InvalidOid, &found_whole_row); /* @@ -2452,7 +2451,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, } } - pfree(newattno); + free_attrmap(newattmap); /* * Close the parent rel, but keep our lock on it until xact commit. @@ -8195,7 +8194,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, for (int i = 0; i < pd->nparts; i++) { Relation partRel; - AttrNumber *map; + AttrMap *map; AttrNumber *mapped_pkattnum; Oid partIndexId; @@ -8211,7 +8210,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, { mapped_pkattnum = palloc(sizeof(AttrNumber) * numfks); for (int j = 0; j < numfks; j++) - mapped_pkattnum[j] = map[pkattnum[j] - 1]; + mapped_pkattnum[j] = map->attnums[pkattnum[j] - 1]; } else mapped_pkattnum = pkattnum; @@ -8232,7 +8231,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, if (map) { pfree(mapped_pkattnum); - pfree(map); + free_attrmap(map); } } } @@ -8336,7 +8335,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, Oid partitionId = pd->oids[i]; Relation partition = table_open(partitionId, lockmode); List *partFKs; - AttrNumber *attmap; + AttrMap *attmap; AttrNumber mapped_fkattnum[INDEX_MAX_KEYS]; bool attached; char *conname; @@ -8349,8 +8348,8 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, attmap = convert_tuples_by_name_map(RelationGetDescr(partition), RelationGetDescr(rel)); - for (int j = 0; j < numfks; j++) - mapped_fkattnum[j] = attmap[fkattnum[j] - 1]; + for (int j = 0; j < attmap->maplen; j++) + mapped_fkattnum[j] = attmap->attnums[fkattnum[j] - 1]; /* Check whether an existing constraint can be repurposed */ partFKs = copyObject(RelationGetFKeyList(partition)); @@ -8498,7 +8497,7 @@ static void CloneFkReferenced(Relation parentRel, Relation partitionRel) { Relation pg_constraint; - AttrNumber *attmap; + AttrMap *attmap; ListCell *cell; SysScanDesc scan; ScanKeyData key[2]; @@ -8576,8 +8575,9 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) conpfeqop, conppeqop, conffeqop); + Assert(numfks == attmap->maplen); for (int i = 0; i < numfks; i++) - mapped_confkey[i] = attmap[confkey[i] - 1]; + mapped_confkey[i] = attmap->attnums[confkey[i] - 1]; fkconstraint = makeNode(Constraint); /* for now this is all we need */ @@ -8644,7 +8644,7 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) static void CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) { - AttrNumber *attmap; + AttrMap *attmap; List *partFKs; List *clone = NIL; ListCell *cell; @@ -8723,8 +8723,8 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) DeconstructFkConstraintRow(tuple, &numfks, conkey, confkey, conpfeqop, conppeqop, conffeqop); - for (int i = 0; i < numfks; i++) - mapped_conkey[i] = attmap[conkey[i] - 1]; + for (int i = 0; i < attmap->maplen; i++) + mapped_conkey[i] = attmap->attnums[conkey[i] - 1]; /* * Before creating a new constraint, see whether any existing FKs are @@ -10497,7 +10497,7 @@ ATPrepAlterColumnType(List **wqueue, */ if (def->cooked_default) { - AttrNumber *attmap; + AttrMap *attmap; bool found_whole_row; /* create a copy to scribble on */ @@ -10508,7 +10508,7 @@ ATPrepAlterColumnType(List **wqueue, ((ColumnDef *) cmd->def)->cooked_default = map_variable_attnos(def->cooked_default, 1, 0, - attmap, RelationGetDescr(rel)->natts, + attmap, InvalidOid, &found_whole_row); if (found_whole_row) ereport(ERROR, @@ -15860,7 +15860,7 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) Oid idx = lfirst_oid(cell); Relation idxRel = index_open(idx, AccessShareLock); IndexInfo *info; - AttrNumber *attmap; + AttrMap *attmap; bool found = false; Oid constraintOid; @@ -15899,8 +15899,7 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) idxRel->rd_indcollation, attachrelIdxRels[i]->rd_opfamily, idxRel->rd_opfamily, - attmap, - RelationGetDescr(rel)->natts)) + attmap)) { /* * If this index is being created in the parent because of a @@ -15941,7 +15940,6 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) stmt = generateClonedIndexStmt(NULL, idxRel, attmap, - RelationGetDescr(rel)->natts, &constraintOid); DefineIndex(RelationGetRelid(attachrel), stmt, InvalidOid, RelationGetRelid(idxRel), @@ -16407,7 +16405,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) { IndexInfo *childInfo; IndexInfo *parentInfo; - AttrNumber *attmap; + AttrMap *attmap; bool found; int i; PartitionDesc partDesc; @@ -16459,8 +16457,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) parentIdx->rd_indcollation, partIdx->rd_opfamily, parentIdx->rd_opfamily, - attmap, - RelationGetDescr(parentTbl)->natts)) + attmap)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("cannot attach index \"%s\" as a partition of index \"%s\"", @@ -16497,7 +16494,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) ConstraintSetParentConstraint(cldConstrId, constraintOid, RelationGetRelid(partTbl)); - pfree(attmap); + free_attrmap(attmap); validatePartitionedIndex(parentIdx, parentTbl); } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index c46eb8d646..5f9345c6fe 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1843,7 +1843,7 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, if (resultRelInfo->ri_PartitionRoot) { TupleDesc old_tupdesc; - AttrNumber *map; + AttrMap *map; root_relid = RelationGetRelid(resultRelInfo->ri_PartitionRoot); tupdesc = RelationGetDescr(resultRelInfo->ri_PartitionRoot); @@ -1929,7 +1929,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, */ if (resultRelInfo->ri_PartitionRoot) { - AttrNumber *map; + AttrMap *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); @@ -1978,7 +1978,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, if (resultRelInfo->ri_PartitionRoot) { TupleDesc old_tupdesc = RelationGetDescr(rel); - AttrNumber *map; + AttrMap *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); @@ -2085,7 +2085,7 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, if (resultRelInfo->ri_PartitionRoot) { TupleDesc old_tupdesc = RelationGetDescr(rel); - AttrNumber *map; + AttrMap *map; rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index d23f292cb0..af5e89bec8 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -143,7 +143,7 @@ typedef struct PartitionDispatchData List *keystate; /* list of ExprState */ PartitionDesc partdesc; TupleTableSlot *tupslot; - AttrNumber *tupmap; + AttrMap *tupmap; int indexes[FLEXIBLE_ARRAY_MEMBER]; } PartitionDispatchData; @@ -298,7 +298,7 @@ ExecFindPartition(ModifyTableState *mtstate, dispatch = pd[0]; while (true) { - AttrNumber *map = dispatch->tupmap; + AttrMap *map = dispatch->tupmap; int partidx = -1; CHECK_FOR_INTERRUPTS(); @@ -511,7 +511,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, Relation firstResultRel = mtstate->resultRelInfo[0].ri_RelationDesc; ResultRelInfo *leaf_part_rri; MemoryContext oldcxt; - AttrNumber *part_attnos = NULL; + AttrMap *part_attmap = NULL; bool found_whole_row; oldcxt = MemoryContextSwitchTo(proute->memcxt); @@ -584,14 +584,13 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, /* * Convert Vars in it to contain this partition's attribute numbers. */ - part_attnos = + part_attmap = convert_tuples_by_name_map(RelationGetDescr(partrel), RelationGetDescr(firstResultRel)); wcoList = (List *) map_variable_attnos((Node *) wcoList, firstVarno, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ @@ -642,15 +641,14 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, /* * Convert Vars in it to contain this partition's attribute numbers. */ - if (part_attnos == NULL) - part_attnos = + if (part_attmap == NULL) + part_attmap = convert_tuples_by_name_map(RelationGetDescr(partrel), RelationGetDescr(firstResultRel)); returningList = (List *) map_variable_attnos((Node *) returningList, firstVarno, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ @@ -785,23 +783,21 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * target relation (firstVarno). */ onconflset = (List *) copyObject((Node *) node->onConflictSet); - if (part_attnos == NULL) - part_attnos = + if (part_attmap == NULL) + part_attmap = convert_tuples_by_name_map(RelationGetDescr(partrel), RelationGetDescr(firstResultRel)); onconflset = (List *) map_variable_attnos((Node *) onconflset, INNER_VAR, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ onconflset = (List *) map_variable_attnos((Node *) onconflset, firstVarno, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ @@ -835,16 +831,14 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, clause = (List *) map_variable_attnos((Node *) clause, INNER_VAR, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ clause = (List *) map_variable_attnos((Node *) clause, firstVarno, 0, - part_attnos, - RelationGetDescr(firstResultRel)->natts, + part_attmap, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ @@ -1434,15 +1428,16 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) { List *new_tlist = NIL; TupleDesc tupdesc = map->outdesc; - AttrNumber *attrMap = map->attrMap; + AttrMap *attrMap = map->attrMap; AttrNumber attrno; + Assert(tupdesc->natts == attrMap->maplen); for (attrno = 1; attrno <= tupdesc->natts; attrno++) { Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1); TargetEntry *tle; - if (attrMap[attrno - 1] != InvalidAttrNumber) + if (attrMap->attnums[attrno - 1] != InvalidAttrNumber) { Assert(!att_tup->attisdropped); @@ -1450,7 +1445,7 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) * Use the corresponding entry from the parent's tlist, adjusting * the resno the match the partition's attno. */ - tle = (TargetEntry *) list_nth(tlist, attrMap[attrno - 1] - 1); + tle = (TargetEntry *) list_nth(tlist, attrMap->attnums[attrno - 1] - 1); tle->resno = attrno; } else diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index ee47547624..9c5462aef6 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -917,7 +917,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla Relation relation; TupleDesc tupleDesc; TupleConstr *constr; - AttrNumber *attmap; + AttrMap *attmap; AclResult aclresult; char *comment; ParseCallbackState pcbstate; @@ -974,7 +974,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla * since dropped columns in the source table aren't copied, so the new * table can have different column numbers. */ - attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * tupleDesc->natts); + attmap = make_attrmap(tupleDesc->natts); /* * Insert the copied attributes into the cxt for the new table definition. @@ -1020,7 +1020,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla */ cxt->columns = lappend(cxt->columns, def); - attmap[parent_attno - 1] = list_length(cxt->columns); + attmap->attnums[parent_attno - 1] = list_length(cxt->columns); /* * Copy default, if present and it should be copied. We have separate @@ -1051,7 +1051,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla def->cooked_default = map_variable_attnos(this_default, 1, 0, - attmap, tupleDesc->natts, + attmap, InvalidOid, &found_whole_row); /* @@ -1134,7 +1134,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla ccbin_node = map_variable_attnos(stringToNode(ccbin), 1, 0, - attmap, tupleDesc->natts, + attmap, InvalidOid, &found_whole_row); /* @@ -1200,7 +1200,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla /* Build CREATE INDEX statement to recreate the parent_index */ index_stmt = generateClonedIndexStmt(cxt->relation, parent_index, - attmap, tupleDesc->natts, + attmap, NULL); /* Copy comment on index, if requested */ @@ -1332,7 +1332,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) */ IndexStmt * generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, - const AttrNumber *attmap, int attmap_length, + const AttrMap *attmap, Oid *constraintOid) { Oid source_relid = RelationGetRelid(source_idx); @@ -1552,7 +1552,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, /* Adjust Vars to match new table's column numbering */ indexkey = map_variable_attnos(indexkey, 1, 0, - attmap, attmap_length, + attmap, InvalidOid, &found_whole_row); /* As in transformTableLikeClause, reject whole-row variables */ @@ -1659,7 +1659,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, /* Adjust Vars to match new table's column numbering */ pred_tree = map_variable_attnos(pred_tree, 1, 0, - attmap, attmap_length, + attmap, InvalidOid, &found_whole_row); /* As in transformTableLikeClause, reject whole-row variables */ diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index b386f8460d..f38c5b3ea4 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -267,7 +267,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) */ desc = RelationGetDescr(entry->localrel); oldctx = MemoryContextSwitchTo(LogicalRepRelMapContext); - entry->attrmap = palloc(desc->natts * sizeof(AttrNumber)); + entry->attrmap = make_attrmap(desc->natts); MemoryContextSwitchTo(oldctx); found = 0; @@ -278,14 +278,14 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) if (attr->attisdropped || attr->attgenerated) { - entry->attrmap[i] = -1; + entry->attrmap->attnums[i] = -1; continue; } attnum = logicalrep_rel_att_by_name(remoterel, NameStr(attr->attname)); - entry->attrmap[i] = attnum; + entry->attrmap->attnums[i] = attnum; if (attnum >= 0) found++; } @@ -340,8 +340,8 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) attnum = AttrNumberGetAttrOffset(attnum); - if (entry->attrmap[attnum] < 0 || - !bms_is_member(entry->attrmap[attnum], remoterel->attkeys)) + if (entry->attrmap->attnums[attnum] < 0 || + !bms_is_member(entry->attrmap->attnums[attnum], remoterel->attkeys)) { entry->updatable = false; break; diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index ff62303638..1a91c60c17 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -232,6 +232,7 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate, defmap = (int *) palloc(num_phys_attrs * sizeof(int)); defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *)); + Assert(rel->attrmap->maplen == num_phys_attrs); for (attnum = 0; attnum < num_phys_attrs; attnum++) { Expr *defexpr; @@ -239,7 +240,7 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate, if (TupleDescAttr(desc, attnum)->attisdropped || TupleDescAttr(desc, attnum)->attgenerated) continue; - if (rel->attrmap[attnum] >= 0) + if (rel->attrmap->attnums[attnum] >= 0) continue; defexpr = (Expr *) build_column_default(rel->localrel, attnum + 1); @@ -321,10 +322,11 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel, error_context_stack = &errcallback; /* Call the "in" function for each non-dropped attribute */ + Assert(natts == rel->attrmap->maplen); for (i = 0; i < natts; i++) { Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i); - int remoteattnum = rel->attrmap[i]; + int remoteattnum = rel->attrmap->attnums[i]; if (!att->attisdropped && remoteattnum >= 0 && values[remoteattnum] != NULL) @@ -390,10 +392,11 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel, error_context_stack = &errcallback; /* Call the "in" function for each replaced attribute */ + Assert(natts == rel->attrmap->maplen); for (i = 0; i < natts; i++) { Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i); - int remoteattnum = rel->attrmap[i]; + int remoteattnum = rel->attrmap->attnums[i]; if (remoteattnum < 0) continue; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 93508c2a87..12f7cadf3b 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -1221,8 +1221,7 @@ typedef struct { int target_varno; /* RTE index to search for */ int sublevels_up; /* (current) nesting depth */ - const AttrNumber *attno_map; /* map array for user attnos */ - int map_length; /* number of entries in attno_map[] */ + const AttrMap *attno_map; /* map array for user attnos */ Oid to_rowtype; /* change whole-row Vars to this type */ bool *found_whole_row; /* output flag */ } map_variable_attnos_context; @@ -1249,11 +1248,11 @@ map_variable_attnos_mutator(Node *node, if (attno > 0) { /* user-defined column, replace attno */ - if (attno > context->map_length || - context->attno_map[attno - 1] == 0) + if (attno > context->attno_map->maplen || + context->attno_map->attnums[attno - 1] == 0) elog(ERROR, "unexpected varattno %d in expression to be mapped", attno); - newvar->varattno = newvar->varoattno = context->attno_map[attno - 1]; + newvar->varattno = newvar->varoattno = context->attno_map->attnums[attno - 1]; } else if (attno == 0) { @@ -1350,7 +1349,7 @@ map_variable_attnos_mutator(Node *node, Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, - const AttrNumber *attno_map, int map_length, + const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row) { map_variable_attnos_context context; @@ -1358,7 +1357,6 @@ map_variable_attnos(Node *node, context.target_varno = target_varno; context.sublevels_up = sublevels_up; context.attno_map = attno_map; - context.map_length = map_length; context.to_rowtype = to_rowtype; context.found_whole_row = found_whole_row; diff --git a/src/include/access/attmap.h b/src/include/access/attmap.h new file mode 100644 index 0000000000..8e4882f096 --- /dev/null +++ b/src/include/access/attmap.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + * + * attnum.h + * Definitions for PostgreSQL attribute mappings + * + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/access/attmap.h + * + *------------------------------------------------------------------------- + */ +#ifndef ATTMAP_H +#define ATTMAP_H + +#include "access/attnum.h" + +/* + * Attribute mapping structure + * + * An attribute mapping tracks the relationship of a child relation and + * its parent for inheritance and partitions. This is used mainly for + * cloned object creations (indexes, foreign keys, etc.) when creating + * an inherited child relation, and for runtime-execution attribute + * mapping. + * + * Dropped attributes are marked with 0 and the length of the map is set + * to be the number of attributes of the parent, which takes into account + * its dropped attributes. + */ +typedef struct AttrMap +{ + AttrNumber *attnums; + int maplen; +} AttrMap; + +/* utility routines to manipulate attribute maps */ +extern AttrMap *make_attrmap(int maplen); +extern void free_attrmap(AttrMap *map); + +#endif /* ATTMAP_H */ diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h index 6d095f8e0d..f48cba967d 100644 --- a/src/include/access/tupconvert.h +++ b/src/include/access/tupconvert.h @@ -14,6 +14,7 @@ #ifndef TUPCONVERT_H #define TUPCONVERT_H +#include "access/attmap.h" #include "access/htup.h" #include "access/tupdesc.h" #include "executor/tuptable.h" @@ -23,7 +24,7 @@ typedef struct TupleConversionMap { TupleDesc indesc; /* tupdesc for source rowtype */ TupleDesc outdesc; /* tupdesc for result rowtype */ - AttrNumber *attrMap; /* indexes of input fields, or 0 for null */ + AttrMap *attrMap; /* indexes of input fields, or 0 for null */ Datum *invalues; /* workspace for deconstructing source */ bool *inisnull; Datum *outvalues; /* workspace for constructing result */ @@ -38,14 +39,15 @@ extern TupleConversionMap *convert_tuples_by_position(TupleDesc indesc, extern TupleConversionMap *convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc); -extern AttrNumber *convert_tuples_by_name_map(TupleDesc indesc, - TupleDesc outdesc); -extern AttrNumber *convert_tuples_by_name_map_if_req(TupleDesc indesc, - TupleDesc outdesc); +extern AttrMap *convert_tuples_by_name_map(TupleDesc indesc, + TupleDesc outdesc); +extern AttrMap *convert_tuples_by_name_map_if_req(TupleDesc indesc, + TupleDesc outdesc); extern HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map); -extern TupleTableSlot *execute_attr_map_slot(AttrNumber *attrMap, - TupleTableSlot *in_slot, TupleTableSlot *out_slot); +extern TupleTableSlot *execute_attr_map_slot(AttrMap *attrMap, + TupleTableSlot *in_slot, + TupleTableSlot *out_slot); extern void free_conversion_map(TupleConversionMap *map); diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 1113d25b2d..f42aa53128 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -109,7 +109,7 @@ extern IndexInfo *BuildIndexInfo(Relation index); extern bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, Oid *collations1, Oid *collations2, Oid *opfamilies1, Oid *opfamilies2, - AttrNumber *attmap, int maplen); + AttrMap *attmap); extern void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii); diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 1348064ad0..08dd0ce4ca 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -16,6 +16,7 @@ #include "parser/parse_node.h" +typedef struct AttrMap AttrMap; extern List *transformCreateStmt(CreateStmt *stmt, const char *queryString); extern List *transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, @@ -29,7 +30,7 @@ extern PartitionBoundSpec *transformPartitionBound(ParseState *pstate, Relation PartitionBoundSpec *spec); extern IndexStmt *generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, - const AttrNumber *attmap, int attmap_length, + const AttrMap *attmap, Oid *constraintOid); #endif /* PARSE_UTILCMD_H */ diff --git a/src/include/replication/logicalrelation.h b/src/include/replication/logicalrelation.h index 2642a3f94e..f167d4e59b 100644 --- a/src/include/replication/logicalrelation.h +++ b/src/include/replication/logicalrelation.h @@ -21,7 +21,7 @@ typedef struct LogicalRepRelMapEntry /* Mapping to local relation, filled as needed. */ Oid localreloid; /* local relation id */ Relation localrel; /* relcache entry */ - AttrNumber *attrmap; /* map of local attributes to remote ones */ + AttrMap *attrmap; /* map of local attributes to remote ones */ bool updatable; /* Can apply updates/deletes? */ /* Sync state. */ diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 8d8fd17e41..634cdc235d 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -17,6 +17,7 @@ #include "nodes/parsenodes.h" +typedef struct AttrMap AttrMap; typedef struct replace_rte_variables_context replace_rte_variables_context; typedef Node *(*replace_rte_variables_callback) (Var *var, @@ -71,7 +72,7 @@ extern Node *replace_rte_variables_mutator(Node *node, extern Node *map_variable_attnos(Node *node, int target_varno, int sublevels_up, - const AttrNumber *attno_map, int map_length, + const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row); extern Node *ReplaceVarsFromTargetList(Node *node, -- 2.24.0