@@ -387,6 +387,8 @@ static bool ConstraintImpliedByRelConstraint(Relation scanrel,
387
387
List *testConstraint, List *provenConstraint);
388
388
static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
389
389
Node *newDefault, LOCKMODE lockmode);
390
+ static ObjectAddress ATExecCookedColumnDefault(Relation rel, AttrNumber attnum,
391
+ Node *newDefault);
390
392
static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
391
393
Node *def, LOCKMODE lockmode);
392
394
static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
@@ -2010,8 +2012,8 @@ storage_name(char c)
2010
2012
* 'schema' is the column/attribute definition for the table. (It's a list
2011
2013
* of ColumnDef's.) It is destructively changed.
2012
2014
* 'supers' is a list of OIDs of parent relations, already locked by caller.
2013
- * 'relpersistence' is a persistence type of the table.
2014
- * 'is_partition' tells if the table is a partition
2015
+ * 'relpersistence' is the persistence type of the table.
2016
+ * 'is_partition' tells if the table is a partition.
2015
2017
*
2016
2018
* Output arguments:
2017
2019
* 'supconstr' receives a list of constraints belonging to the parents,
@@ -2176,7 +2178,11 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2176
2178
TupleDesc tupleDesc;
2177
2179
TupleConstr *constr;
2178
2180
AttrNumber *newattno;
2181
+ List *inherited_defaults;
2182
+ List *cols_with_defaults;
2179
2183
AttrNumber parent_attno;
2184
+ ListCell *lc1;
2185
+ ListCell *lc2;
2180
2186
2181
2187
/* caller already got lock */
2182
2188
relation = table_open(parent, NoLock);
@@ -2263,6 +2269,9 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2263
2269
newattno = (AttrNumber *)
2264
2270
palloc0(tupleDesc->natts * sizeof(AttrNumber));
2265
2271
2272
+ /* We can't process inherited defaults until newattno[] is complete. */
2273
+ inherited_defaults = cols_with_defaults = NIL;
2274
+
2266
2275
for (parent_attno = 1; parent_attno <= tupleDesc->natts;
2267
2276
parent_attno++)
2268
2277
{
@@ -2318,7 +2327,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2318
2327
get_collation_name(defCollId),
2319
2328
get_collation_name(attribute->attcollation))));
2320
2329
2321
- /* Copy storage parameter */
2330
+ /* Copy/check storage parameter */
2322
2331
if (def->storage == 0)
2323
2332
def->storage = attribute->attstorage;
2324
2333
else if (def->storage != attribute->attstorage)
@@ -2369,7 +2378,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2369
2378
}
2370
2379
2371
2380
/*
2372
- * Copy default if any
2381
+ * Locate default if any
2373
2382
*/
2374
2383
if (attribute->atthasdef)
2375
2384
{
@@ -2391,23 +2400,59 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2391
2400
Assert(this_default != NULL);
2392
2401
2393
2402
/*
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.
2402
2407
*/
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
+ bool found_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;
2411
2456
}
2412
2457
}
2413
2458
@@ -2625,7 +2670,6 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
2625
2670
def->raw_default = newdef->raw_default;
2626
2671
def->cooked_default = newdef->cooked_default;
2627
2672
}
2628
-
2629
2673
}
2630
2674
else
2631
2675
{
@@ -3729,6 +3773,7 @@ AlterTableGetLockLevel(List *cmds)
3729
3773
* Theoretically, these could be ShareRowExclusiveLock.
3730
3774
*/
3731
3775
case AT_ColumnDefault:
3776
+ case AT_CookedColumnDefault:
3732
3777
case AT_AlterConstraint:
3733
3778
case AT_AddIndex: /* from ADD CONSTRAINT */
3734
3779
case AT_AddIndexConstraint:
@@ -3982,6 +4027,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
3982
4027
/* No command-specific prep needed */
3983
4028
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
3984
4029
break;
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;
3985
4037
case AT_AddIdentity:
3986
4038
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
3987
4039
/* This command never recurses */
@@ -4316,6 +4368,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
4316
4368
case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
4317
4369
address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
4318
4370
break;
4371
+ case AT_CookedColumnDefault: /* add a pre-cooked default */
4372
+ address = ATExecCookedColumnDefault(rel, cmd->num, cmd->def);
4373
+ break;
4319
4374
case AT_AddIdentity:
4320
4375
address = ATExecAddIdentity(rel, cmd->name, cmd->def, lockmode);
4321
4376
break;
@@ -6564,6 +6619,35 @@ ATExecColumnDefault(Relation rel, const char *colName,
6564
6619
return address;
6565
6620
}
6566
6621
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
+
6567
6651
/*
6568
6652
* ALTER TABLE ALTER COLUMN ADD IDENTITY
6569
6653
*
0 commit comments