@@ -405,6 +405,8 @@ static bool ConstraintImpliedByRelConstraint(Relation scanrel,
405405 List *testConstraint, List *provenConstraint);
406406static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
407407 Node *newDefault, LOCKMODE lockmode);
408+ static ObjectAddress ATExecCookedColumnDefault(Relation rel, AttrNumber attnum,
409+ Node *newDefault);
408410static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
409411 Node *def, LOCKMODE lockmode);
410412static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
@@ -2054,8 +2056,8 @@ storage_name(char c)
20542056 * 'schema' is the column/attribute definition for the table. (It's a list
20552057 *of ColumnDef's.) It is destructively changed.
20562058 * 'supers' is a list of OIDs of parent relations, already locked by caller.
2057- * 'relpersistence' isa persistence type of the table.
2058- * 'is_partition' tells if the table is a partition
2059+ * 'relpersistence' isthe persistence type of the table.
2060+ * 'is_partition' tells if the table is a partition.
20592061 *
20602062 * Output arguments:
20612063 * 'supconstr' receives a list of constraints belonging to the parents,
@@ -2218,7 +2220,11 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
22182220TupleDesctupleDesc;
22192221TupleConstr *constr;
22202222AttrMap *newattmap;
2223+ List *inherited_defaults;
2224+ List *cols_with_defaults;
22212225AttrNumberparent_attno;
2226+ ListCell *lc1;
2227+ ListCell *lc2;
22222228
22232229/* caller already got lock */
22242230relation = table_open(parent, NoLock);
@@ -2304,6 +2310,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
23042310 */
23052311newattmap = make_attrmap(tupleDesc->natts);
23062312
2313+ /* We can't process inherited defaults until newattmap is complete. */
2314+ inherited_defaults = cols_with_defaults = NIL;
2315+
23072316for (parent_attno = 1; parent_attno <= tupleDesc->natts;
23082317 parent_attno++)
23092318{
@@ -2359,7 +2368,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
23592368 get_collation_name(defCollId),
23602369 get_collation_name(attribute->attcollation))));
23612370
2362- /* Copy storage parameter */
2371+ /* Copy/check storage parameter */
23632372if (def->storage == 0)
23642373def->storage = attribute->attstorage;
23652374else if (def->storage != attribute->attstorage)
@@ -2410,7 +2419,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
24102419}
24112420
24122421/*
2413- *Copy default if any
2422+ *Locate default if any
24142423 */
24152424if (attribute->atthasdef)
24162425{
@@ -2432,23 +2441,59 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
24322441Assert(this_default != NULL);
24332442
24342443/*
2435- * If default expr could contain any vars, we'd need to fix
2436- * 'em, but it can't; so default is ready to apply to child.
2437- *
2438- * If we already had a default from some prior parent, check
2439- * to see if they are the same. If so, no problem; if not,
2440- * mark the column as having a bogus default. Below, we will
2441- * complain if the bogus default isn't overridden by the child
2442- * schema.
2444+ * If it's a GENERATED default, it might contain Vars that
2445+ * need to be mapped to the inherited column(s)' new numbers.
2446+ * We can't do that till newattmap is ready, so just remember
2447+ * all the inherited default expressions for the moment.
24432448 */
2444- Assert(def->raw_default == NULL);
2445- if (def->cooked_default == NULL)
2446- def->cooked_default = this_default;
2447- else if (!equal(def->cooked_default, this_default))
2448- {
2449- def->cooked_default = &bogus_marker;
2450- have_bogus_defaults = true;
2451- }
2449+ inherited_defaults = lappend(inherited_defaults, this_default);
2450+ cols_with_defaults = lappend(cols_with_defaults, def);
2451+ }
2452+ }
2453+
2454+ /*
2455+ * Now process any inherited default expressions, adjusting attnos
2456+ * using the completed newattmap map.
2457+ */
2458+ forboth(lc1, inherited_defaults, lc2, cols_with_defaults)
2459+ {
2460+ Node *this_default = (Node *) lfirst(lc1);
2461+ ColumnDef *def = (ColumnDef *) lfirst(lc2);
2462+ boolfound_whole_row;
2463+
2464+ /* Adjust Vars to match new table's column numbering */
2465+ this_default = map_variable_attnos(this_default,
2466+ 1, 0,
2467+ newattmap,
2468+ InvalidOid, &found_whole_row);
2469+
2470+ /*
2471+ * For the moment we have to reject whole-row variables. We could
2472+ * convert them, if we knew the new table's rowtype OID, but that
2473+ * hasn't been assigned yet. (A variable could only appear in a
2474+ * generation expression, so the error message is correct.)
2475+ */
2476+ if (found_whole_row)
2477+ ereport(ERROR,
2478+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2479+ errmsg("cannot convert whole-row table reference"),
2480+ errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
2481+ def->colname,
2482+ RelationGetRelationName(relation))));
2483+
2484+ /*
2485+ * If we already had a default from some prior parent, check to
2486+ * see if they are the same. If so, no problem; if not, mark the
2487+ * column as having a bogus default. Below, we will complain if
2488+ * the bogus default isn't overridden by the child schema.
2489+ */
2490+ Assert(def->raw_default == NULL);
2491+ if (def->cooked_default == NULL)
2492+ def->cooked_default = this_default;
2493+ else if (!equal(def->cooked_default, this_default))
2494+ {
2495+ def->cooked_default = &bogus_marker;
2496+ have_bogus_defaults = true;
24522497}
24532498}
24542499
@@ -2667,7 +2712,6 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
26672712def->raw_default = newdef->raw_default;
26682713def->cooked_default = newdef->cooked_default;
26692714}
2670-
26712715}
26722716else
26732717{
@@ -3781,6 +3825,7 @@ AlterTableGetLockLevel(List *cmds)
37813825 * Theoretically, these could be ShareRowExclusiveLock.
37823826 */
37833827case AT_ColumnDefault:
3828+ case AT_CookedColumnDefault:
37843829case AT_AlterConstraint:
37853830case AT_AddIndex:/* from ADD CONSTRAINT */
37863831case AT_AddIndexConstraint:
@@ -4040,6 +4085,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
40404085/* No command-specific prep needed */
40414086pass = cmd->def ? AT_PASS_ADD_OTHERCONSTR : AT_PASS_DROP;
40424087break;
4088+ case AT_CookedColumnDefault:/* add a pre-cooked default */
4089+ /* This is currently used only in CREATE TABLE */
4090+ /* (so the permission check really isn't necessary) */
4091+ ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
4092+ /* This command never recurses */
4093+ pass = AT_PASS_ADD_OTHERCONSTR;
4094+ break;
40434095case AT_AddIdentity:
40444096ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
40454097/* This command never recurses */
@@ -4398,6 +4450,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
43984450case AT_ColumnDefault:/* ALTER COLUMN DEFAULT */
43994451address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
44004452break;
4453+ case AT_CookedColumnDefault:/* add a pre-cooked default */
4454+ address = ATExecCookedColumnDefault(rel, cmd->num, cmd->def);
4455+ break;
44014456case AT_AddIdentity:
44024457cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode,
44034458 cur_pass, context);
@@ -6857,6 +6912,35 @@ ATExecColumnDefault(Relation rel, const char *colName,
68576912return address;
68586913}
68596914
6915+ /*
6916+ * Add a pre-cooked default expression.
6917+ *
6918+ * Return the address of the affected column.
6919+ */
6920+ static ObjectAddress
6921+ ATExecCookedColumnDefault(Relation rel, AttrNumber attnum,
6922+ Node *newDefault)
6923+ {
6924+ ObjectAddress address;
6925+
6926+ /* We assume no checking is required */
6927+
6928+ /*
6929+ * Remove any old default for the column. We use RESTRICT here for
6930+ * safety, but at present we do not expect anything to depend on the
6931+ * default. (In ordinary cases, there could not be a default in place
6932+ * anyway, but it's possible when combining LIKE with inheritance.)
6933+ */
6934+ RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
6935+ true);
6936+
6937+ (void) StoreAttrDefault(rel, attnum, newDefault, true, false);
6938+
6939+ ObjectAddressSubSet(address, RelationRelationId,
6940+ RelationGetRelid(rel), attnum);
6941+ return address;
6942+ }
6943+
68606944/*
68616945 * ALTER TABLE ALTER COLUMN ADD IDENTITY
68626946 *