Add TupleDescGetDefault()
authorPeter Eisentraut <peter@eisentraut.org>
Wed, 27 Sep 2023 17:52:40 +0000 (18:52 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
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 */