Support tablespaces for continuous aggregates

Adding support for tablespaces when creating a continuous aggregate
using `CREATE MATERIALIZED VIEW` and when altering a continuous
aggregate using `ALTER MATERIALIZED VIEW`.

Fixes #2122
This commit is contained in:
Mats Kindahl 2020-08-28 15:51:25 +02:00 committed by Mats Kindahl
parent 4179f4f324
commit d5a6a5b193
5 changed files with 185 additions and 5 deletions

View File

@ -2762,6 +2762,8 @@ process_altertable_start_matview(ProcessUtilityArgs *args)
NameData view_schema;
ContinuousAgg *cagg;
ListCell *lc;
Hypertable *ht;
Cache *hcache;
if (!OidIsValid(view_relid))
return DDL_CONTINUE;
@ -2788,6 +2790,19 @@ process_altertable_start_matview(ProcessUtilityArgs *args)
errmsg("expected set options to contain a list")));
process_altercontinuousagg_set_with(cagg, view_relid, (List *) cmd->def);
break;
case AT_SetTableSpace:
hcache = ts_hypertable_cache_pin();
ht = ts_hypertable_cache_get_entry_by_id(hcache, cagg->data.mat_hypertable_id);
Assert(ht); /* Broken continuous aggregate */
ts_hypertable_permissions_check_by_id(ht->fd.id);
check_alter_table_allowed_on_ht_with_compression(ht, stmt);
relation_not_only(stmt->relation);
process_altertable_set_tablespace_end(ht, cmd);
AlterTableInternal(ht->main_table_relid, list_make1(cmd), false);
ts_cache_release(hcache);
break;
default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

View File

