Merge pull request #548 from citusdata/feature/manual_ddl_propagation

Add enable_ddl_propagation flag to control automatic ddl propagation
pull/575/head
Murat Tuncer 2016-06-06 14:08:47 +03:00
commit 46fcbd1ff9
5 changed files with 157 additions and 25 deletions

View File

@ -40,6 +40,8 @@
#include "utils/syscache.h"
bool EnableDDLPropagation = true; /* ddl propagation is enabled */
/*
* This struct defines the state for the callback for drop statements.
* It is copied as it is from commands/tablecmds.c in Postgres source.
@ -145,39 +147,43 @@ multi_ProcessUtility(Node *parsetree,
}
}
if (IsA(parsetree, IndexStmt))
/* ddl commands are propagated to workers only if EnableDDLPropagation is set */
if (EnableDDLPropagation)
{
parsetree = ProcessIndexStmt((IndexStmt *) parsetree, queryString);
}
if (IsA(parsetree, DropStmt))
{
DropStmt *dropStatement = (DropStmt *) parsetree;
if (dropStatement->removeType == OBJECT_INDEX)
if (IsA(parsetree, IndexStmt))
{
parsetree = ProcessDropIndexStmt(dropStatement, queryString);
parsetree = ProcessIndexStmt((IndexStmt *) parsetree, queryString);
}
}
if (IsA(parsetree, AlterTableStmt))
{
AlterTableStmt *alterTableStmt = (AlterTableStmt *) parsetree;
if (alterTableStmt->relkind == OBJECT_TABLE)
if (IsA(parsetree, DropStmt))
{
parsetree = ProcessAlterTableStmt(alterTableStmt, queryString);
DropStmt *dropStatement = (DropStmt *) parsetree;
if (dropStatement->removeType == OBJECT_INDEX)
{
parsetree = ProcessDropIndexStmt(dropStatement, queryString);
}
}
}
/*
* ALTER TABLE ... RENAME statements have their node type as RenameStmt and
* not AlterTableStmt. So, we intercept RenameStmt to tackle these commands.
*/
if (IsA(parsetree, RenameStmt))
{
RenameStmt *renameStmt = (RenameStmt *) parsetree;
if (IsAlterTableRenameStmt(renameStmt))
if (IsA(parsetree, AlterTableStmt))
{
ErrorIfDistributedRenameStmt(renameStmt);
AlterTableStmt *alterTableStmt = (AlterTableStmt *) parsetree;
if (alterTableStmt->relkind == OBJECT_TABLE)
{
parsetree = ProcessAlterTableStmt(alterTableStmt, queryString);
}
}
/*
* ALTER TABLE ... RENAME statements have their node type as RenameStmt and
* not AlterTableStmt. So, we intercept RenameStmt to tackle these commands.
*/
if (IsA(parsetree, RenameStmt))
{
RenameStmt *renameStmt = (RenameStmt *) parsetree;
if (IsAlterTableRenameStmt(renameStmt))
{
ErrorIfDistributedRenameStmt(renameStmt);
}
}
}

View File

@ -308,6 +308,16 @@ RegisterCitusConfigVariables(void)
0,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.enable_ddl_propagation",
gettext_noop("Enables propagating DDL statements to worker shards"),
NULL,
&EnableDDLPropagation,
true,
PGC_USERSET,
0,
NULL, NULL, NULL);
DefineCustomIntVariable(
"citus.shard_replication_factor",
gettext_noop("Sets the replication factor for shards."),

View File

@ -12,6 +12,7 @@
#include "tcop/utility.h"
extern bool EnableDDLPropagation;
extern void multi_ProcessUtility(Node *parsetree, const char *queryString,
ProcessUtilityContext context, ParamListInfo params,

View File

@ -162,7 +162,56 @@ FROM
ORDER BY attnum;
\c - - - :master_port
-- 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 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';
-- 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_103000 LIMIT 0;
\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;
-- 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;
-- 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;
ALTER TABLE lineitem_alter SET WITHOUT OIDS;
-- even distribution column can be dropped however postgresql prevents this.
ALTER TABLE lineitem_alter DROP COLUMN l_orderkey;
-- 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';
-- verify index is not created on worker
\c - - - :worker_1_port
SELECT indexname, tablename FROM pg_indexes WHERE tablename like 'lineitem_alter_%';
\c - - - :master_port
-- Cleanup the table and its shards
SET citus.enable_ddl_propagation to true;
SELECT master_apply_delete_command('DELETE FROM lineitem_alter');
DROP TABLE lineitem_alter;
-- check that nothing's left over on workers

View File

@ -451,8 +451,74 @@ ORDER BY attnum;
........pg.dropped.23........ | -
(29 rows)
\c - - - :master_port
-- 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 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_103000 LIMIT 0;
ERROR: column "column_only_added_to_master" does not exist
LINE 1: SELECT column_only_added_to_master FROM lineitem_alter_10300...
^
\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;
-- even distribution column can be dropped however postgresql prevents this.
ALTER TABLE lineitem_alter DROP COLUMN l_orderkey;
ERROR: cannot drop table lineitem_alter column l_orderkey because other objects depend on it
DETAIL: table lineitem_alter depends on table lineitem_alter column l_orderkey
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- 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
-- Cleanup the table and its shards
SET citus.enable_ddl_propagation to true;
SELECT master_apply_delete_command('DELETE FROM lineitem_alter');
master_apply_delete_command
-----------------------------