| -- |
| -- Test ALTER TABLE ADD COLUMN WITH NULL DEFAULT on AO TABLES |
| -- |
| --- |
| --- basic support for alter add column with NULL default to AO tables |
| --- |
| drop table if exists ao1; |
| create table ao1(col1 varchar(2), col2 int) WITH (APPENDONLY=TRUE) distributed randomly; |
| |
| insert into ao1 values('aa', 1); |
| insert into ao1 values('bb', 2); |
| |
| -- following should be OK. |
| alter table ao1 add column col3 char(1) default 5; |
| |
| -- the following should be supported now |
| alter table ao1 add column col4 char(1) default NULL; |
| |
| select * from ao1; |
| insert into ao1 values('cc', 3); |
| select * from ao1; |
| |
| alter table ao1 alter column col4 drop default; |
| select * from ao1; |
| insert into ao1 values('dd', 4); |
| select * from ao1; |
| |
| alter table ao1 alter column col2 set default 2; |
| select pg_get_expr(adbin, adrelid) from pg_attrdef pdef, pg_attribute pattr |
| where pdef.adrelid='ao1'::regclass and pdef.adrelid=pattr.attrelid and pdef.adnum=pattr.attnum and pattr.attname='col2'; |
| |
| alter table ao1 rename col2 to col2_renamed; |
| |
| -- check dropping column |
| alter table ao1 drop column col4; |
| select attname from pg_attribute where attrelid='ao1'::regclass and attname='col4'; |
| |
| -- change the storage type of a column |
| alter table ao1 alter column col3 set storage plain; |
| select attname, attstorage from pg_attribute where attrelid='ao1'::regclass and attname='col3'; |
| alter table ao1 alter column col3 set storage main; |
| select attname, attstorage from pg_attribute where attrelid='ao1'::regclass and attname='col3'; |
| alter table ao1 alter column col3 set storage external; |
| select attname, attstorage from pg_attribute where attrelid='ao1'::regclass and attname='col3'; |
| alter table ao1 alter column col3 set storage extended; |
| select attname, attstorage from pg_attribute where attrelid='ao1'::regclass and attname='col3'; |
| |
| --- |
| --- check catalog contents after alter table on AO tables |
| --- |
| drop table if exists ao1; |
| create table ao1(col1 varchar(2), col2 int) WITH (APPENDONLY=TRUE) distributed randomly; |
| |
| -- relnatts is 2 |
| select relname, relnatts from pg_class where relname = 'ao1'; |
| |
| alter table ao1 add column col3 char(1) default NULL; |
| |
| -- relnatts in pg_class should be 3 |
| select relname, relnatts from pg_class where relname = 'ao1'; |
| |
| -- check col details in pg_attribute |
| select pg_class.relname, attname, typname from pg_attribute, pg_class, pg_type where attrelid = pg_class.oid and pg_class.relname = 'ao1' and atttypid = pg_type.oid and attname = 'col3'; |
| |
| -- There's an explicit entry in pg_attrdef for the NULL default (although it has |
| -- the same effect as no entry). |
| select relname, attname, pg_get_expr(adbin, adrelid) from pg_class, pg_attribute, pg_attrdef where attrelid = pg_class.oid and adrelid = pg_class.oid and adnum = pg_attribute.attnum and pg_class.relname = 'ao1'; |
| |
| |
| --- |
| --- check with IS NOT NULL constraint |
| --- |
| drop table if exists ao1; |
| create table ao1(col1 varchar(2), col2 int) WITH (APPENDONLY=TRUE) distributed randomly; |
| |
| insert into ao1 values('a', 1); |
| |
| -- should fail |
| alter table ao1 add column col3 char(1) not null default NULL; |
| |
| drop table if exists ao1; |
| create table ao1(col1 varchar(2), col2 int) WITH (APPENDONLY=TRUE) distributed randomly; |
| |
| -- should pass |
| alter table ao1 add column col3 char(1) not null default NULL; |
| |
| -- this should fail (same behavior as heap tables) |
| insert into ao1(col1, col2) values('a', 10); |
| --- |
| --- alter add with no default should continue to fail |
| --- |
| drop table if exists ao1; |
| create table ao1(col1 varchar(1)) with (APPENDONLY=TRUE) distributed randomly; |
| |
| insert into ao1 values('1'); |
| insert into ao1 values('1'); |
| insert into ao1 values('1'); |
| insert into ao1 values('1'); |
| |
| alter table ao1 add column col2 char(1); |
| select * from ao1; |
| |
| -- |
| -- MPP-19664 |
| -- Test ALTER TABLE ADD COLUMN WITH NULL DEFAULT on AO/CO TABLES |
| -- |
| --- |
| --- basic support for alter add column with NULL default to AO/CO tables |
| --- |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(2), col2 int) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| insert into aoco1 values('aa', 1); |
| insert into aoco1 values('bb', 2); |
| |
| -- following should be OK. |
| alter table aoco1 add column col3 char(1) default 5; |
| |
| -- the following should be supported now |
| alter table aoco1 add column col4 char(1) default NULL; |
| |
| select * from aoco1; |
| insert into aoco1 values('cc', 3); |
| select * from aoco1; |
| |
| alter table aoco1 alter column col4 drop default; |
| select * from aoco1; |
| insert into aoco1 values('dd', 4); |
| select * from aoco1; |
| |
| --- |
| --- check catalog contents after alter table on AO/CO tables |
| --- |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(2), col2 int) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| -- relnatts is 2 |
| select relname, relnatts from pg_class where relname = 'aoco1'; |
| |
| alter table aoco1 add column col3 char(1) default NULL; |
| |
| -- relnatts in pg_class should be 3 |
| select relname, relnatts from pg_class where relname = 'aoco1'; |
| |
| -- check col details in pg_attribute |
| select pg_class.relname, attname, typname from pg_attribute, pg_class, pg_type where attrelid = pg_class.oid and pg_class.relname = 'aoco1' and atttypid = pg_type.oid and attname = 'col3'; |
| |
| -- There's an explicit entry in pg_attrdef for the NULL default (although it has |
| -- the same effect as no entry). |
| select relname, attname, pg_get_expr(adbin, adrelid) from pg_class, pg_attribute, pg_attrdef where attrelid = pg_class.oid and adrelid = pg_class.oid and adnum = pg_attribute.attnum and pg_class.relname = 'aoco1'; |
| |
| --- |
| --- check with IS NOT NULL constraint |
| --- |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(2), col2 int) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| insert into aoco1 values('a', 1); |
| |
| -- should fail (rewrite needs to do null checking) |
| alter table aoco1 add column col3 char(1) not null default NULL; |
| alter table aoco1 add column c5 int check (c5 IS NOT NULL) default NULL; |
| |
| -- should fail (rewrite needs to do constraint checking) |
| insert into aoco1(col1, col2) values('a', NULL); |
| alter table aoco1 alter column col2 set not null; |
| |
| -- should pass (rewrite needs to do constraint checking) |
| alter table aoco1 alter column col2 type int; |
| |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(2), col2 int) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| -- should pass |
| alter table aoco1 add column col3 char(1) not null default NULL; |
| |
| -- this should fail (same behavior as heap tables) |
| insert into aoco1 (col1, col2) values('a', 10); |
| |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(2), col2 int not null) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| insert into aoco1 values('aa', 1); |
| alter table aoco1 add column col3 char(1) default NULL; |
| insert into aoco1 values('bb', 2); |
| select * from aoco1; |
| alter table aoco1 add column col4 char(1) not NULL default NULL; |
| select * from aoco1; |
| |
| --- |
| --- alter add with no default should continue to fail |
| --- |
| drop table if exists aoco1; |
| create table aoco1(col1 varchar(1)) |
| WITH (APPENDONLY=TRUE, ORIENTATION=column) distributed randomly; |
| |
| insert into aoco1 values('1'); |
| insert into aoco1 values('1'); |
| insert into aoco1 values('1'); |
| insert into aoco1 values('1'); |
| |
| alter table aoco1 add column col2 char(1); |
| select * from aoco1; |
| |
| drop table aoco1; |
| |
| --- |
| --- new column with a domain type |
| --- |
| drop table if exists ao1; |
| create table ao1(col1 varchar(5)) with (APPENDONLY=TRUE) distributed randomly; |
| |
| insert into ao1 values('abcde'); |
| |
| drop domain zipcode; |
| create domain zipcode as text |
| constraint c1 not null; |
| |
| -- following should fail |
| alter table ao1 add column col2 zipcode; |
| |
| alter table ao1 add column col2 zipcode default NULL; |
| |
| select * from ao1; |
| |
| -- cleanup |
| drop table ao1; |
| drop domain zipcode; |
| drop schema if exists mpp17582 cascade; |
| create schema mpp17582; |
| set search_path=mpp17582; |
| |
| DROP TABLE testbug_char5; |
| CREATE TABLE testbug_char5 |
| ( |
| timest character varying(6), |
| user_id numeric(16,0) NOT NULL, |
| to_be_drop char(5), -- Iterate through different data types |
| tag1 char(5), -- Iterate through different data types |
| tag2 char(5) |
| ) |
| DISTRIBUTED BY (user_id) |
| PARTITION BY LIST(timest) |
| ( |
| PARTITION part201203 VALUES('201203') WITH (APPENDONLY=true, COMPRESSLEVEL=5, ORIENTATION=column), |
| PARTITION part201204 VALUES('201204') WITH (APPENDONLY=true, COMPRESSLEVEL=5, ORIENTATION=row), |
| PARTITION part201205 VALUES('201205') |
| ); |
| |
| create index testbug_char5_tag1 on testbug_char5 using btree(tag1); |
| |
| insert into testbug_char5 (timest,user_id,to_be_drop) select '201203',1111,'10000'; |
| insert into testbug_char5 (timest,user_id,to_be_drop) select '201204',1111,'10000'; |
| insert into testbug_char5 (timest,user_id,to_be_drop) select '201205',1111,'10000'; |
| |
| analyze testbug_char5; |
| |
| select * from testbug_char5 order by 1,2; |
| |
| ALTER TABLE testbug_char5 drop column to_be_drop; |
| |
| select * from testbug_char5 order by 1,2; |
| |
| insert into testbug_char5 (timest,user_id,tag2) select '201203',2222,'2'; |
| insert into testbug_char5 (timest,user_id,tag2) select '201204',2222,'2'; |
| insert into testbug_char5 (timest,user_id,tag2) select '201205',2222,'2'; |
| |
| select * from testbug_char5 order by 1,2; |
| |
| alter table testbug_char5 add PARTITION part201206 VALUES('201206') WITH (APPENDONLY=true, COMPRESSLEVEL=5, ORIENTATION=column); |
| alter table testbug_char5 add PARTITION part201207 VALUES('201207') WITH (APPENDONLY=true, COMPRESSLEVEL=5, ORIENTATION=row); |
| alter table testbug_char5 add PARTITION part201208 VALUES('201208'); |
| |
| insert into testbug_char5 select '201206',3333,'1','2'; |
| insert into testbug_char5 select '201207',3333,'1','2'; |
| insert into testbug_char5 select '201208',3333,'1','2'; |
| |
| select * from testbug_char5 order by 1,2; |
| |
| -- Test exchanging partition and then rolling back |
| begin work; |
| create table testbug_char5_exchange (timest character varying(6), user_id numeric(16,0) NOT NULL, tag1 char(5), tag2 char(5)) |
| with (appendonly=true, compresstype=zlib, compresslevel=3) distributed by (user_id); |
| create index on testbug_char5_exchange using btree(tag1); |
| insert into testbug_char5_exchange values ('201205', 3333, '2', '2'); |
| alter table testbug_char5 truncate partition part201205; |
| select count(*) from testbug_char5; |
| alter table testbug_char5 exchange partition part201205 with table testbug_char5_exchange; |
| select count(*) from testbug_char5; |
| rollback work; |
| select count(*) from testbug_char5; |
| |
| -- Test AO hybrid partitioning scheme (range and list) w/ subpartitions |
| create table ao_multi_level_part_table (date date, region text, region1 text, amount decimal(10,2)) |
| with (appendonly=true, compresstype=zlib, compresslevel=1) |
| partition by range(date) subpartition by list(region) ( |
| partition part1 start(date '2008-01-01') end(date '2009-01-01') |
| (subpartition usa values ('usa'), subpartition asia values ('asia'), default subpartition def), |
| partition part2 start(date '2009-01-01') end(date '2010-01-01') |
| (subpartition usa values ('usa'), subpartition asia values ('asia'))); |
| |
| -- insert some data |
| insert into ao_multi_level_part_table values ('2008-02-02', 'usa', 'Texas', 10.05), ('2008-03-03', 'asia', 'China', 1.01); |
| insert into ao_multi_level_part_table values ('2009-02-02', 'usa', 'Utah', 10.05), ('2009-03-03', 'asia', 'Japan', 1.01); |
| |
| -- add a partition that is not a default partition |
| alter table ao_multi_level_part_table add partition part3 start(date '2010-01-01') end(date '2012-01-01') with (appendonly=true) |
| (subpartition usa values ('usa'), subpartition asia values ('asia'), default subpartition def); |
| |
| -- Add default partition (defaults to heap storage unless set with AO) |
| alter table ao_multi_level_part_table add default partition yearYYYY (default subpartition def); |
| SELECT am.amname FROM pg_class c LEFT JOIN pg_am am ON (c.relam = am.oid) |
| WHERE c.relname = 'ao_multi_level_part_table_1_prt_yearyyyy_2_prt_def'; |
| |
| alter table ao_multi_level_part_table drop partition yearYYYY; |
| alter table ao_multi_level_part_table add default partition yearYYYY with (appendonly=true) (default subpartition def); |
| SELECT am.amname FROM pg_class c LEFT JOIN pg_am am ON (c.relam = am.oid) |
| WHERE c.relname = 'ao_multi_level_part_table_1_prt_yearyyyy_2_prt_def'; |
| |
| -- index on atts 1, 4 |
| create index ao_mlp_idx on ao_multi_level_part_table(date, amount); |
| select indexname from pg_indexes where tablename='ao_multi_level_part_table'; |
| alter index ao_mlp_idx rename to ao_mlp_idx_renamed; |
| select indexname from pg_indexes where tablename='ao_multi_level_part_table'; |
| |
| -- truncate partitions until table is empty |
| select * from ao_multi_level_part_table; |
| truncate ao_multi_level_part_table_1_prt_part1_2_prt_asia; |
| select * from ao_multi_level_part_table; |
| alter table ao_multi_level_part_table truncate partition for ('2008-02-02'); |
| select * from ao_multi_level_part_table; |
| alter table ao_multi_level_part_table alter partition part2 truncate partition usa; |
| select * from ao_multi_level_part_table; |
| alter table ao_multi_level_part_table truncate partition part2; |
| select * from ao_multi_level_part_table; |
| |
| -- drop column in the partition table |
| select count(*) from pg_attribute where attrelid='ao_multi_level_part_table'::regclass and attname = 'region1'; |
| alter table ao_multi_level_part_table drop column region1; |
| select count(*) from pg_attribute where attrelid='ao_multi_level_part_table'::regclass and attname = 'region1'; |
| |
| -- splitting top partition of a multi-level partition should not work |
| alter table ao_multi_level_part_table split partition part3 at (date '2011-01-01') into (partition part3, partition part4); |
| |
| -- |
| -- Check index scan |
| -- |
| |
| set enable_seqscan=off; |
| set enable_indexscan=on; |
| |
| select * from testbug_char5 where tag1='1'; |
| |
| -- |
| -- Check NL Index scan plan |
| -- |
| |
| create table dim(tag1 char(5)); |
| insert into dim values('1'); |
| |
| set enable_hashjoin=off; |
| set enable_seqscan=off; |
| set enable_nestloop=on; |
| set enable_indexscan=on; |
| |
| select * from testbug_char5, dim where testbug_char5.tag1=dim.tag1; |
| |
| -- |
| -- Load from another table |
| -- |
| |
| DROP TABLE load; |
| CREATE TABLE load |
| ( |
| timest character varying(6), |
| user_id numeric(16,0) NOT NULL, |
| tag1 char(5), |
| tag2 char(5) |
| ) |
| DISTRIBUTED randomly; |
| |
| insert into load select '20120' || i , 1111 * (i + 2), '1','2' from generate_series(3,8) i; |
| select * from load; |
| |
| insert into testbug_char5 select * from load; |
| |
| select * from testbug_char5; |
| |
| -- |
| -- Update values |
| -- |
| |
| update testbug_char5 set tag1='6' where tag1='1' and timest='201208'; |
| update testbug_char5 set tag2='7' where tag2='1' and timest='201208'; |
| |
| select * from testbug_char5; |
| |
| set search_path=public; |
| drop schema if exists mpp17582 cascade; |
| |
| -- Test for tuple descriptor leak during row splitting |
| DROP TABLE IF EXISTS split_tupdesc_leak; |
| CREATE TABLE split_tupdesc_leak |
| ( |
| ym character varying(6) NOT NULL, |
| suid character varying(50) NOT NULL, |
| genre_ids character varying(20)[] |
| ) |
| WITH (APPENDONLY=true, ORIENTATION=row, COMPRESSTYPE=zlib, OIDS=FALSE) |
| DISTRIBUTED BY (suid) |
| PARTITION BY LIST(ym) |
| ( |
| DEFAULT PARTITION p_split_tupdesc_leak_ym WITH (appendonly=true, orientation=row, compresstype=zlib) |
| ); |
| |
| INSERT INTO split_tupdesc_leak VALUES ('201412','0001EC1TPEvT5SaJKIR5yYXlFQ7tS','{0}'); |
| |
| ALTER TABLE split_tupdesc_leak SPLIT DEFAULT PARTITION AT ('201412') |
| INTO (PARTITION p_split_tupdesc_leak_ym, PARTITION p_split_tupdesc_leak_ym_201412); |
| |
| DROP TABLE split_tupdesc_leak; |