@ -203,6 +203,7 @@ static int32 mattablecolumninfo_create_materialization_table(MatTableColumnInfo
int32 hypertable_id, RangeVar *mat_rel,
CAggTimebucketInfo *origquery_tblinfo,
bool create_addl_index,
char *tablespacename,
ObjectAddress *mataddress);
static Query *mattablecolumninfo_get_partial_select_query(MatTableColumnInfo *matcolinfo,
Query *userview_query);
@ -460,7 +461,8 @@ static int32
mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, int32 hypertable_id,
RangeVar *mat_rel,
CAggTimebucketInfo *origquery_tblinfo,
bool create_addl_index, ObjectAddress *mataddress)
bool create_addl_index, char *const tablespacename,
ObjectAddress *mataddress)
{
Oid uid, saved_uid;
int sec_ctx;
@ -484,7 +486,7 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo,
create->constraints = NIL;
create->options = NULL;
create->oncommit = ONCOMMIT_NOOP;
create->tablespacename = NULL;
create->tablespacename = tablespacename;
create->if_not_exists = false;
/* Create the materialization table. */
@ -1662,8 +1664,8 @@ fixup_userview_query_tlist(Query *userquery, List *tlist_aliases)
* )
*/
static void
cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht,
WithClauseResult *with_clause_options)
cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquery,
CAggTimebucketInfo *origquery_ht, WithClauseResult *with_clause_options)
{
ObjectAddress mataddress;
char relnamebuf[NAMEDATALEN];
@ -1721,6 +1723,7 @@ cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht,
mat_rel,
origquery_ht,
is_create_mattbl_index,
create_stmt->into->tableSpaceName,
&mataddress);
/* Step 2: create view with select finalize from materialization
* table
@ -1819,7 +1822,7 @@ tsl_process_continuous_agg_viewstmt(Node *node, const char *query_string, void *
}
timebucket_exprinfo = cagg_validate_query((Query *) stmt->into->viewQuery);
cagg_create(&viewstmt, (Query *) stmt->query, &timebucket_exprinfo, with_clause_options);
cagg_create(stmt, &viewstmt, (Query *) stmt->query, &timebucket_exprinfo, with_clause_options);
return DDL_DONE;
}

View File

@ -22,6 +22,8 @@ select table_name from create_hypertable('conditions', 'timec');
-- schema tests
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE1_PATH;
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE2_PATH;
CREATE SCHEMA rename_schema;
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@ -876,3 +878,85 @@ DETAIL: Hypertable "_materialized_hypertable_11" is a materialized hypertable.
HINT: Try the operation on the continuous aggregate instead.
\set VERBOSITY terse
\set ON_ERROR_STOP 1
--------------------------------------------------------------------
-- Check that we can create a materialized table in a tablespace. We
-- create one with tablespace and one without and compare them.
CREATE VIEW cagg_info AS
WITH
caggs AS (
SELECT format('%s.%s', user_view_schema, user_view_name)::regclass AS user_view,
format('%s.%s', ht.schema_name, ht.table_name)::regclass AS mat_relid
FROM _timescaledb_catalog.hypertable ht,
_timescaledb_catalog.continuous_agg cagg
WHERE ht.id = cagg.mat_hypertable_id
)
SELECT user_view,
relname AS mat_table,
(SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace
FROM pg_class JOIN caggs ON pg_class.oid = caggs.mat_relid;
CREATE VIEW chunk_info AS
SELECT ht.schema_name, ht.table_name, relname AS chunk_name,
(SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace
FROM pg_class c,
_timescaledb_catalog.hypertable ht,
_timescaledb_catalog.chunk ch
WHERE ch.table_name = c.relname AND ht.id = ch.hypertable_id;
CREATE TABLE whatever(time BIGINT NOT NULL, data INTEGER);
SELECT hypertable_id AS whatever_nid
FROM create_hypertable('whatever', 'time', chunk_time_interval => 10)
\gset
SELECT set_integer_now_func('whatever', 'integer_now_test');
set_integer_now_func
----------------------
(1 row)
CREATE MATERIALIZED VIEW whatever_view_1
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
SELECT time_bucket('2', time), COUNT(data)
FROM whatever GROUP BY 1;
CREATE MATERIALIZED VIEW whatever_view_2
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
TABLESPACE tablespace1 AS
SELECT time_bucket('2', time), COUNT(data)
FROM whatever GROUP BY 1;
INSERT INTO whatever SELECT i, i FROM generate_series(0, 29) AS i;
REFRESH MATERIALIZED VIEW whatever_view_1;
LOG: materializing continuous aggregate public.whatever_view_1: nothing to invalidate, new range up to 30
REFRESH MATERIALIZED VIEW whatever_view_2;
LOG: materializing continuous aggregate public.whatever_view_2: nothing to invalidate, new range up to 30
SELECT user_view,
mat_table,
cagg_info.tablespace AS mat_tablespace,
chunk_name,
chunk_info.tablespace AS chunk_tablespace
FROM cagg_info, chunk_info
WHERE mat_table::text = table_name
AND user_view::text LIKE 'whatever_view%';
user_view | mat_table | mat_tablespace | chunk_name | chunk_tablespace
-----------------+-----------------------------+----------------+--------------------+------------------
whatever_view_1 | _materialized_hypertable_13 | | _hyper_13_24_chunk |
whatever_view_2 | _materialized_hypertable_14 | tablespace1 | _hyper_14_25_chunk | tablespace1
(2 rows)
ALTER MATERIALIZED VIEW whatever_view_1 SET TABLESPACE tablespace2;
SELECT user_view,
mat_table,
cagg_info.tablespace AS mat_tablespace,
chunk_name,
chunk_info.tablespace AS chunk_tablespace
FROM cagg_info, chunk_info
WHERE mat_table::text = table_name
AND user_view::text LIKE 'whatever_view%';
user_view | mat_table | mat_tablespace | chunk_name | chunk_tablespace
-----------------+-----------------------------+----------------+--------------------+------------------
whatever_view_1 | _materialized_hypertable_13 | tablespace2 | _hyper_13_24_chunk | tablespace2
whatever_view_2 | _materialized_hypertable_14 | tablespace1 | _hyper_14_25_chunk | tablespace1
(2 rows)
DROP MATERIALIZED VIEW whatever_view_1;
NOTICE: drop cascades to table _timescaledb_internal._hyper_13_24_chunk
DROP MATERIALIZED VIEW whatever_view_2;
NOTICE: drop cascades to table _timescaledb_internal._hyper_14_25_chunk
DROP TABLESPACE tablespace1;
DROP TABLESPACE tablespace2;

View File

@ -114,6 +114,7 @@ set(SOLO_TESTS
compress_bgw_reorder_drop_chunks
compression_ddl
continuous_aggs_bgw
continuous_aggs_ddl
continuous_aggs_dump
data_fetcher
data_node

View File

@ -24,6 +24,8 @@ select table_name from create_hypertable('conditions', 'timec');
-- schema tests
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE1_PATH;
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE2_PATH;
CREATE SCHEMA rename_schema;
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;
@ -478,3 +480,78 @@ WHERE hypertable_name = :'drop_chunks_mat_table_name' ORDER BY range_start_integ
SELECT drop_chunks(:'drop_chunks_mat_tablen', older_than => 60);
\set VERBOSITY terse
\set ON_ERROR_STOP 1
--------------------------------------------------------------------
-- Check that we can create a materialized table in a tablespace. We
-- create one with tablespace and one without and compare them.
CREATE VIEW cagg_info AS
WITH
caggs AS (
SELECT format('%s.%s', user_view_schema, user_view_name)::regclass AS user_view,
format('%s.%s', ht.schema_name, ht.table_name)::regclass AS mat_relid
FROM _timescaledb_catalog.hypertable ht,
_timescaledb_catalog.continuous_agg cagg
WHERE ht.id = cagg.mat_hypertable_id
)
SELECT user_view,
relname AS mat_table,
(SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace
FROM pg_class JOIN caggs ON pg_class.oid = caggs.mat_relid;
CREATE VIEW chunk_info AS
SELECT ht.schema_name, ht.table_name, relname AS chunk_name,
(SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace
FROM pg_class c,
_timescaledb_catalog.hypertable ht,
_timescaledb_catalog.chunk ch
WHERE ch.table_name = c.relname AND ht.id = ch.hypertable_id;
CREATE TABLE whatever(time BIGINT NOT NULL, data INTEGER);
SELECT hypertable_id AS whatever_nid
FROM create_hypertable('whatever', 'time', chunk_time_interval => 10)
\gset
SELECT set_integer_now_func('whatever', 'integer_now_test');
CREATE MATERIALIZED VIEW whatever_view_1
WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS
SELECT time_bucket('2', time), COUNT(data)
FROM whatever GROUP BY 1;
CREATE MATERIALIZED VIEW whatever_view_2
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
TABLESPACE tablespace1 AS
SELECT time_bucket('2', time), COUNT(data)
FROM whatever GROUP BY 1;
INSERT INTO whatever SELECT i, i FROM generate_series(0, 29) AS i;
REFRESH MATERIALIZED VIEW whatever_view_1;
REFRESH MATERIALIZED VIEW whatever_view_2;
SELECT user_view,
mat_table,
cagg_info.tablespace AS mat_tablespace,
chunk_name,
chunk_info.tablespace AS chunk_tablespace
FROM cagg_info, chunk_info
WHERE mat_table::text = table_name
AND user_view::text LIKE 'whatever_view%';
ALTER MATERIALIZED VIEW whatever_view_1 SET TABLESPACE tablespace2;
SELECT user_view,
mat_table,
cagg_info.tablespace AS mat_tablespace,
chunk_name,
chunk_info.tablespace AS chunk_tablespace
FROM cagg_info, chunk_info
WHERE mat_table::text = table_name
AND user_view::text LIKE 'whatever_view%';
DROP MATERIALIZED VIEW whatever_view_1;
DROP MATERIALIZED VIEW whatever_view_2;
DROP TABLESPACE tablespace1;
DROP TABLESPACE tablespace2;