diff options
| author | Tom Lane | 2020-01-21 21:17:21 +0000 |
|---|---|---|
| committer | Tom Lane | 2020-01-21 21:17:21 +0000 |
| commit | 9b9c5f279e8261ab90dc64559911d2578288b7e9 (patch) | |
| tree | e189ac7d1cc3113b3f0302192f71c565a47fd616 /src/test | |
| parent | affdde2e15d9df6e9736bbb7e7cd9d56049d2f5a (diff) | |
Clarify behavior of adding and altering a column in same ALTER command.
The behavior of something like
ALTER TABLE transactions
ADD COLUMN status varchar(30) DEFAULT 'old',
ALTER COLUMN status SET default 'current';
is to fill existing table rows with 'old', not 'current'. That's
intentional and desirable for a couple of reasons:
* It makes the behavior the same whether you merge the sub-commands
into one ALTER command or give them separately;
* If we applied the new default while filling the table, there would
be no way to get the existing behavior in one SQL command.
The same reasoning applies in cases that add a column and then
manipulate its GENERATED/IDENTITY status in a second sub-command,
since the generation expression is really just a kind of default.
However, that wasn't very obvious (at least not to me; earlier in
the referenced discussion thread I'd thought it was a bug to be
fixed). And it certainly wasn't documented.
Hence, add documentation, code comments, and a test case to clarify
that this behavior is all intentional.
In passing, adjust ATExecAddColumn's defaults-related relkind check
so that it matches up exactly with ATRewriteTables, instead of being
effectively (though not literally) the negated inverse condition.
The reasoning can be explained a lot more concisely that way, too
(not to mention that the comment now matches the code, which it
did not before).
Discussion: https://postgr.es/m/10365.1558909428@sss.pgh.pa.us
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/identity.out | 6 | ||||
| -rw-r--r-- | src/test/regress/sql/identity.sql | 6 |
2 files changed, 12 insertions, 0 deletions
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out index 7cf4696ec95..1a614b85f99 100644 --- a/src/test/regress/expected/identity.out +++ b/src/test/regress/expected/identity.out @@ -409,6 +409,12 @@ ALTER TABLE itest8 ALTER COLUMN f5 DROP NOT NULL, ALTER COLUMN f5 SET DATA TYPE bigint; INSERT INTO itest8 VALUES(0), (1); +-- This does not work when the table isn't empty. That's intentional, +-- since ADD GENERATED should only affect later insertions: +ALTER TABLE itest8 + ADD COLUMN f22 int NOT NULL, + ALTER COLUMN f22 ADD GENERATED ALWAYS AS IDENTITY; +ERROR: column "f22" contains null values TABLE itest8; f1 | f2 | f3 | f4 | f5 ----+----+----+----+---- diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql index 685607c90c1..b4cdd21bdd4 100644 --- a/src/test/regress/sql/identity.sql +++ b/src/test/regress/sql/identity.sql @@ -269,6 +269,12 @@ ALTER TABLE itest8 INSERT INTO itest8 VALUES(0), (1); +-- This does not work when the table isn't empty. That's intentional, +-- since ADD GENERATED should only affect later insertions: +ALTER TABLE itest8 + ADD COLUMN f22 int NOT NULL, + ALTER COLUMN f22 ADD GENERATED ALWAYS AS IDENTITY; + TABLE itest8; \d+ itest8 \d itest8_f2_seq |
