Skip to content

Commit

Permalink
Support moving compressed chunks
Browse files Browse the repository at this point in the history
Allow move_chunk() to work with uncompressed chunk and
automatically move associated compressed chunk to specified
tablespace.

Block move_chunk() execution for compressed chunks.

Issue: timescale#2067
  • Loading branch information
pmwkaa committed Jul 24, 2020
1 parent 4506c1e commit f936557
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 24 deletions.
27 changes: 21 additions & 6 deletions src/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2765,19 +2765,34 @@ init_scan_by_compressed_chunk_id(ScanIterator *iterator, int32 compressed_chunk_
Int32GetDatum(compressed_chunk_id));
}

bool
ts_chunk_contains_compressed_data(Chunk *chunk)
Chunk *
ts_chunk_get_compressed_chunk_parent(Chunk *chunk)
{
ScanIterator iterator = ts_scan_iterator_create(CHUNK, AccessShareLock, CurrentMemoryContext);
bool found = false;
Oid parent_id = InvalidOid;

init_scan_by_compressed_chunk_id(&iterator, chunk->fd.id);
ts_scanner_foreach(&iterator)
{
Assert(!found);
found = true;
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
bool isnull;

Assert(!OidIsValid(parent_id));
parent_id = DatumGetObjectId(heap_getattr(ti->tuple, Anum_chunk_id, ti->desc, &isnull));
}
return found;

if (OidIsValid(parent_id))
return ts_chunk_get_by_id(DatumGetObjectId(parent_id), true);

return NULL;
}

bool
ts_chunk_contains_compressed_data(Chunk *chunk)
{
Chunk *parent_chunk = ts_chunk_get_compressed_chunk_parent(chunk);

return parent_chunk != NULL;
}

List *
Expand Down
1 change: 1 addition & 0 deletions src/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ extern TSDLLEXPORT Chunk *ts_chunk_find_or_create_without_cuts(Hypertable *ht, H
const char *schema_name,
const char *table_name,
bool *created);
extern TSDLLEXPORT Chunk *ts_chunk_get_compressed_chunk_parent(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_contains_compressed_data(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_can_be_compressed(int32 chunk_id);
extern TSDLLEXPORT Datum ts_chunk_id_from_relid(PG_FUNCTION_ARGS);
Expand Down
59 changes: 48 additions & 11 deletions tsl/src/reorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ tsl_move_chunk(PG_FUNCTION_ARGS)
PG_ARGISNULL(2) ? InvalidOid : get_tablespace_oid(PG_GETARG_NAME(2)->data, false);
Oid index_id = PG_ARGISNULL(3) ? InvalidOid : PG_GETARG_OID(3);
bool verbose = PG_ARGISNULL(4) ? false : PG_GETARG_BOOL(4);
Chunk *chunk;

/* used for debugging purposes only see finish_heap_swaps */
Oid wait_id = PG_NARGS() < 6 || PG_ARGISNULL(5) ? InvalidOid : PG_GETARG_OID(5);
Expand Down Expand Up @@ -148,12 +149,53 @@ tsl_move_chunk(PG_FUNCTION_ARGS)
errmsg("valid chunk, destination_tablespace, and index_destination_tablespaces "
"are required")));

reorder_chunk(chunk_id,
index_id,
verbose,
wait_id,
destination_tablespace,
index_destination_tablespace);
chunk = ts_chunk_get_by_relid(chunk_id, false);

if (NULL == chunk)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a chunk", get_rel_name(chunk_id))));

if (ts_chunk_contains_compressed_data(chunk))
{
Chunk *chunk_parent = ts_chunk_get_compressed_chunk_parent(chunk);

ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot directly move internal compression data"),
errdetail("Chunk \"%s\" contains compressed data for chunk \"%s\" and cannot be "
"moved directly.",
get_rel_name(chunk_id),
get_rel_name(chunk_parent->table_id)),
errhint("Moving chunk \"%s\" will also move the compressed data.",
get_rel_name(chunk_parent->table_id))));
}

/* If chunk is compressed move it by altering tablespace on both chunks */
if (OidIsValid(chunk->fd.compressed_chunk_id))
{
Chunk *compressed_chunk = ts_chunk_get_by_id(chunk->fd.compressed_chunk_id, true);
AlterTableCmd cmd = { .type = T_AlterTableCmd,
.subtype = AT_SetTableSpace,
.name = get_tablespace_name(destination_tablespace) };

ereport(NOTICE,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Reordering is not used with compressed chunk")));

AlterTableInternal(chunk_id, list_make1(&cmd), false);
AlterTableInternal(compressed_chunk->table_id, list_make1(&cmd), false);
}
else
{
reorder_chunk(chunk_id,
index_id,
verbose,
wait_id,
destination_tablespace,
index_destination_tablespace);
}

PG_RETURN_VOID();
}

Expand All @@ -178,11 +220,6 @@ reorder_chunk(Oid chunk_id, Oid index_id, bool verbose, Oid wait_id, Oid destina
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a chunk", get_rel_name(chunk_id))));

if (chunk->fd.compressed_chunk_id != INVALID_CHUNK_ID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is a compressed chunk", get_rel_name(chunk_id))));

ht = ts_hypertable_cache_get_cache_and_entry(chunk->hypertable_relid, CACHE_FLAG_NONE, &hcache);

/* Our check gives better error messages, but keep the original one too. */
Expand Down
20 changes: 15 additions & 5 deletions tsl/test/expected/compression_ddl.out
Original file line number Diff line number Diff line change
Expand Up @@ -150,22 +150,32 @@ FROM pg_tables WHERE tablespace = 'tablespace1';
(0 rows)

\set ON_ERROR_STOP 0
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
WARNING: Timescale License expired
ERROR: "_hyper_1_1_chunk" is a compressed chunk
ERROR: cannot directly move internal compression data
\set ON_ERROR_STOP 1
SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
-- ensure that both compressed and uncompressed chunks moved
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
NOTICE: Reordering is not used with compressed chunk
move_chunk
------------

(1 row)

SELECT tablename
FROM pg_tables WHERE tablespace = 'tablespace1';
tablename
---------------------------
_hyper_1_1_chunk
compress_hyper_2_28_chunk
(2 rows)

-- the compressed chunk is in here now
SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
1
2
(1 row)

SELECT decompress_chunk(:'UNCOMPRESSED_CHUNK_NAME');
Expand All @@ -179,7 +189,7 @@ SELECT count(*)
FROM pg_tables WHERE tablespace = 'tablespace1';
count
-------
0
1
(1 row)

SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
Expand Down
7 changes: 5 additions & 2 deletions tsl/test/sql/compression_ddl.sql
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,13 @@ SELECT tablename
FROM pg_tables WHERE tablespace = 'tablespace1';

\set ON_ERROR_STOP 0
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
\set ON_ERROR_STOP 1

SELECT move_chunk(chunk=>:'COMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."compress_hyper_2_28_chunk__compressed_hypertable_2_b__ts_meta_s"');
-- ensure that both compressed and uncompressed chunks moved
SELECT move_chunk(chunk=>:'UNCOMPRESSED_CHUNK_NAME', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'_timescaledb_internal."_hyper_1_1_chunk_test1_Time_idx"');
SELECT tablename
FROM pg_tables WHERE tablespace = 'tablespace1';

-- the compressed chunk is in here now
SELECT count(*)
Expand Down

0 comments on commit f936557

Please sign in to comment.