mirror of https://github.com/citusdata/citus.git
1372 lines
58 KiB
Plaintext
1372 lines
58 KiB
Plaintext
--
|
|
-- MULTI_ALTER_TABLE_STATEMENTS
|
|
--
|
|
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 220000;
|
|
-- Check that we can run ALTER TABLE statements on distributed tables.
|
|
-- We set the shardid sequence here so that the shardids in this test
|
|
-- aren't affected by changes to the previous tests.
|
|
CREATE TABLE lineitem_alter (
|
|
l_orderkey bigint not null,
|
|
l_partkey integer not null,
|
|
l_suppkey integer not null,
|
|
l_linenumber integer not null,
|
|
l_quantity decimal(15, 2) not null,
|
|
l_extendedprice decimal(15, 2) not null,
|
|
l_discount decimal(15, 2) not null,
|
|
l_tax decimal(15, 2) not null,
|
|
l_returnflag char(1) not null,
|
|
l_linestatus char(1) not null,
|
|
l_shipdate date not null,
|
|
l_commitdate date not null,
|
|
l_receiptdate date not null,
|
|
l_shipinstruct char(25) not null,
|
|
l_shipmode char(10) not null,
|
|
l_comment varchar(44) not null
|
|
)
|
|
WITH ( fillfactor = 80 );
|
|
SELECT create_distributed_table('lineitem_alter', 'l_orderkey', 'append');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
SELECT master_create_empty_shard('lineitem_alter') AS shardid \gset
|
|
\set lineitem_1_data_file :abs_srcdir '/data/lineitem.1.data'
|
|
copy lineitem_alter FROM :'lineitem_1_data_file' with (delimiter '|', append_to_shard :shardid);
|
|
-- verify that the storage options made it to the table definitions
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter | {fillfactor=80}
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter_220000 | {fillfactor=80}
|
|
(1 row)
|
|
|
|
\c - - - :master_port
|
|
-- Verify that we can add columns
|
|
ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT;
|
|
ALTER TABLE lineitem_alter ADD COLUMN date_column DATE;
|
|
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER DEFAULT 1;
|
|
ALTER TABLE lineitem_alter ADD COLUMN int_column2 INTEGER DEFAULT 2;
|
|
ALTER TABLE lineitem_alter ADD COLUMN null_column INTEGER;
|
|
-- show changed schema on one worker
|
|
\c - - - :worker_1_port
|
|
SELECT attname, atttypid::regtype
|
|
FROM
|
|
(SELECT oid FROM pg_class WHERE relname LIKE 'lineitem_alter_%' ORDER BY relname LIMIT 1) pc
|
|
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
|
ORDER BY attnum;
|
|
attname | atttypid
|
|
---------------------------------------------------------------------
|
|
tableoid | oid
|
|
cmax | cid
|
|
xmax | xid
|
|
cmin | cid
|
|
xmin | xid
|
|
ctid | tid
|
|
l_orderkey | bigint
|
|
l_partkey | integer
|
|
l_suppkey | integer
|
|
l_linenumber | integer
|
|
l_quantity | numeric
|
|
l_extendedprice | numeric
|
|
l_discount | numeric
|
|
l_tax | numeric
|
|
l_returnflag | character
|
|
l_linestatus | character
|
|
l_shipdate | date
|
|
l_commitdate | date
|
|
l_receiptdate | date
|
|
l_shipinstruct | character
|
|
l_shipmode | character
|
|
l_comment | character varying
|
|
float_column | double precision
|
|
date_column | date
|
|
int_column1 | integer
|
|
int_column2 | integer
|
|
null_column | integer
|
|
(27 rows)
|
|
|
|
\c - - - :master_port
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
float_column | double precision |
|
|
date_column | date |
|
|
int_column1 | integer | default 1
|
|
int_column2 | integer | default 2
|
|
null_column | integer |
|
|
(21 rows)
|
|
|
|
SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column;
|
|
float_column | count
|
|
---------------------------------------------------------------------
|
|
| 6000
|
|
(1 row)
|
|
|
|
SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
|
int_column1 | count
|
|
---------------------------------------------------------------------
|
|
1 | 6000
|
|
(1 row)
|
|
|
|
-- Verify that SET|DROP DEFAULT works
|
|
ALTER TABLE lineitem_alter ALTER COLUMN float_column SET DEFAULT 1;
|
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column1 DROP DEFAULT;
|
|
-- COPY to verify that default values take effect
|
|
SELECT master_create_empty_shard('lineitem_alter') as shardid \gset
|
|
copy lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM :'lineitem_1_data_file' with (delimiter '|', append_to_shard :shardid);
|
|
SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column;
|
|
float_column | count
|
|
---------------------------------------------------------------------
|
|
| 6000
|
|
1 | 6000
|
|
(2 rows)
|
|
|
|
SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
|
int_column1 | count
|
|
---------------------------------------------------------------------
|
|
| 6000
|
|
1 | 6000
|
|
(2 rows)
|
|
|
|
-- Verify that SET NOT NULL works
|
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
float_column | double precision | default 1
|
|
date_column | date |
|
|
int_column1 | integer |
|
|
int_column2 | integer | not null default 2
|
|
null_column | integer |
|
|
(21 rows)
|
|
|
|
-- Drop default so that NULLs will be inserted for this column
|
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT;
|
|
-- COPY should fail because it will try to insert NULLs for a NOT NULL column
|
|
-- Note, this operation will create a table on the workers but it won't be in the metadata
|
|
BEGIN;
|
|
SELECT master_create_empty_shard('lineitem_alter') as shardid \gset
|
|
copy lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM :'lineitem_1_data_file' with (delimiter '|', append_to_shard :shardid);
|
|
ERROR: null value in column "int_column2" violates not-null constraint
|
|
DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02, N, O, 1996-03-13, 1996-02-12, 1996-03-22, DELIVER IN PERSON , TRUCK , egular courts above the, 1, null, null, null, null).
|
|
END;
|
|
-- Verify that DROP NOT NULL works
|
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
float_column | double precision | default 1
|
|
date_column | date |
|
|
int_column1 | integer |
|
|
int_column2 | integer |
|
|
null_column | integer |
|
|
(21 rows)
|
|
|
|
-- COPY should succeed now
|
|
SELECT master_create_empty_shard('lineitem_alter') as shardid \gset
|
|
copy lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM :'lineitem_1_data_file' with (delimiter '|', append_to_shard :shardid);
|
|
SELECT count(*) from lineitem_alter;
|
|
count
|
|
---------------------------------------------------------------------
|
|
18000
|
|
(1 row)
|
|
|
|
-- Verify that SET DATA TYPE works
|
|
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
|
int_column2 | pg_typeof | count
|
|
---------------------------------------------------------------------
|
|
| integer | 6000
|
|
2 | integer | 12000
|
|
(2 rows)
|
|
|
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
float_column | double precision | default 1
|
|
date_column | date |
|
|
int_column1 | integer |
|
|
int_column2 | double precision |
|
|
null_column | integer |
|
|
(21 rows)
|
|
|
|
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
|
int_column2 | pg_typeof | count
|
|
---------------------------------------------------------------------
|
|
| double precision | 6000
|
|
2 | double precision | 12000
|
|
(2 rows)
|
|
|
|
-- Verify that DROP COLUMN works
|
|
ALTER TABLE lineitem_alter DROP COLUMN int_column1;
|
|
ALTER TABLE lineitem_alter DROP COLUMN float_column;
|
|
ALTER TABLE lineitem_alter DROP COLUMN date_column;
|
|
-- Verify that RENAME COLUMN works
|
|
ALTER TABLE lineitem_alter RENAME COLUMN l_orderkey TO l_orderkey_renamed;
|
|
SELECT SUM(l_orderkey_renamed) FROM lineitem_alter;
|
|
sum
|
|
---------------------------------------------------------------------
|
|
53620791
|
|
(1 row)
|
|
|
|
-- Verify that IF EXISTS works as expected
|
|
ALTER TABLE non_existent_table ADD COLUMN new_column INTEGER;
|
|
ERROR: relation "non_existent_table" does not exist
|
|
ALTER TABLE IF EXISTS non_existent_table ADD COLUMN new_column INTEGER;
|
|
NOTICE: relation "non_existent_table" does not exist, skipping
|
|
ALTER TABLE IF EXISTS lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE INTEGER;
|
|
ALTER TABLE lineitem_alter DROP COLUMN non_existent_column;
|
|
ERROR: column "non_existent_column" of relation "lineitem_alter" does not exist
|
|
ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS non_existent_column;
|
|
NOTICE: column "non_existent_column" of relation "lineitem_alter" does not exist, skipping
|
|
ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS int_column2;
|
|
-- Verify with IF EXISTS for extant table
|
|
ALTER TABLE IF EXISTS lineitem_alter RENAME COLUMN l_orderkey_renamed TO l_orderkey;
|
|
SELECT SUM(l_orderkey) FROM lineitem_alter;
|
|
sum
|
|
---------------------------------------------------------------------
|
|
53620791
|
|
(1 row)
|
|
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
null_column | integer |
|
|
(17 rows)
|
|
|
|
-- Verify that we can execute commands with multiple subcommands
|
|
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER,
|
|
ADD COLUMN int_column2 INTEGER;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
null_column | integer |
|
|
int_column1 | integer |
|
|
int_column2 | integer |
|
|
(19 rows)
|
|
|
|
ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER,
|
|
ALTER COLUMN int_column1 SET STATISTICS 10;
|
|
ERROR: alter table command is currently unsupported
|
|
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported.
|
|
ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
null_column | integer |
|
|
(17 rows)
|
|
|
|
-- Verify that we cannot execute alter commands on the distribution column
|
|
ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey DROP NOT NULL;
|
|
ERROR: cannot execute ALTER TABLE command involving partition column
|
|
ALTER TABLE lineitem_alter DROP COLUMN l_orderkey;
|
|
ERROR: cannot execute ALTER TABLE command involving partition column
|
|
-- Verify that we error out on unsupported statement types
|
|
ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100;
|
|
ERROR: alter table command is currently unsupported
|
|
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported.
|
|
ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint;
|
|
NOTICE: constraint "non_existent_contraint" of relation "lineitem_alter" does not exist, skipping
|
|
ALTER TABLE lineitem_alter SET WITHOUT OIDS;
|
|
ERROR: alter table command is currently unsupported
|
|
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported.
|
|
-- Verify that we error out in case of postgres errors on supported statement
|
|
-- types
|
|
ALTER TABLE lineitem_alter ADD COLUMN new_column non_existent_type;
|
|
ERROR: type "non_existent_type" does not exist
|
|
ALTER TABLE lineitem_alter ALTER COLUMN null_column SET NOT NULL;
|
|
ERROR: column "null_column" contains null values
|
|
CONTEXT: while executing command on localhost:xxxxx
|
|
ALTER TABLE lineitem_alter ALTER COLUMN l_partkey SET DEFAULT 'a';
|
|
ERROR: invalid input syntax for type integer: "a"
|
|
-- Verify that we error out on RENAME CONSTRAINT statement
|
|
ALTER TABLE lineitem_alter RENAME CONSTRAINT constraint_a TO constraint_b;
|
|
ERROR: renaming constraints belonging to distributed tables is currently unsupported
|
|
-- Verify that IF EXISTS works as expected with RENAME statements
|
|
ALTER TABLE non_existent_table RENAME TO non_existent_table_renamed;
|
|
ERROR: relation "non_existent_table" does not exist
|
|
ALTER TABLE IF EXISTS non_existent_table RENAME TO non_existent_table_renamed;
|
|
NOTICE: relation "non_existent_table" does not exist, skipping
|
|
ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2;
|
|
NOTICE: relation "non_existent_table" does not exist, skipping
|
|
-- Verify that none of the failed alter table commands took effect on the master
|
|
-- node
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
null_column | integer |
|
|
(17 rows)
|
|
|
|
-- verify that non-propagated ddl commands are allowed inside a transaction block
|
|
SET citus.enable_ddl_propagation to false;
|
|
BEGIN;
|
|
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
|
COMMIT;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
temp_index_1 | lineitem_alter
|
|
(1 row)
|
|
|
|
DROP INDEX temp_index_1;
|
|
-- verify that single distributed ddl commands are allowed inside a transaction block
|
|
SET citus.enable_ddl_propagation to true;
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
COMMIT;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
temp_index_2 | lineitem_alter
|
|
(1 row)
|
|
|
|
DROP INDEX temp_index_2;
|
|
-- and so are multiple ddl statements
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
|
COMMIT;
|
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
|
Column | Type | Modifiers
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | not null
|
|
l_partkey | integer | not null
|
|
l_suppkey | integer | not null
|
|
l_linenumber | integer | not null
|
|
l_quantity | numeric(15,2) | not null
|
|
l_extendedprice | numeric(15,2) | not null
|
|
l_discount | numeric(15,2) | not null
|
|
l_tax | numeric(15,2) | not null
|
|
l_returnflag | character(1) | not null
|
|
l_linestatus | character(1) | not null
|
|
l_shipdate | date | not null
|
|
l_commitdate | date | not null
|
|
l_receiptdate | date | not null
|
|
l_shipinstruct | character(25) | not null
|
|
l_shipmode | character(10) | not null
|
|
l_comment | character varying(44) | not null
|
|
null_column | integer |
|
|
first | integer |
|
|
(18 rows)
|
|
|
|
SELECT "Column", "Type", "Definition" FROM index_attrs WHERE
|
|
relid = 'temp_index_2'::regclass;
|
|
Column | Type | Definition
|
|
---------------------------------------------------------------------
|
|
l_orderkey | bigint | l_orderkey
|
|
(1 row)
|
|
|
|
ALTER TABLE lineitem_alter DROP COLUMN first;
|
|
DROP INDEX temp_index_2;
|
|
-- ensure that user-specified rollback causes full rollback
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
CREATE INDEX temp_index_3 ON lineitem_alter(l_partkey);
|
|
ROLLBACK;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- ensure that errors cause full rollback
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
ERROR: relation "temp_index_2" already exists
|
|
ROLLBACK;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- verify that SAVEPOINT is allowed...
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
SAVEPOINT my_savepoint;
|
|
CREATE INDEX temp_index_3 ON lineitem_alter(l_partkey);
|
|
ROLLBACK;
|
|
-- and also rolling back to it is also allowed
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
SAVEPOINT my_savepoint;
|
|
CREATE INDEX temp_index_3 ON lineitem_alter(l_partkey);
|
|
ROLLBACK TO my_savepoint;
|
|
COMMIT;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
temp_index_2 | lineitem_alter
|
|
(1 row)
|
|
|
|
DROP INDEX temp_index_2;
|
|
-- Add column on only one worker...
|
|
\c - - - :worker_2_port
|
|
ALTER TABLE lineitem_alter_220000 ADD COLUMN first integer;
|
|
\c - - - :master_port
|
|
-- and try to add it in a multi-statement block, which fails
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
|
ERROR: column "first" of relation "lineitem_alter_220000" already exists
|
|
CONTEXT: while executing command on localhost:xxxxx
|
|
COMMIT;
|
|
-- Nothing from the block should have committed
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- Create single-shard table (to avoid deadlocks in the upcoming test hackery)
|
|
CREATE TABLE single_shard_items (id integer NOT NULL, name text);
|
|
SET citus.shard_count TO 1;
|
|
SET citus.shard_replication_factor TO 2;
|
|
SELECT create_distributed_table('single_shard_items', 'id', 'hash');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
-- Verify that ALTER TABLE .. REPLICATION IDENTITY [USING INDEX]* .. works
|
|
CREATE UNIQUE INDEX replica_idx on single_shard_items(id);
|
|
SELECT relreplident FROM pg_class WHERE relname = 'single_shard_items';
|
|
relreplident
|
|
---------------------------------------------------------------------
|
|
d
|
|
(1 row)
|
|
|
|
SELECT run_command_on_workers('SELECT relreplident FROM pg_class WHERE relname LIKE ''single_shard_items_%'' LIMIT 1;');
|
|
run_command_on_workers
|
|
---------------------------------------------------------------------
|
|
(localhost,57637,t,d)
|
|
(localhost,57638,t,d)
|
|
(2 rows)
|
|
|
|
ALTER TABLE single_shard_items REPLICA IDENTITY nothing;
|
|
SELECT relreplident FROM pg_class WHERE relname = 'single_shard_items';
|
|
relreplident
|
|
---------------------------------------------------------------------
|
|
n
|
|
(1 row)
|
|
|
|
SELECT run_command_on_workers('SELECT relreplident FROM pg_class WHERE relname LIKE ''single_shard_items_%'' LIMIT 1;');
|
|
run_command_on_workers
|
|
---------------------------------------------------------------------
|
|
(localhost,57637,t,n)
|
|
(localhost,57638,t,n)
|
|
(2 rows)
|
|
|
|
ALTER TABLE single_shard_items REPLICA IDENTITY full;
|
|
SELECT relreplident FROM pg_class WHERE relname = 'single_shard_items';
|
|
relreplident
|
|
---------------------------------------------------------------------
|
|
f
|
|
(1 row)
|
|
|
|
SELECT run_command_on_workers('SELECT relreplident FROM pg_class WHERE relname LIKE ''single_shard_items_%'' LIMIT 1;');
|
|
run_command_on_workers
|
|
---------------------------------------------------------------------
|
|
(localhost,57637,t,f)
|
|
(localhost,57638,t,f)
|
|
(2 rows)
|
|
|
|
ALTER TABLE single_shard_items REPLICA IDENTITY USING INDEX replica_idx;
|
|
SELECT relreplident FROM pg_class WHERE relname = 'single_shard_items';
|
|
relreplident
|
|
---------------------------------------------------------------------
|
|
i
|
|
(1 row)
|
|
|
|
SELECT run_command_on_workers('SELECT relreplident FROM pg_class WHERE relname LIKE ''single_shard_items_%'' LIMIT 1;');
|
|
run_command_on_workers
|
|
---------------------------------------------------------------------
|
|
(localhost,57637,t,i)
|
|
(localhost,57638,t,i)
|
|
(2 rows)
|
|
|
|
ALTER TABLE single_shard_items REPLICA IDENTITY default, REPLICA IDENTITY USING INDEX replica_idx, REPLICA IDENTITY nothing;
|
|
SELECT relreplident FROM pg_class WHERE relname = 'single_shard_items';
|
|
relreplident
|
|
---------------------------------------------------------------------
|
|
n
|
|
(1 row)
|
|
|
|
SELECT run_command_on_workers('SELECT relreplident FROM pg_class WHERE relname LIKE ''single_shard_items_%'' LIMIT 1;');
|
|
run_command_on_workers
|
|
---------------------------------------------------------------------
|
|
(localhost,57637,t,n)
|
|
(localhost,57638,t,n)
|
|
(2 rows)
|
|
|
|
ALTER TABLE single_shard_items ADD COLUMN test_col int, REPLICA IDENTITY full;
|
|
DROP INDEX replica_idx;
|
|
ALTER TABLE single_shard_items REPLICA IDENTITY default;
|
|
-- Drop the column from the worker...
|
|
\c - - - :worker_2_port
|
|
ALTER TABLE lineitem_alter_220000 DROP COLUMN first;
|
|
-- Create table to trigger at-xact-end (deferred) failure
|
|
CREATE TABLE ddl_commands (command text UNIQUE DEFERRABLE INITIALLY DEFERRED);
|
|
-- Use an event trigger to log all DDL event tags in it
|
|
SET citus.enable_metadata_sync TO OFF;
|
|
CREATE FUNCTION log_ddl_tag() RETURNS event_trigger AS $ldt$
|
|
BEGIN
|
|
INSERT INTO ddl_commands VALUES (tg_tag);
|
|
END;
|
|
$ldt$ LANGUAGE plpgsql;
|
|
RESET citus.enable_metadata_sync;
|
|
CREATE EVENT TRIGGER log_ddl_tag ON ddl_command_end EXECUTE PROCEDURE log_ddl_tag();
|
|
\c - - - :master_port
|
|
-- The above trigger will cause failure at transaction end on one placement.
|
|
-- Citus always uses 2PC. 2PC should handle this "best" (no divergence)
|
|
BEGIN;
|
|
CREATE INDEX single_index_2 ON single_shard_items(id);
|
|
CREATE INDEX single_index_3 ON single_shard_items(name);
|
|
COMMIT;
|
|
ERROR: duplicate key value violates unique constraint "ddl_commands_command_key"
|
|
DETAIL: Key (command)=(CREATE INDEX) already exists.
|
|
CONTEXT: while executing command on localhost:xxxxx
|
|
-- Nothing from the block should have committed
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'single_shard_items' ORDER BY 1;
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
\c - - - :worker_2_port
|
|
DROP EVENT TRIGGER log_ddl_tag;
|
|
DROP FUNCTION log_ddl_tag();
|
|
DROP TABLE ddl_commands;
|
|
\c - - - :master_port
|
|
-- Distributed SELECTs may appear after ALTER
|
|
BEGIN;
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
SELECT count(*) FROM lineitem_alter;
|
|
count
|
|
---------------------------------------------------------------------
|
|
18000
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- and before
|
|
BEGIN;
|
|
SELECT count(*) FROM lineitem_alter;
|
|
count
|
|
---------------------------------------------------------------------
|
|
18000
|
|
(1 row)
|
|
|
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
|
COMMIT;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
temp_index_2 | lineitem_alter
|
|
(1 row)
|
|
|
|
DROP INDEX temp_index_2;
|
|
-- verify that distributed ddl commands are allowed without transaction block as well
|
|
-- Reminder: Now Citus always uses 2PC
|
|
CREATE INDEX temp_index_3 ON lineitem_alter(l_orderkey);
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
temp_index_3 | lineitem_alter
|
|
(1 row)
|
|
|
|
DROP INDEX temp_index_3;
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- verify that not any of shard placements are marked as failed when a query failure occurs
|
|
CREATE TABLE test_ab (a int, b int);
|
|
SET citus.shard_count TO 8;
|
|
SELECT create_distributed_table('test_ab', 'a', 'hash');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
INSERT INTO test_ab VALUES (2, 10);
|
|
INSERT INTO test_ab VALUES (2, 11);
|
|
CREATE UNIQUE INDEX temp_unique_index_1 ON test_ab(a);
|
|
ERROR: could not create unique index "temp_unique_index_1_220011"
|
|
DETAIL: Key (a)=(2) is duplicated.
|
|
CONTEXT: while executing command on localhost:xxxxx
|
|
SELECT shardid FROM pg_dist_shard_placement NATURAL JOIN pg_dist_shard
|
|
WHERE logicalrelid='test_ab'::regclass AND shardstate=3;
|
|
shardid
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- Check that the schema on the worker still looks reasonable
|
|
\c - - - :worker_1_port
|
|
SELECT attname, atttypid::regtype
|
|
FROM
|
|
(SELECT oid FROM pg_class WHERE relname LIKE 'lineitem_alter_%' ORDER BY relname LIMIT 1) pc
|
|
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
|
ORDER BY attnum;
|
|
attname | atttypid
|
|
---------------------------------------------------------------------
|
|
tableoid | oid
|
|
cmax | cid
|
|
xmax | xid
|
|
cmin | cid
|
|
xmin | xid
|
|
ctid | tid
|
|
l_orderkey | bigint
|
|
l_partkey | integer
|
|
l_suppkey | integer
|
|
l_linenumber | integer
|
|
l_quantity | numeric
|
|
l_extendedprice | numeric
|
|
l_discount | numeric
|
|
l_tax | numeric
|
|
l_returnflag | character
|
|
l_linestatus | character
|
|
l_shipdate | date
|
|
l_commitdate | date
|
|
l_receiptdate | date
|
|
l_shipinstruct | character
|
|
l_shipmode | character
|
|
l_comment | character varying
|
|
........pg.dropped.17........ | -
|
|
........pg.dropped.18........ | -
|
|
........pg.dropped.19........ | -
|
|
........pg.dropped.20........ | -
|
|
null_column | integer
|
|
........pg.dropped.22........ | -
|
|
........pg.dropped.23........ | -
|
|
........pg.dropped.24........ | -
|
|
(30 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify that we can rename distributed tables
|
|
SHOW citus.enable_ddl_propagation;
|
|
citus.enable_ddl_propagation
|
|
---------------------------------------------------------------------
|
|
on
|
|
(1 row)
|
|
|
|
ALTER TABLE lineitem_alter RENAME TO lineitem_renamed;
|
|
-- verify rename is performed
|
|
SELECT relname FROM pg_class WHERE relname = 'lineitem_renamed';
|
|
relname
|
|
---------------------------------------------------------------------
|
|
lineitem_renamed
|
|
(1 row)
|
|
|
|
-- show rename worked on one worker, too
|
|
\c - - - :worker_1_port
|
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_renamed%' ORDER BY relname;
|
|
relname
|
|
---------------------------------------------------------------------
|
|
lineitem_renamed_220000
|
|
lineitem_renamed_220001
|
|
lineitem_renamed_220003
|
|
(3 rows)
|
|
|
|
\c - - - :master_port
|
|
-- revert it to original name
|
|
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
|
-- show rename worked on one worker, too
|
|
\c - - - :worker_1_port
|
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
|
relname
|
|
---------------------------------------------------------------------
|
|
lineitem_alter_220000
|
|
lineitem_alter_220001
|
|
lineitem_alter_220003
|
|
(3 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify that we can set and reset storage parameters
|
|
ALTER TABLE lineitem_alter SET(fillfactor=40);
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter | {fillfactor=40}
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter_220000 | {fillfactor=40}
|
|
lineitem_alter_220001 | {fillfactor=40}
|
|
lineitem_alter_220003 | {fillfactor=40}
|
|
(3 rows)
|
|
|
|
\c - - - :master_port
|
|
ALTER TABLE lineitem_alter RESET(fillfactor);
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter |
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
lineitem_alter_220000 |
|
|
lineitem_alter_220001 |
|
|
lineitem_alter_220003 |
|
|
(3 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify that we can rename indexes on distributed tables
|
|
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
|
ALTER INDEX temp_index_1 RENAME TO idx_lineitem_linenumber;
|
|
-- verify rename is performed
|
|
SELECT relname FROM pg_class WHERE relname = 'idx_lineitem_linenumber';
|
|
relname
|
|
---------------------------------------------------------------------
|
|
idx_lineitem_linenumber
|
|
(1 row)
|
|
|
|
-- show rename worked on one worker, too
|
|
\c - - - :worker_1_port
|
|
SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%' ORDER BY relname;
|
|
relname
|
|
---------------------------------------------------------------------
|
|
idx_lineitem_linenumber_220000
|
|
idx_lineitem_linenumber_220001
|
|
idx_lineitem_linenumber_220003
|
|
(3 rows)
|
|
|
|
\c - - - :master_port
|
|
-- now get rid of the index
|
|
DROP INDEX idx_lineitem_linenumber;
|
|
-- verify that we don't intercept DDL commands if propagation is turned off
|
|
SET citus.enable_ddl_propagation to false;
|
|
-- table rename statement can be performed on the coordinator only now
|
|
ALTER TABLE lineitem_alter RENAME TO lineitem_renamed;
|
|
-- verify rename is performed
|
|
SELECT relname FROM pg_class WHERE relname = 'lineitem_alter' or relname = 'lineitem_renamed';
|
|
relname
|
|
---------------------------------------------------------------------
|
|
lineitem_renamed
|
|
(1 row)
|
|
|
|
-- revert it to original name
|
|
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
|
-- this column is added to master table and not workers
|
|
ALTER TABLE lineitem_alter ADD COLUMN column_only_added_to_master int;
|
|
-- verify newly added column is not present in a worker shard
|
|
\c - - - :worker_1_port
|
|
SELECT column_only_added_to_master FROM lineitem_alter_220000 LIMIT 0;
|
|
ERROR: column "column_only_added_to_master" does not exist
|
|
\c - - - :master_port
|
|
-- ddl propagation flag is reset to default, disable it again
|
|
SET citus.enable_ddl_propagation to false;
|
|
-- following query succeeds since it accesses an previously existing column
|
|
SELECT l_orderkey FROM lineitem_alter LIMIT 0;
|
|
l_orderkey
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- make master and workers have the same schema again
|
|
ALTER TABLE lineitem_alter DROP COLUMN column_only_added_to_master;
|
|
-- now this should succeed
|
|
SELECT * FROM lineitem_alter LIMIT 0;
|
|
l_orderkey | l_partkey | l_suppkey | l_linenumber | l_quantity | l_extendedprice | l_discount | l_tax | l_returnflag | l_linestatus | l_shipdate | l_commitdate | l_receiptdate | l_shipinstruct | l_shipmode | l_comment | null_column
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
-- previously unsupported statements are accepted by postgresql now
|
|
ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100;
|
|
ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint;
|
|
NOTICE: constraint "non_existent_contraint" of relation "lineitem_alter" does not exist, skipping
|
|
ALTER TABLE lineitem_alter SET WITHOUT OIDS;
|
|
-- distribution column still cannot be dropped.
|
|
ALTER TABLE lineitem_alter DROP COLUMN l_orderkey;
|
|
ERROR: cannot execute ALTER TABLE command dropping partition column
|
|
-- Even unique indexes on l_partkey (non-partition column) are allowed.
|
|
-- Citus would have prevented that.
|
|
CREATE UNIQUE INDEX unique_lineitem_partkey on lineitem_alter(l_partkey);
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
unique_lineitem_partkey | lineitem_alter
|
|
(1 row)
|
|
|
|
-- verify index is not created on worker
|
|
\c - - - :worker_1_port
|
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename like 'lineitem_alter_%';
|
|
indexname | tablename
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify alter table and drop sequence in the same transaction does not cause deadlock
|
|
SET citus.shard_count TO 4;
|
|
SET citus.shard_replication_factor TO 2;
|
|
CREATE TABLE sequence_deadlock_test (a serial, b serial);
|
|
SELECT create_distributed_table('sequence_deadlock_test', 'a');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
BEGIN;
|
|
ALTER TABLE sequence_deadlock_test ADD COLUMN c int;
|
|
-- suppress notice message caused by DROP ... CASCADE to prevent pg version difference
|
|
SET client_min_messages TO 'WARNING';
|
|
DROP SEQUENCE sequence_deadlock_test_b_seq CASCADE;
|
|
RESET client_min_messages;
|
|
END;
|
|
DROP TABLE sequence_deadlock_test;
|
|
-- verify enable/disable trigger all works
|
|
SET citus.shard_replication_factor TO 1;
|
|
SET citus.shard_count TO 1;
|
|
CREATE TABLE trigger_table (
|
|
id int,
|
|
value text
|
|
);
|
|
SELECT create_distributed_table('trigger_table', 'id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
-- first set a trigger on a shard
|
|
\c - - - :worker_1_port
|
|
SET citus.enable_metadata_sync TO OFF;
|
|
CREATE FUNCTION update_value() RETURNS trigger AS $up$
|
|
BEGIN
|
|
NEW.value := 'trigger enabled';
|
|
RETURN NEW;
|
|
END;
|
|
$up$ LANGUAGE plpgsql;
|
|
RESET citus.enable_metadata_sync;
|
|
CREATE TRIGGER update_value
|
|
BEFORE INSERT ON trigger_table_220017
|
|
FOR EACH ROW EXECUTE PROCEDURE update_value();
|
|
\c - - - :master_port
|
|
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
|
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
|
value | count
|
|
---------------------------------------------------------------------
|
|
trigger enabled | 1
|
|
(1 row)
|
|
|
|
ALTER TABLE trigger_table DISABLE TRIGGER ALL;
|
|
ERROR: triggers are not supported on distributed tables
|
|
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
|
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
|
value | count
|
|
---------------------------------------------------------------------
|
|
trigger enabled | 2
|
|
(1 row)
|
|
|
|
ALTER TABLE trigger_table ENABLE TRIGGER ALL;
|
|
ERROR: triggers are not supported on distributed tables
|
|
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
|
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
|
value | count
|
|
---------------------------------------------------------------------
|
|
trigger enabled | 3
|
|
(1 row)
|
|
|
|
DROP TABLE trigger_table;
|
|
-- test ALTER TABLE ALL IN TABLESPACE
|
|
-- we expect that it will warn out
|
|
\set tablespace_location :abs_srcdir '/data'
|
|
CREATE TABLESPACE super_fast_ssd LOCATION :'tablespace_location';
|
|
ALTER TABLE ALL IN TABLESPACE pg_default SET TABLESPACE super_fast_ssd;
|
|
WARNING: not propagating ALTER TABLE ALL IN TABLESPACE commands to worker nodes
|
|
HINT: Connect to worker nodes directly to manually move all tables.
|
|
ALTER TABLE ALL IN TABLESPACE super_fast_ssd SET TABLESPACE pg_default;
|
|
WARNING: not propagating ALTER TABLE ALL IN TABLESPACE commands to worker nodes
|
|
HINT: Connect to worker nodes directly to manually move all tables.
|
|
DROP TABLESPACE super_fast_ssd;
|
|
-- Cleanup the table and its shards
|
|
SET citus.enable_ddl_propagation to true;
|
|
CREATE USER alter_table_owner WITH LOGIN;
|
|
GRANT USAGE ON SCHEMA public TO alter_table_owner;
|
|
\c - alter_table_owner - :master_port
|
|
-- should not be able to access table without permission
|
|
SELECT count(*) FROM lineitem_alter;
|
|
ERROR: permission denied for table lineitem_alter
|
|
-- should not be able to drop the table as non table owner
|
|
DROP TABLE lineitem_alter;
|
|
ERROR: must be owner of table lineitem_alter
|
|
\c - postgres - :master_port
|
|
ALTER TABLE lineitem_alter OWNER TO alter_table_owner;
|
|
\c - alter_table_owner - :master_port
|
|
-- should be able to query the table as table owner
|
|
SELECT count(*) FROM lineitem_alter;
|
|
count
|
|
---------------------------------------------------------------------
|
|
18000
|
|
(1 row)
|
|
|
|
-- should be able to drop the table as table owner
|
|
DROP TABLE lineitem_alter;
|
|
-- check that nothing's left over on workers, other than the leftover shard created
|
|
-- during the unsuccessful COPY
|
|
\c - postgres - :worker_1_port
|
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%';
|
|
relname
|
|
---------------------------------------------------------------------
|
|
lineitem_alter_220002
|
|
(1 row)
|
|
|
|
\c - - - :master_port
|
|
-- drop the roles created
|
|
REVOKE ALL ON SCHEMA PUBLIC FROM alter_table_owner;
|
|
DROP ROLE alter_table_owner;
|
|
-- Test alter table with drop table in the same transaction
|
|
BEGIN;
|
|
CREATE TABLE test_table_1(id int);
|
|
SELECT create_distributed_table('test_table_1','id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
ALTER TABLE test_table_1 ADD CONSTRAINT u_key UNIQUE(id);
|
|
DROP TABLE test_table_1;
|
|
END;
|
|
-- There should be no test_table_1 shard on workers
|
|
\c - - - :worker_1_port
|
|
SELECT relname FROM pg_class WHERE relname LIKE 'test_table_1%';
|
|
relname
|
|
---------------------------------------------------------------------
|
|
(0 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify logged info is propagated to workers when distributing the table
|
|
CREATE TABLE logged_test(id int);
|
|
ALTER TABLE logged_test SET UNLOGGED;
|
|
SELECT create_distributed_table('logged_test', 'id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
|
relname | logged_info
|
|
---------------------------------------------------------------------
|
|
logged_test_220022 | unlogged
|
|
logged_test_220023 | unlogged
|
|
logged_test_220024 | unlogged
|
|
logged_test_220025 | unlogged
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify SET LOGGED/UNLOGGED works after distributing the table
|
|
ALTER TABLE logged_test SET LOGGED;
|
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
|
relname | logged_info
|
|
---------------------------------------------------------------------
|
|
logged_test | logged
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
|
relname | logged_info
|
|
---------------------------------------------------------------------
|
|
logged_test_220022 | logged
|
|
logged_test_220023 | logged
|
|
logged_test_220024 | logged
|
|
logged_test_220025 | logged
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
ALTER TABLE logged_test SET UNLOGGED;
|
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
|
relname | logged_info
|
|
---------------------------------------------------------------------
|
|
logged_test | unlogged
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
|
relname | logged_info
|
|
---------------------------------------------------------------------
|
|
logged_test_220022 | unlogged
|
|
logged_test_220023 | unlogged
|
|
logged_test_220024 | unlogged
|
|
logged_test_220025 | unlogged
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
DROP TABLE logged_test;
|
|
-- Test WITH options on a normal simple hash-distributed table
|
|
CREATE TABLE hash_dist(id bigint primary key, f1 text) WITH (fillfactor=40);
|
|
SELECT create_distributed_table('hash_dist','id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
-- verify that the storage options made it to the table definitions
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist | {fillfactor=40}
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relkind = 'r' AND relname LIKE 'hash_dist_%' ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist_220026 | {fillfactor=40}
|
|
hash_dist_220027 | {fillfactor=40}
|
|
hash_dist_220028 | {fillfactor=40}
|
|
hash_dist_220029 | {fillfactor=40}
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify that we can set and reset index storage parameters
|
|
ALTER INDEX hash_dist_pkey SET(fillfactor=40);
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist_pkey | {fillfactor=40}
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist_pkey_220026 | {fillfactor=40}
|
|
hash_dist_pkey_220027 | {fillfactor=40}
|
|
hash_dist_pkey_220028 | {fillfactor=40}
|
|
hash_dist_pkey_220029 | {fillfactor=40}
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
ALTER INDEX hash_dist_pkey RESET(fillfactor);
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist_pkey |
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
hash_dist_pkey_220026 |
|
|
hash_dist_pkey_220027 |
|
|
hash_dist_pkey_220028 |
|
|
hash_dist_pkey_220029 |
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
-- verify error message on ALTER INDEX, SET TABLESPACE is unsupported
|
|
ALTER INDEX hash_dist_pkey SET TABLESPACE foo;
|
|
ERROR: alter index ... set tablespace ... is currently unsupported
|
|
DETAIL: Only RENAME TO, SET (), RESET (), ATTACH PARTITION and SET STATISTICS are supported.
|
|
-- verify that we can add indexes with new storage options
|
|
CREATE UNIQUE INDEX another_index ON hash_dist(id) WITH (fillfactor=50);
|
|
-- show the index and its storage options on coordinator, then workers
|
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'another_index';
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
another_index | {fillfactor=50}
|
|
(1 row)
|
|
|
|
\c - - - :worker_1_port
|
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index_%' ORDER BY relname;
|
|
relname | reloptions
|
|
---------------------------------------------------------------------
|
|
another_index_220026 | {fillfactor=50}
|
|
another_index_220027 | {fillfactor=50}
|
|
another_index_220028 | {fillfactor=50}
|
|
another_index_220029 | {fillfactor=50}
|
|
(4 rows)
|
|
|
|
\c - - - :master_port
|
|
-- get rid of the index
|
|
DROP INDEX another_index;
|
|
-- check if we fail properly when a column with un-supported constraint is added
|
|
-- UNIQUE, PRIMARY KEY on non-distribution column is not supported
|
|
-- CHECK, FOREIGN KEY, UNIQE, PRIMARY KEY cannot be added together with ADD COLUMN
|
|
SET citus.shard_replication_factor TO 1;
|
|
CREATE TABLE test_table_1(id int);
|
|
SELECT create_distributed_table('test_table_1', 'id');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int UNIQUE;
|
|
ERROR: cannot create constraint on "test_table_1"
|
|
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int PRIMARY KEY;
|
|
ERROR: cannot create constraint on "test_table_1"
|
|
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int CHECK (test_col > 3);
|
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
|
HINT: You can issue each command separately such as ALTER TABLE test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name CHECK (check_expression);
|
|
CREATE TABLE reference_table(i int UNIQUE);
|
|
SELECT create_reference_table('reference_table');
|
|
create_reference_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE;
|
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
|
HINT: You can issue each command separately such as ALTER TABLE test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name FOREIGN KEY (test_col) REFERENCES reference_table(i) ON DELETE CASCADE;
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
|
HINT: You can issue each command separately such as ALTER TABLE test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name FOREIGN KEY (test_col) REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
|
DROP TABLE reference_table;
|
|
CREATE TABLE referenced_table(i int UNIQUE);
|
|
SELECT create_distributed_table('referenced_table', 'i');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES referenced_table(i);
|
|
ERROR: cannot create foreign key constraint
|
|
DETAIL: Foreign keys are supported in two cases, either in between two colocated tables including partition column in the same ordinal in the both tables or from distributed to reference tables
|
|
DROP TABLE referenced_table, test_table_1;
|
|
-- Check sequence propagate its own dependencies while adding a column
|
|
CREATE TABLE table_without_sequence(a int);
|
|
SELECT create_distributed_table('table_without_sequence', 'a');
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
CREATE SCHEMA test_schema_for_sequence_propagation;
|
|
CREATE SEQUENCE test_schema_for_sequence_propagation.seq_10;
|
|
ALTER TABLE table_without_sequence ADD COLUMN x BIGINT DEFAULT nextval('test_schema_for_sequence_propagation.seq_10');
|
|
-- Should be distributed along with the sequence
|
|
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation.seq_10'::regclass);
|
|
pg_identify_object_as_address
|
|
---------------------------------------------------------------------
|
|
(sequence,"{test_schema_for_sequence_propagation,seq_10}",{})
|
|
(1 row)
|
|
|
|
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation'::regnamespace);
|
|
pg_identify_object_as_address
|
|
---------------------------------------------------------------------
|
|
(schema,{test_schema_for_sequence_propagation},{})
|
|
(1 row)
|
|
|
|
-- Bug: https://github.com/citusdata/citus/issues/7378
|
|
-- Create a reference table
|
|
CREATE TABLE tbl_ref_mats(row_id integer primary key);
|
|
INSERT INTO tbl_ref_mats VALUES (1), (2);
|
|
SELECT create_reference_table('tbl_ref_mats');
|
|
NOTICE: Copying data from local table...
|
|
NOTICE: copying the data has completed
|
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.tbl_ref_mats$$)
|
|
create_reference_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
-- Create a distributed table
|
|
CREATE TABLE tbl_dist_mats(series_id integer);
|
|
INSERT INTO tbl_dist_mats VALUES (1), (1), (2), (2);
|
|
SELECT create_distributed_table('tbl_dist_mats', 'series_id');
|
|
NOTICE: Copying data from local table...
|
|
NOTICE: copying the data has completed
|
|
DETAIL: The local data in the table is no longer visible, but is still on disk.
|
|
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$public.tbl_dist_mats$$)
|
|
create_distributed_table
|
|
---------------------------------------------------------------------
|
|
|
|
(1 row)
|
|
|
|
-- Create a view that joins the distributed table with the reference table on the distribution key.
|
|
CREATE VIEW vw_citus_views as
|
|
SELECT d.series_id FROM tbl_dist_mats d JOIN tbl_ref_mats r ON d.series_id = r.row_id;
|
|
-- The view initially works fine
|
|
SELECT * FROM vw_citus_views ORDER BY 1;
|
|
series_id
|
|
---------------------------------------------------------------------
|
|
1
|
|
1
|
|
2
|
|
2
|
|
(4 rows)
|
|
|
|
-- Now, alter the table
|
|
ALTER TABLE tbl_ref_mats ADD COLUMN category1 varchar(50);
|
|
SELECT * FROM vw_citus_views ORDER BY 1;
|
|
series_id
|
|
---------------------------------------------------------------------
|
|
1
|
|
1
|
|
2
|
|
2
|
|
(4 rows)
|
|
|
|
ALTER TABLE tbl_ref_mats ADD COLUMN category2 varchar(50);
|
|
SELECT * FROM vw_citus_views ORDER BY 1;
|
|
series_id
|
|
---------------------------------------------------------------------
|
|
1
|
|
1
|
|
2
|
|
2
|
|
(4 rows)
|
|
|
|
ALTER TABLE tbl_ref_mats DROP COLUMN category1;
|
|
SELECT * FROM vw_citus_views ORDER BY 1;
|
|
series_id
|
|
---------------------------------------------------------------------
|
|
1
|
|
1
|
|
2
|
|
2
|
|
(4 rows)
|
|
|
|
DROP SCHEMA test_schema_for_sequence_propagation CASCADE;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to sequence test_schema_for_sequence_propagation.seq_10
|
|
drop cascades to default value for column x of table table_without_sequence
|
|
DROP TABLE table_without_sequence;
|
|
DROP TABLE tbl_ref_mats CASCADE;
|
|
NOTICE: drop cascades to view vw_citus_views
|
|
DROP TABLE tbl_dist_mats CASCADE;
|