@@ -387,6 +387,8 @@ static bool ConstraintImpliedByRelConstraint(Relation scanrel,
387387 List *testConstraint, List *provenConstraint);
388388static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
389389 Node *newDefault, LOCKMODE lockmode);
390+ static ObjectAddress ATExecCookedColumnDefault(Relation rel, AttrNumber attnum,
391+ Node *newDefault);
390392static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
391393 Node *def, LOCKMODE lockmode);
392394static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
@@ -2010,8 +2012,8 @@ storage_name(char c)
20102012 * 'schema' is the column/attribute definition for the table. (It's a list
20112013 *of ColumnDef's.) It is destructively changed.
20122014 * 'supers' is a list of OIDs of parent relations, already locked by caller.
2013- * 'relpersistence' isa persistence type of the table.
2014- * 'is_partition' tells if the table is a partition
2015+ * 'relpersistence' isthe persistence type of the table.
2016+ * 'is_partition' tells if the table is a partition.
20152017 *
20162018 * Output arguments:
20172019 * 'supconstr' receives a list of constraints belonging to the parents,
@@ -2176,7 +2178,11 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
21762178TupleDesctupleDesc;
21772179TupleConstr *constr;
21782180AttrNumber *newattno;
2181+ List *inherited_defaults;
2182+ List *cols_with_defaults;
21792183AttrNumberparent_attno;
2184+ ListCell *lc1;
2185+ ListCell *lc2;
21802186
21812187/* caller already got lock */
21822188relation = table_open(parent, NoLock);
@@ -2263,6 +2269,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
22632269newattno = (AttrNumber *)
22642270palloc0(tupleDesc->natts * sizeof(AttrNumber));
22652271
2272+ /* We can't process inherited defaults until newattno[] is complete. */
2273+ inherited_defaults = cols_with_defaults = NIL;
2274+
22662275for (parent_attno = 1; parent_attno <= tupleDesc->natts;
22672276 parent_attno++)
22682277{
@@ -2318,7 +2327,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
23182327 get_collation_name(defCollId),
23192328 get_collation_name(attribute->attcollation))));
23202329
2321- /* Copy storage parameter */
2330+ /* Copy/check storage parameter */
23222331if (def->storage == 0)
23232332def->storage = attribute->attstorage;
23242333else if (def->storage != attribute->attstorage)
@@ -2369,7 +2378,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
23692378}
23702379
23712380/*
2372- *Copy default if any
2381+ *Locate default if any
23732382 */
23742383if (attribute->atthasdef)
23752384{
@@ -2391,23 +2400,59 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
23912400Assert(this_default != NULL);
23922401
23932402/*
2394- * If default expr could contain any vars, we'd need to fix
2395- * 'em, but it can't; so default is ready to apply to child.
2396- *
2397- * If we already had a default from some prior parent, check
2398- * to see if they are the same. If so, no problem; if not,
2399- * mark the column as having a bogus default. Below, we will
2400- * complain if the bogus default isn't overridden by the child
2401- * schema.
2403+ * If it's a GENERATED default, it might contain Vars that
2404+ * need to be mapped to the inherited column(s)' new numbers.
2405+ * We can't do that till newattno[] is ready, so just remember
2406+ * all the inherited default expressions for the moment.
24022407 */
2403- Assert(def->raw_default == NULL);
2404- if (def->cooked_default == NULL)
2405- def->cooked_default = this_default;
2406- else if (!equal(def->cooked_default, this_default))
2407- {
2408- def->cooked_default = &bogus_marker;
2409- have_bogus_defaults = true;
2410- }
2408+ inherited_defaults = lappend(inherited_defaults, this_default);
2409+ cols_with_defaults = lappend(cols_with_defaults, def);
2410+ }
2411+ }
2412+
2413+ /*
2414+ * Now process any inherited default expressions, adjusting attnos
2415+ * using the completed newattno[] map.
2416+ */
2417+ forboth(lc1, inherited_defaults, lc2, cols_with_defaults)
2418+ {
2419+ Node *this_default = (Node *) lfirst(lc1);
2420+ ColumnDef *def = (ColumnDef *) lfirst(lc2);
2421+ boolfound_whole_row;
2422+
2423+ /* Adjust Vars to match new table's column numbering */
2424+ this_default = map_variable_attnos(this_default,
2425+ 1, 0,
2426+ newattno, tupleDesc->natts,
2427+ InvalidOid, &found_whole_row);
2428+
2429+ /*
2430+ * For the moment we have to reject whole-row variables. We could
2431+ * convert them, if we knew the new table's rowtype OID, but that
2432+ * hasn't been assigned yet. (A variable could only appear in a
2433+ * generation expression, so the error message is correct.)
2434+ */
2435+ if (found_whole_row)
2436+ ereport(ERROR,
2437+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2438+ errmsg("cannot convert whole-row table reference"),
2439+ errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
2440+ def->colname,
2441+ RelationGetRelationName(relation))));
2442+
2443+ /*
2444+ * If we already had a default from some prior parent, check to
2445+ * see if they are the same. If so, no problem; if not, mark the
2446+ * column as having a bogus default. Below, we will complain if
2447+ * the bogus default isn't overridden by the child schema.
2448+ */
2449+ Assert(def->raw_default == NULL);
2450+ if (def->cooked_default == NULL)
2451+ def->cooked_default = this_default;
2452+ else if (!equal(def->cooked_default, this_default))
2453+ {
2454+ def->cooked_default = &bogus_marker;
2455+ have_bogus_defaults = true;
24112456}
24122457}
24132458
@@ -2625,7 +2670,6 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
26252670def->raw_default = newdef->raw_default;
26262671def->cooked_default = newdef->cooked_default;
26272672}
2628-
26292673}
26302674else
26312675{
@@ -3729,6 +3773,7 @@ AlterTableGetLockLevel(List *cmds)
37293773 * Theoretically, these could be ShareRowExclusiveLock.
37303774 */
37313775case AT_ColumnDefault:
3776+ case AT_CookedColumnDefault:
37323777case AT_AlterConstraint:
37333778case AT_AddIndex:/* from ADD CONSTRAINT */
37343779case AT_AddIndexConstraint:
@@ -3982,6 +4027,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
39824027/* No command-specific prep needed */
39834028pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
39844029break;
4030+ case AT_CookedColumnDefault:/* add a pre-cooked default */
4031+ /* This is currently used only in CREATE TABLE */
4032+ /* (so the permission check really isn't necessary) */
4033+ ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
4034+ /* This command never recurses */
4035+ pass = AT_PASS_ADD_CONSTR;
4036+ break;
39854037case AT_AddIdentity:
39864038ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
39874039/* This command never recurses */
@@ -4316,6 +4368,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
43164368case AT_ColumnDefault:/* ALTER COLUMN DEFAULT */
43174369address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
43184370break;
4371+ case AT_CookedColumnDefault:/* add a pre-cooked default */
4372+ address = ATExecCookedColumnDefault(rel, cmd->num, cmd->def);
4373+ break;
43194374case AT_AddIdentity:
43204375address = ATExecAddIdentity(rel, cmd->name, cmd->def, lockmode);
43214376break;
@@ -6564,6 +6619,35 @@ ATExecColumnDefault(Relation rel, const char *colName,
65646619return address;
65656620}
65666621
6622+ /*
6623+ * Add a pre-cooked default expression.
6624+ *
6625+ * Return the address of the affected column.
6626+ */
6627+ static ObjectAddress
6628+ ATExecCookedColumnDefault(Relation rel, AttrNumber attnum,
6629+ Node *newDefault)
6630+ {
6631+ ObjectAddress address;
6632+
6633+ /* We assume no checking is required */
6634+
6635+ /*
6636+ * Remove any old default for the column. We use RESTRICT here for
6637+ * safety, but at present we do not expect anything to depend on the
6638+ * default. (In ordinary cases, there could not be a default in place
6639+ * anyway, but it's possible when combining LIKE with inheritance.)
6640+ */
6641+ RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
6642+ true);
6643+
6644+ (void) StoreAttrDefault(rel, attnum, newDefault, true, false);
6645+
6646+ ObjectAddressSubSet(address, RelationRelationId,
6647+ RelationGetRelid(rel), attnum);
6648+ return address;
6649+ }
6650+
65676651/*
65686652 * ALTER TABLE ALTER COLUMN ADD IDENTITY
65696653 *