mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-18 03:23:37 +08:00
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:
parent
4179f4f324
commit
d5a6a5b193
@ -2762,6 +2762,8 @@ process_altertable_start_matview(ProcessUtilityArgs *args)
|
|||||||
NameData view_schema;
|
NameData view_schema;
|
||||||
ContinuousAgg *cagg;
|
ContinuousAgg *cagg;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
Hypertable *ht;
|
||||||
|
Cache *hcache;
|
||||||
|
|
||||||
if (!OidIsValid(view_relid))
|
if (!OidIsValid(view_relid))
|
||||||
return DDL_CONTINUE;
|
return DDL_CONTINUE;
|
||||||
@ -2788,6 +2790,19 @@ process_altertable_start_matview(ProcessUtilityArgs *args)
|
|||||||
errmsg("expected set options to contain a list")));
|
errmsg("expected set options to contain a list")));
|
||||||
process_altercontinuousagg_set_with(cagg, view_relid, (List *) cmd->def);
|
process_altercontinuousagg_set_with(cagg, view_relid, (List *) cmd->def);
|
||||||
break;
|
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:
|
default:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
@ -203,6 +203,7 @@ static int32 mattablecolumninfo_create_materialization_table(MatTableColumnInfo
|
|||||||
int32 hypertable_id, RangeVar *mat_rel,
|
int32 hypertable_id, RangeVar *mat_rel,
|
||||||
CAggTimebucketInfo *origquery_tblinfo,
|
CAggTimebucketInfo *origquery_tblinfo,
|
||||||
bool create_addl_index,
|
bool create_addl_index,
|
||||||
|
char *tablespacename,
|
||||||
ObjectAddress *mataddress);
|
ObjectAddress *mataddress);
|
||||||
static Query *mattablecolumninfo_get_partial_select_query(MatTableColumnInfo *matcolinfo,
|
static Query *mattablecolumninfo_get_partial_select_query(MatTableColumnInfo *matcolinfo,
|
||||||
Query *userview_query);
|
Query *userview_query);
|
||||||
@ -460,7 +461,8 @@ static int32
|
|||||||
mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, int32 hypertable_id,
|
mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, int32 hypertable_id,
|
||||||
RangeVar *mat_rel,
|
RangeVar *mat_rel,
|
||||||
CAggTimebucketInfo *origquery_tblinfo,
|
CAggTimebucketInfo *origquery_tblinfo,
|
||||||
bool create_addl_index, ObjectAddress *mataddress)
|
bool create_addl_index, char *const tablespacename,
|
||||||
|
ObjectAddress *mataddress)
|
||||||
{
|
{
|
||||||
Oid uid, saved_uid;
|
Oid uid, saved_uid;
|
||||||
int sec_ctx;
|
int sec_ctx;
|
||||||
@ -484,7 +486,7 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo,
|
|||||||
create->constraints = NIL;
|
create->constraints = NIL;
|
||||||
create->options = NULL;
|
create->options = NULL;
|
||||||
create->oncommit = ONCOMMIT_NOOP;
|
create->oncommit = ONCOMMIT_NOOP;
|
||||||
create->tablespacename = NULL;
|
create->tablespacename = tablespacename;
|
||||||
create->if_not_exists = false;
|
create->if_not_exists = false;
|
||||||
|
|
||||||
/* Create the materialization table. */
|
/* Create the materialization table. */
|
||||||
@ -1662,8 +1664,8 @@ fixup_userview_query_tlist(Query *userquery, List *tlist_aliases)
|
|||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht,
|
cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquery,
|
||||||
WithClauseResult *with_clause_options)
|
CAggTimebucketInfo *origquery_ht, WithClauseResult *with_clause_options)
|
||||||
{
|
{
|
||||||
ObjectAddress mataddress;
|
ObjectAddress mataddress;
|
||||||
char relnamebuf[NAMEDATALEN];
|
char relnamebuf[NAMEDATALEN];
|
||||||
@ -1721,6 +1723,7 @@ cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht,
|
|||||||
mat_rel,
|
mat_rel,
|
||||||
origquery_ht,
|
origquery_ht,
|
||||||
is_create_mattbl_index,
|
is_create_mattbl_index,
|
||||||
|
create_stmt->into->tableSpaceName,
|
||||||
&mataddress);
|
&mataddress);
|
||||||
/* Step 2: create view with select finalize from materialization
|
/* Step 2: create view with select finalize from materialization
|
||||||
* table
|
* 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);
|
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;
|
return DDL_DONE;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ select table_name from create_hypertable('conditions', 'timec');
|
|||||||
|
|
||||||
-- schema tests
|
-- schema tests
|
||||||
\c :TEST_DBNAME :ROLE_SUPERUSER
|
\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;
|
CREATE SCHEMA rename_schema;
|
||||||
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;
|
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;
|
||||||
\c :TEST_DBNAME :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.
|
HINT: Try the operation on the continuous aggregate instead.
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
\set ON_ERROR_STOP 1
|
\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;
|
||||||
|
@ -114,6 +114,7 @@ set(SOLO_TESTS
|
|||||||
compress_bgw_reorder_drop_chunks
|
compress_bgw_reorder_drop_chunks
|
||||||
compression_ddl
|
compression_ddl
|
||||||
continuous_aggs_bgw
|
continuous_aggs_bgw
|
||||||
|
continuous_aggs_ddl
|
||||||
continuous_aggs_dump
|
continuous_aggs_dump
|
||||||
data_fetcher
|
data_fetcher
|
||||||
data_node
|
data_node
|
||||||
|
@ -24,6 +24,8 @@ select table_name from create_hypertable('conditions', 'timec');
|
|||||||
-- schema tests
|
-- schema tests
|
||||||
|
|
||||||
\c :TEST_DBNAME :ROLE_SUPERUSER
|
\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;
|
CREATE SCHEMA rename_schema;
|
||||||
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;
|
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);
|
SELECT drop_chunks(:'drop_chunks_mat_tablen', older_than => 60);
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
\set ON_ERROR_STOP 1
|
\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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user