Add TupleDescGetDefault()
authorPeter Eisentraut
Wed, 27 Sep 2023 17:52:40 +0000 (18:52 +0100)
committerPeter Eisentraut
Wed, 27 Sep 2023 17:52:40 +0000 (18:52 +0100)
This unifies some repetitive code.

Note: I didn't push the "not found" error message into the new
function, even though all existing callers would be able to make use
of it.  Using the existing error handling as-is would probably require
exposing the Relation type via tupdesc.h, which doesn't seem
desirable.  (Or even if we changed it to just report the OID, it would
inject the concept of a relation containing the tuple descriptor into
tupdesc.h, which might be a layering violation.  Perhaps some further
improvements could be considered here separately.)

Discussion: https://www.postgresql.org/message-id/flat/52a125e4-ff9a-95f5-9f61-b87cf447e4da%40eisentraut.org

src/backend/access/common/tupdesc.c
src/backend/commands/tablecmds.c
src/backend/parser/parse_utilcmd.c
src/backend/rewrite/rewriteHandler.c
src/include/access/tupdesc.h

index 253d6c86f86bf94388991e06f80b759b128bb2c0..ce2c7bce8566f41a146a4683262c7a19aa6383e1 100644 (file)
@@ -927,3 +927,28 @@ BuildDescFromLists(const List *names, const List *types, const List *typmods, co
 
    return desc;
 }
+
+/*
+ * Get default expression (or NULL if none) for the given attribute number.
+ */
+Node *
+TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum)
+{
+   Node       *result = NULL;
+
+   if (tupdesc->constr)
+   {
+       AttrDefault *attrdef = tupdesc->constr->defval;
+
+       for (int i = 0; i < tupdesc->constr->num_defval; i++)
+       {
+           if (attrdef[i].adnum == attnum)
+           {
+               result = stringToNode(attrdef[i].adbin);
+               break;
+           }
+       }
+   }
+
+   return result;
+}
index ad398e837d577345a9307f1fc50c8914de96893f..73b8dea81c8a7fdbae20ef54af280ed4c7655c08 100644 (file)
@@ -2795,22 +2795,9 @@ MergeAttributes(List *columns, const List *supers, char relpersistence,
             */
            if (attribute->atthasdef)
            {
-               Node       *this_default = NULL;
+               Node       *this_default;
 
-               /* Find default in constraint structure */
-               if (constr != NULL)
-               {
-                   AttrDefault *attrdef = constr->defval;
-
-                   for (int i = 0; i < constr->num_defval; i++)
-                   {
-                       if (attrdef[i].adnum == parent_attno)
-                       {
-                           this_default = stringToNode(attrdef[i].adbin);
-                           break;
-                       }
-                   }
-               }
+               this_default = TupleDescGetDefault(tupleDesc, parent_attno);
                if (this_default == NULL)
                    elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
                         parent_attno, RelationGetRelationName(relation));
index 55c315f0e28c7fcf0ea98b98f715986606b6b997..cf0d432ab13c3afefddf9712141504f5880a94c4 100644 (file)
@@ -1358,20 +1358,11 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
                 (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED) :
                 (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)))
            {
-               Node       *this_default = NULL;
-               AttrDefault *attrdef = constr->defval;
+               Node       *this_default;
                AlterTableCmd *atsubcmd;
                bool        found_whole_row;
 
-               /* Find default in constraint structure */
-               for (int i = 0; i < constr->num_defval; i++)
-               {
-                   if (attrdef[i].adnum == parent_attno)
-                   {
-                       this_default = stringToNode(attrdef[i].adbin);
-                       break;
-                   }
-               }
+               this_default = TupleDescGetDefault(tupleDesc, parent_attno);
                if (this_default == NULL)
                    elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
                         parent_attno, RelationGetRelationName(relation));
index b486ab559a84c5afeb100e0934be43dca2c4213e..41a362310a8905a8e37a86c56572041050dcae5a 100644 (file)
@@ -1246,21 +1246,7 @@ build_column_default(Relation rel, int attrno)
     */
    if (att_tup->atthasdef)
    {
-       if (rd_att->constr && rd_att->constr->num_defval > 0)
-       {
-           AttrDefault *defval = rd_att->constr->defval;
-           int         ndef = rd_att->constr->num_defval;
-
-           while (--ndef >= 0)
-           {
-               if (attrno == defval[ndef].adnum)
-               {
-                   /* Found it, convert string representation to node tree. */
-                   expr = stringToNode(defval[ndef].adbin);
-                   break;
-               }
-           }
-       }
+       expr = TupleDescGetDefault(rd_att, attrno);
        if (expr == NULL)
            elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
                 attrno, RelationGetRelationName(rel));
index f6cc28a6618db0f5cf6e35444a879f14cb95f6a3..ffd2874ee3cc2df20c4478c63c9a4cb450080eb8 100644 (file)
@@ -151,4 +151,6 @@ extern TupleDesc BuildDescForRelation(const List *columns);
 
 extern TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations);
 
+extern Node *TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum);
+
 #endif                         /* TUPDESC_H */