Re: bug when apply fast default mechanism for adding new column over domain with default value
jian he <jian.universality@gmail.com>
From: jian he <jian.universality@gmail.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: PostgreSQL-development <pgsql-hackers@postgresql.org>
Date: 2025-03-03T08:45:21Z
Lists: pgsql-hackers
On Mon, Mar 3, 2025 at 6:08 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> jian he <jian.universality@gmail.com> writes:
> > On Sun, Mar 2, 2025 at 7:54 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> >> I think the fundamental problem here is that StoreAttrDefault
> >> shouldn't be involved in this in the first place.
>
> > i've split missingval related code into StoreAttrMissingVal.
>
> Hm, this does nothing to improve the modularity of the affected
> code; if anything it's worse than before. (Fools around for
> awhile...) I had something more like the attached in mind.
> The idea here is to centralize the control of whether we are
> storing a missingval or doing a table rewrite in ATExecAddColumn.
> StoreAttrMissingVal has nothing to do with pg_attrdef nor does
> StoreAttrDefault have anything to do with attmissingval.
>
your patch looks very good!!!
within ATExecAddColumn, we can
if (!missingIsNull)
StoreAttrMissingVal(rel, attribute->attnum, missingval, missingIsNull);
to save some cycles?
+ /* ... and store it. If it's null, nothing is stored. */
+ StoreAttrMissingVal(rel, attribute->attnum,
+ missingval, missingIsNull);
+ has_missing = !missingIsNull;
+ FreeExecutorState(estate);
do we need pfree missingval?
+ else
+ {
+ /*
+ * Failed to use missing mode. We have to do a table rewrite
+ * to install the value --- unless it's a virtual generated
+ * column.
+ */
+ if (colDef->generated != ATTRIBUTE_GENERATED_VIRTUAL)
+ tab->rewrite |= AT_REWRITE_DEFAULT_VAL;
+ }
maybe here add comments mentioning that the identity column needs table rewrite.
since we removed ``tab->rewrite |= AT_REWRITE_DEFAULT_VAL;``
in the if (colDef->identity) branch.
StoreAttrDefault is at the end of
ATExecAlterColumnType, ATExecCookedColumnDefault, StoreConstraints
these function later will call CommandCounterIncrement
I also checked AddRelationNewConstraints surrounding code.
overall i think StoreAttrDefault doesn't have CommandCounterIncrement
should be fine.
looking at DefineRelation comments:
* We can set the atthasdef flags now in the tuple descriptor; this just
* saves StoreAttrDefault from having to do an immediate update of the
* pg_attribute rows.
this seems not right?
DefineRelation->heap_create_with_catalog->heap_create->RelationBuildLocalRelation->CreateTupleDescCopy
don't copy atthasdef.
RelationBuildLocalRelation later didn't touch atthasdef.
populate_compact_attribute didn't touch atthasdef.
so StoreAttrDefault has to update that pg_attribute row.
somehow related, if you look at AddRelationNewConstraints.
```
foreach_ptr(RawColumnDefault, colDef, newColDefaults)
{
defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
cooked->conoid = defOid;
}
maybe we can minor change comments in struct CookedConstraint.conoid.
We can mention: if contype is CONSTR_DEFAULT then it is pg_attrdef.oid
for the default expression.
Commits
-
Need to do CommandCounterIncrement after StoreAttrMissingVal.
- dd34cbfce296 13.21 landed
- d31d39cfe4f5 14.18 landed
- bd178960c69b 18.0 landed
- 2d6cfb0cddd3 15.13 landed
- 0941aadcd55b 17.5 landed
- 053222a97b13 16.9 landed
-
Simplify some logic around setting pg_attribute.atthasdef.
- 35c8dd9e1176 18.0 landed
-
Remove now-dead code in StoreAttrDefault().
- 4528768d98f8 18.0 landed
-
Fix broken handling of domains in atthasmissing logic.
- 95f650674d2c 18.0 landed
- edc3bccd0dc7 16.9 landed
- d6dd2a02bae0 17.5 landed
- c75c830e2392 14.18 landed
- aac07b56256e 13.21 landed
- 1d180931cc3b 15.13 landed