Add 'missing_ok' argument to build_attrmap_by_name
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 29 Nov 2022 08:39:36 +0000 (09:39 +0100)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 29 Nov 2022 08:39:36 +0000 (09:39 +0100)
When it's given as true, return a 0 in the position of the missing
column rather than raising an error.

This is currently unused, but it allows us to reimplement column
permission checking in a subsequent commit.  It seems worth breaking
into a separate commit because it affects unrelated code.

Author: Amit Langote <amitlangote09@gmail.com>
Discussion: https://postgr.es/m/CA+HiwqFfiai=qBxPDTjaio_ZcaqUKh+FC=prESrB8ogZgFNNNQ@mail.gmail.com

src/backend/access/common/attmap.c
src/backend/access/common/tupconvert.c
src/backend/catalog/partition.c
src/backend/commands/indexcmds.c
src/backend/commands/tablecmds.c
src/backend/executor/execMain.c
src/backend/executor/execPartition.c
src/backend/parser/parse_utilcmd.c
src/backend/replication/pgoutput/pgoutput.c
src/include/access/attmap.h

index 896f82a22b48bd0ad887ee4f91548b3c65117d3d..1e65d8a120c2309dd777ceeb95a77fc45f7936f2 100644 (file)
@@ -169,10 +169,15 @@ build_attrmap_by_position(TupleDesc indesc,
  * 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;
@@ -235,7 +240,7 @@ build_attrmap_by_name(TupleDesc indesc,
                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"),
@@ -257,12 +262,13 @@ build_attrmap_by_name(TupleDesc indesc,
  */
 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))
index 4010e20cfbc26e3d4b991bd5daca418ad3e32b35..b2f892d2fdf0bbfcf855de5d943ca979e822ff53 100644 (file)
@@ -107,7 +107,7 @@ convert_tuples_by_name(TupleDesc indesc,
    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)
    {
index c6ec479004876e63e5b2473eb2dee4712403b66b..79ccddce556e5b6d5c118e70b7c6979cd4bb7c46 100644 (file)
@@ -227,7 +227,8 @@ map_partition_varattnos(List *expr, int fromrel_varno,
        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,
index 91cee27743da031c54498e74dd48f4d9e7025d4a..b5b860c3abf700174e748f4fcd18d23424c25cfd 100644 (file)
@@ -1290,7 +1290,8 @@ DefineIndex(Oid relationId,
                childidxs = RelationGetIndexList(childrel);
                attmap =
                    build_attrmap_by_name(RelationGetDescr(childrel),
-                                         parentDesc);
+                                         parentDesc,
+                                         false);
 
                foreach(cell, childidxs)
                {
index 845208d662ba9450cc1c915c3f99699fc45c5bff..10c1955884f29c2f37f58a9207d6265acc5eb951 100644 (file)
@@ -1206,7 +1206,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
            }
 
            attmap = build_attrmap_by_name(RelationGetDescr(rel),
-                                          RelationGetDescr(parent));
+                                          RelationGetDescr(parent),
+                                          false);
            idxstmt =
                generateClonedIndexStmt(NULL, idxRel,
                                        attmap, &constraintOid);
@@ -9647,7 +9648,8 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
             * 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);
@@ -9814,7 +9816,8 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
            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];
 
@@ -10022,7 +10025,8 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel)
    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);
@@ -10219,7 +10223,8 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
     * different.  This map is used to convert them.
     */
    attmap = build_attrmap_by_name(RelationGetDescr(partRel),
-                                  RelationGetDescr(parentRel));
+                                  RelationGetDescr(parentRel),
+                                  false);
 
    partFKs = copyObject(RelationGetFKeyList(partRel));
 
@@ -12335,7 +12340,8 @@ ATPrepAlterColumnType(List **wqueue,
                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,
@@ -18043,7 +18049,8 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
        /* 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);
 
        /*
@@ -18981,7 +18988,8 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name)
        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,
index ef828e049606e9c0b366f162d1f4de06ee4adab9..e301c687e37ef6e95e20053473e8965b2a3ad596 100644 (file)
@@ -1859,7 +1859,7 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
 
        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
@@ -1944,7 +1944,8 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
                    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
@@ -1996,7 +1997,8 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
                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
@@ -2103,7 +2105,8 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
                        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,
index 262cabd940342576318d81ca6fcdffe631f8cd1f..e85f9b8f5a070f898061bda4c7b89100342acf82 100644 (file)
@@ -582,7 +582,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
         */
        part_attmap =
            build_attrmap_by_name(RelationGetDescr(partrel),
-                                 RelationGetDescr(firstResultRel));
+                                 RelationGetDescr(firstResultRel),
+                                 false);
        wcoList = (List *)
            map_variable_attnos((Node *) wcoList,
                                firstVarno, 0,
@@ -639,7 +640,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
        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,
@@ -780,7 +782,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
                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,
@@ -878,7 +881,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
        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);
@@ -1147,7 +1151,8 @@ ExecInitPartitionDispatchInfo(EState *estate,
         * routing.
         */
        pd->tupmap = build_attrmap_by_name_if_req(RelationGetDescr(parent_pd->reldesc),
-                                                 tupdesc);
+                                                 tupdesc,
+                                                 false);
        pd->tupslot = pd->tupmap ?
            MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual) : NULL;
    }
index 487eb2041beaf5601ed583841c0fc2b38fe12f45..36791d881797f83e260873076baba4a7811d049d 100644 (file)
@@ -1232,7 +1232,8 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
     * have a failure since both tables are locked.
     */
    attmap = build_attrmap_by_name(RelationGetDescr(childrel),
-                                  tupleDesc);
+                                  tupleDesc,
+                                  false);
 
    /*
     * Process defaults, if required.
index 2ecaa5b9074bebd719949a74f202b91411d0abbe..f2128190d899d0ab7d3f88ff1f99fd07636c3026 100644 (file)
@@ -1125,7 +1125,7 @@ init_tuple_slot(PGOutputData *data, Relation relation,
        /* 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);
index 3ae40cade7577a56336bb0f035d56f269edceebc..dc0277384f0fc2d8d89273a425d826cc81ea7763 100644 (file)
@@ -42,9 +42,11 @@ extern void free_attrmap(AttrMap *map);
 
 /* 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);