From 16828d5c0273b4fe5f10f42588005f16b415b2d8 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Wed, 28 Mar 2018 10:43:52 +1030 Subject: Fast ALTER TABLE ADD COLUMN with a non-NULL default Currently adding a column to a table with a non-NULL default results in a rewrite of the table. For large tables this can be both expensive and disruptive. This patch removes the need for the rewrite as long as the default value is not volatile. The default expression is evaluated at the time of the ALTER TABLE and the result stored in a new column (attmissingval) in pg_attribute, and a new column (atthasmissing) is set to true. Any existing row when fetched will be supplied with the attmissingval. New rows will have the supplied value or the default and so will never need the attmissingval. Any time the table is rewritten all the atthasmissing and attmissingval settings for the attributes are cleared, as they are no longer needed. The most visible code change from this is in heap_attisnull, which acquires a third TupleDesc argument, allowing it to detect a missing value if there is one. In many cases where it is known that there will not be any (e.g. catalog relations) NULL can be passed for this argument. Andrew Dunstan, heavily modified from an original patch from Serge Rielau. Reviewed by Tom Lane, Andres Freund, Tomas Vondra and David Rowley. Discussion: https://postgr.es/m/31e2e921-7002-4c27-59f5-51f08404c858@2ndQuadrant.com --- src/backend/utils/adt/ruleutils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/backend/utils/adt/ruleutils.c') diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index b0559ca5bcd..f8fc7f83f9b 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -1242,7 +1242,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, * versions of the expressions and predicate, because we want to display * non-const-folded expressions.) */ - if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs)) + if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL)) { Datum exprsDatum; bool isnull; @@ -1410,7 +1410,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, /* * If it's a partial index, decompile and append the predicate */ - if (!heap_attisnull(ht_idx, Anum_pg_index_indpred)) + if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL)) { Node *node; Datum predDatum; @@ -1644,7 +1644,7 @@ pg_get_partkeydef_worker(Oid relid, int prettyFlags, * versions of the expressions, because we want to display * non-const-folded expressions.) */ - if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs)) + if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL)) { Datum exprsDatum; bool isnull; -- cgit v1.2.3