Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 076ffbc

Browse files
committed
Fix missing values when doing ALTER TABLE ALTER COLUMN TYPE
This was an oversight in commit 16828d5. If the table is going to be rewritten, we simply clear all the missing values from all the table's attributes, since there will no longer be any rows with the attributes missing. Otherwise, we repackage the missing value in an array constructed with the new type specifications. Backpatch to release 11. This fixes bug #15446, reported by Dmitry Molotkov Reviewed by Dean Rasheed
1 parent 312d21d commit 076ffbc

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

src/backend/commands/tablecmds.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9384,6 +9384,21 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
93849384
HeapTuple depTup;
93859385
ObjectAddress address;
93869386

9387+
/*
9388+
* Clear all the missing values if we're rewriting the table, since this
9389+
* renders them pointless.
9390+
*/
9391+
if (tab->rewrite)
9392+
{
9393+
Relation newrel;
9394+
9395+
newrel = heap_open(RelationGetRelid(rel), NoLock);
9396+
RelationClearMissing(newrel);
9397+
relation_close(newrel, NoLock);
9398+
/* make sure we don't conflict with later attribute modifications */
9399+
CommandCounterIncrement();
9400+
}
9401+
93879402
attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
93889403

93899404
/* Look up the target column */
@@ -9700,7 +9715,69 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
97009715
/*
97019716
* Here we go --- change the recorded column type and collation. (Note
97029717
* heapTup is a copy of the syscache entry, so okay to scribble on.)
9718+
* First fix up the missing value if any.
97039719
*/
9720+
if (attTup->atthasmissing)
9721+
{
9722+
Datum missingval;
9723+
bool missingNull;
9724+
9725+
/* if rewrite is true the missing value should already be cleared */
9726+
Assert(tab->rewrite == 0);
9727+
9728+
/* Get the missing value datum */
9729+
missingval = heap_getattr(heapTup,
9730+
Anum_pg_attribute_attmissingval,
9731+
attrelation->rd_att,
9732+
&missingNull);
9733+
9734+
/* if it's a null array there is nothing to do */
9735+
9736+
if (! missingNull)
9737+
{
9738+
/*
9739+
* Get the datum out of the array and repack it in a new array
9740+
* built with the new type data. We assume that since the table
9741+
* doesn't need rewriting, the actual Datum doesn't need to be
9742+
* changed, only the array metadata.
9743+
*/
9744+
9745+
int one = 1;
9746+
bool isNull;
9747+
Datum valuesAtt[Natts_pg_attribute];
9748+
bool nullsAtt[Natts_pg_attribute];
9749+
bool replacesAtt[Natts_pg_attribute];
9750+
9751+
MemSet(valuesAtt, 0, sizeof(valuesAtt));
9752+
MemSet(nullsAtt, false, sizeof(nullsAtt));
9753+
MemSet(replacesAtt, false, sizeof(replacesAtt));
9754+
9755+
missingval = array_get_element(missingval,
9756+
1,
9757+
&one,
9758+
0,
9759+
attTup->attlen,
9760+
attTup->attbyval,
9761+
attTup->attalign,
9762+
&isNull);
9763+
missingval = PointerGetDatum(
9764+
construct_array(&missingval,
9765+
1,
9766+
targettype,
9767+
tform->typlen,
9768+
tform->typbyval,
9769+
tform->typalign));
9770+
9771+
valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
9772+
replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
9773+
nullsAtt[Anum_pg_attribute_attmissingval - 1] = false;
9774+
9775+
heapTup = heap_modify_tuple(heapTup, RelationGetDescr(attrelation),
9776+
valuesAtt, nullsAtt, replacesAtt);
9777+
attTup = (Form_pg_attribute) GETSTRUCT(heapTup);
9778+
}
9779+
}
9780+
97049781
attTup->atttypid = targettype;
97059782
attTup->atttypmod = targettypmod;
97069783
attTup->attcollation = targetcollid;

src/test/regress/expected/fast_default.out

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,44 @@ INSERT INTO leader VALUES (1, 1), (2, 2);
735735
ALTER TABLE leader ADD c int;
736736
ALTER TABLE leader DROP c;
737737
DELETE FROM leader;
738+
-- check that ALTER TABLE ... ALTER TYPE does the right thing
739+
CREATE TABLE vtype( a integer);
740+
INSERT INTO vtype VALUES (1);
741+
ALTER TABLE vtype ADD COLUMN b DOUBLE PRECISION DEFAULT 0.2;
742+
ALTER TABLE vtype ADD COLUMN c BOOLEAN DEFAULT true;
743+
SELECT * FROM vtype;
744+
a | b | c
745+
---+-----+---
746+
1 | 0.2 | t
747+
(1 row)
748+
749+
ALTER TABLE vtype
750+
ALTER b TYPE text USING b::text,
751+
ALTER c TYPE text USING c::text;
752+
NOTICE: rewriting table vtype for reason 4
753+
SELECT * FROM vtype;
754+
a | b | c
755+
---+-----+------
756+
1 | 0.2 | true
757+
(1 row)
758+
759+
-- also check the case that doesn't rewrite the table
760+
CREATE TABLE vtype2 (a int);
761+
INSERT INTO vtype2 VALUES (1);
762+
ALTER TABLE vtype2 ADD COLUMN b varchar(10) DEFAULT 'xxx';
763+
ALTER TABLE vtype2 ALTER COLUMN b SET DEFAULT 'yyy';
764+
INSERT INTO vtype2 VALUES (2);
765+
ALTER TABLE vtype2 ALTER COLUMN b TYPE varchar(20) USING b::varchar(20);
766+
SELECT * FROM vtype2;
767+
a | b
768+
---+-----
769+
1 | xxx
770+
2 | yyy
771+
(2 rows)
772+
738773
-- cleanup
774+
DROP TABLE vtype;
775+
DROP TABLE vtype2;
739776
DROP TABLE follower;
740777
DROP TABLE leader;
741778
DROP FUNCTION test_trigger();

src/test/regress/sql/fast_default.sql

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,33 @@ ALTER TABLE leader ADD c int;
481481
ALTER TABLE leader DROP c;
482482
DELETE FROM leader;
483483

484+
-- check that ALTER TABLE ... ALTER TYPE does the right thing
485+
486+
CREATE TABLE vtype( a integer);
487+
INSERT INTO vtype VALUES (1);
488+
ALTER TABLE vtype ADD COLUMN b DOUBLE PRECISION DEFAULT 0.2;
489+
ALTER TABLE vtype ADD COLUMN c BOOLEAN DEFAULT true;
490+
SELECT * FROM vtype;
491+
ALTER TABLE vtype
492+
ALTER b TYPE text USING b::text,
493+
ALTER c TYPE text USING c::text;
494+
SELECT * FROM vtype;
495+
496+
-- also check the case that doesn't rewrite the table
497+
498+
CREATE TABLE vtype2 (a int);
499+
INSERT INTO vtype2 VALUES (1);
500+
ALTER TABLE vtype2 ADD COLUMN b varchar(10) DEFAULT 'xxx';
501+
ALTER TABLE vtype2 ALTER COLUMN b SET DEFAULT 'yyy';
502+
INSERT INTO vtype2 VALUES (2);
503+
504+
ALTER TABLE vtype2 ALTER COLUMN b TYPE varchar(20) USING b::varchar(20);
505+
SELECT * FROM vtype2;
506+
507+
484508
-- cleanup
509+
DROP TABLE vtype;
510+
DROP TABLE vtype2;
485511
DROP TABLE follower;
486512
DROP TABLE leader;
487513
DROP FUNCTION test_trigger();

0 commit comments

Comments
 (0)