Set all variable-length fields of pg_attribute to null on column drop
authorPeter Eisentraut <[email protected]>
Fri, 22 Dec 2023 20:44:55 +0000 (21:44 +0100)
committerPeter Eisentraut <[email protected]>
Fri, 22 Dec 2023 20:44:55 +0000 (21:44 +0100)
When a column is dropped, the fields attacl, attoptions, and
attfdwoptions were kept unchanged.  This is probably harmless, but it
seems wasteful, and leaves potentially dangling data lying around (for
example, attacl could contain references to users that are later also
dropped).

Change this to set those fields to null when a column is marked as
dropped.

Reviewed-by: Alvaro Herrera <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/249d819d-1763-4580-8110-0bf91a0f08b7@eisentraut.org

src/backend/catalog/heap.c

index 7224d966950436d3c693d6559aa62e02fbe0edce..b93894889d6b630e9fbb945d6805e2e60186be63 100644 (file)
@@ -1647,6 +1647,9 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
    HeapTuple   tuple;
    Form_pg_attribute attStruct;
    char        newattname[NAMEDATALEN];
+   Datum       valuesAtt[Natts_pg_attribute] = {0};
+   bool        nullsAtt[Natts_pg_attribute] = {0};
+   bool        replacesAtt[Natts_pg_attribute] = {0};
 
    /*
     * Grab an exclusive lock on the target table, which we will NOT release
@@ -1695,24 +1698,24 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
             "........pg.dropped.%d........", attnum);
    namestrcpy(&(attStruct->attname), newattname);
 
-   /* clear the missing value if any */
-   if (attStruct->atthasmissing)
-   {
-       Datum       valuesAtt[Natts_pg_attribute] = {0};
-       bool        nullsAtt[Natts_pg_attribute] = {0};
-       bool        replacesAtt[Natts_pg_attribute] = {0};
-
-       /* update the tuple - set atthasmissing and attmissingval */
-       valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
-           BoolGetDatum(false);
-       replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
-       valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
-       nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
-       replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
-
-       tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
-                                 valuesAtt, nullsAtt, replacesAtt);
-   }
+   /* Clear the missing value */
+   attStruct->atthasmissing = false;
+   nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
+   replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
+
+   /*
+    * Clear the other variable-length fields.  This saves some space in
+    * pg_attribute and removes no longer useful information.
+    */
+   nullsAtt[Anum_pg_attribute_attacl - 1] = true;
+   replacesAtt[Anum_pg_attribute_attacl - 1] = true;
+   nullsAtt[Anum_pg_attribute_attoptions - 1] = true;
+   replacesAtt[Anum_pg_attribute_attoptions - 1] = true;
+   nullsAtt[Anum_pg_attribute_attfdwoptions - 1] = true;
+   replacesAtt[Anum_pg_attribute_attfdwoptions - 1] = true;
+
+   tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
+                             valuesAtt, nullsAtt, replacesAtt);
 
    CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);