Block most DDL on hypertable with compression

Block most DDL commands on hypertables with compression enabled.
This restriction will be relaxed over time.

The only alter table commands currently allowed are:
Add/Remove index, Set storage options, clustering index,
set statistics and set tablespace.

We also disallow reseting compression options.
This commit is contained in:
Matvey Arye 2019-09-26 16:16:03 -04:00 committed by Matvey Arye
parent 91a73c3e17
commit a399a57af9
5 changed files with 124 additions and 9 deletions

View File

@ -74,6 +74,7 @@ static ProcessUtility_hook_type prev_ProcessUtility_hook;
static bool expect_chunk_modification = false;
static bool process_altertable_set_options(AlterTableCmd *cmd, Hypertable *ht);
static bool process_altertable_reset_options(AlterTableCmd *cmd, Hypertable *ht);
/* Call the default ProcessUtility and handle PostgreSQL version differences */
static void
@ -196,6 +197,59 @@ check_continuous_agg_alter_table_allowed(Hypertable *ht, AlterTableStmt *stmt)
}
}
static void
check_alter_table_allowed_on_ht_with_compression(Hypertable *ht, AlterTableStmt *stmt)
{
ListCell *lc;
if (ht->fd.compressed_hypertable_id == INVALID_HYPERTABLE_ID)
return;
/* only allow if all commands are allowed */
foreach (lc, stmt->cmds)
{
AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lc);
switch (cmd->subtype)
{
/*
* ALLOWED:
*/
case AT_AddIndex:
case AT_ReAddIndex:
case AT_ResetRelOptions:
case AT_ReplaceRelOptions:
case AT_SetRelOptions:
case AT_ClusterOn:
case AT_DropCluster:
/* allow now, improve later */
case AT_SetStatistics: /* pass statistics down to compressed? */
case AT_SetTableSpace: /* pass down to compressed as well */
/* allowed on materialization tables */
continue;
/*
* BLOCKED:
*/
/* should be implemented later */
case AT_ChangeOwner:
/* definitely block */
case AT_AddOids:
case AT_DropOids:
case AT_AddOidsRecurse:
case AT_EnableRowSecurity:
case AT_DisableRowSecurity:
case AT_ForceRowSecurity:
case AT_NoForceRowSecurity:
default:
/* blocked by default */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("operation not supported on hypertables that have compression "
"enabled")));
break;
}
}
}
static void
relation_not_only(RangeVar *rv)
{
@ -2266,6 +2320,7 @@ process_altertable_start_table(ProcessUtilityArgs *args)
{
ts_hypertable_permissions_check_by_id(ht->fd.id);
check_continuous_agg_alter_table_allowed(ht, stmt);
check_alter_table_allowed_on_ht_with_compression(ht, stmt);
relation_not_only(stmt->relation);
process_add_hypertable(args, ht);
}
@ -2362,7 +2417,10 @@ process_altertable_start_table(ProcessUtilityArgs *args)
}
break;
}
case AT_ResetRelOptions:
case AT_ReplaceRelOptions:
process_altertable_reset_options(cmd, ht);
break;
default:
break;
}
@ -2805,6 +2863,25 @@ process_altertable_set_options(AlterTableCmd *cmd, Hypertable *ht)
return true;
}
static bool
process_altertable_reset_options(AlterTableCmd *cmd, Hypertable *ht)
{
List *pg_options = NIL, *compress_options = NIL;
List *inpdef = NIL;
/* is this a compress table stmt */
Assert(IsA(cmd->def, List));
inpdef = (List *) cmd->def;
ts_with_clause_filter(inpdef, &compress_options, &pg_options);
if (compress_options)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("compression options cannot be reset")));
}
else
return false;
}
static bool
process_viewstmt(ProcessUtilityArgs *args)
{

View File

@ -38,11 +38,8 @@ NOTICE: adding not-null constraint to column "Time"
INSERT INTO test1 SELECT t, gen_rand_minstd(), gen_rand_minstd(), gen_rand_minstd()::text FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') t;
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = '"Time" DESC');
--
-- DROP CHUNKS
--
SELECT COUNT(*) AS count_compressed
FROM
FROM
(
SELECT compress_chunk(chunk.schema_name|| '.' || chunk.table_name)
FROM _timescaledb_catalog.chunk chunk
@ -55,6 +52,17 @@ AS sub;
27
(1 row)
--make sure allowed ddl still work
ALTER TABLE test1 CLUSTER ON "test1_Time_idx";
ALTER TABLE test1 SET WITHOUT CLUSTER;
CREATE INDEX new_index ON test1(b);
DROP INDEX new_index;
ALTER TABLE test1 SET (fillfactor=100);
ALTER TABLE test1 RESET (fillfactor);
ALTER TABLE test1 ALTER COLUMN b SET STATISTICS 10;
--
-- DROP CHUNKS
--
SELECT count(*) as count_chunks_uncompressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)

View File

@ -137,6 +137,17 @@ ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, p'
ERROR: invalid order by column type: could not identify an less-than operator for type point
--should succeed
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, b');
--ddl on ht with compression
ALTER TABLE foo ADD COLUMN new_column INT;
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo DROP COLUMN a;
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo DROP COLUMN t;
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo ALTER COLUMN t SET NOT NULL;
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo RESET (timescaledb.compress);
ERROR: compression options cannot be reset
--note that the time column "a" should not be added to the end of the order by list again (should appear first)
select hc.* from _timescaledb_catalog.hypertable_compression hc inner join _timescaledb_catalog.hypertable h on (h.id = hc.hypertable_id) where h.table_name = 'foo' order by attname;
hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst

View File

@ -14,11 +14,9 @@ INSERT INTO test1 SELECT t, gen_rand_minstd(), gen_rand_minstd(), gen_rand_mins
ALTER TABLE test1 set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = '"Time" DESC');
--
-- DROP CHUNKS
--
SELECT COUNT(*) AS count_compressed
FROM
FROM
(
SELECT compress_chunk(chunk.schema_name|| '.' || chunk.table_name)
FROM _timescaledb_catalog.chunk chunk
@ -28,6 +26,19 @@ WHERE hypertable.table_name like 'test1' and chunk.compressed_chunk_id IS NULL O
AS sub;
--make sure allowed ddl still work
ALTER TABLE test1 CLUSTER ON "test1_Time_idx";
ALTER TABLE test1 SET WITHOUT CLUSTER;
CREATE INDEX new_index ON test1(b);
DROP INDEX new_index;
ALTER TABLE test1 SET (fillfactor=100);
ALTER TABLE test1 RESET (fillfactor);
ALTER TABLE test1 ALTER COLUMN b SET STATISTICS 10;
--
-- DROP CHUNKS
--
SELECT count(*) as count_chunks_uncompressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)

View File

@ -77,6 +77,14 @@ ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, p'
--should succeed
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, b');
--ddl on ht with compression
ALTER TABLE foo ADD COLUMN new_column INT;
ALTER TABLE foo DROP COLUMN a;
ALTER TABLE foo DROP COLUMN t;
ALTER TABLE foo ALTER COLUMN t SET NOT NULL;
ALTER TABLE foo RESET (timescaledb.compress);
--note that the time column "a" should not be added to the end of the order by list again (should appear first)
select hc.* from _timescaledb_catalog.hypertable_compression hc inner join _timescaledb_catalog.hypertable h on (h.id = hc.hypertable_id) where h.table_name = 'foo' order by attname;