diff --git a/.unreleased/pr_7832 b/.unreleased/pr_7832 new file mode 100644 index 000000000..57f18477e --- /dev/null +++ b/.unreleased/pr_7832 @@ -0,0 +1 @@ +Implements: #7832 Allow setting chunk_time_interval for continuous aggregates during creation diff --git a/src/dimension.c b/src/dimension.c index c095d24b2..f98ca3e5b 100644 --- a/src/dimension.c +++ b/src/dimension.c @@ -995,13 +995,6 @@ ts_hyperspace_calculate_point(const Hyperspace *hs, TupleTableSlot *slot) return p; } -static inline int64 -interval_to_usec(Interval *interval) -{ - return (interval->month * DAYS_PER_MONTH * USECS_PER_DAY) + (interval->day * USECS_PER_DAY) + - interval->time; -} - #define INT_TYPE_MAX(type) \ (int64)(((type) == INT2OID) ? PG_INT16_MAX : \ (((type) == INT4OID) ? PG_INT32_MAX : PG_INT64_MAX)) diff --git a/src/dimension.h b/src/dimension.h index 44d9d1a80..aa40e250c 100644 --- a/src/dimension.h +++ b/src/dimension.h @@ -140,7 +140,7 @@ extern int32 ts_dimension_get_hypertable_id(int32 dimension_id); extern int ts_dimension_set_type(Dimension *dim, Oid newtype); extern TSDLLEXPORT Oid ts_dimension_get_partition_type(const Dimension *dim); extern int ts_dimension_set_name(Dimension *dim, const char *newname); -extern int ts_dimension_set_chunk_interval(Dimension *dim, int64 chunk_interval); +extern TSDLLEXPORT int ts_dimension_set_chunk_interval(Dimension *dim, int64 chunk_interval); extern int ts_dimension_set_compress_interval(Dimension *dim, int64 compress_interval); extern Datum ts_dimension_transform_value(const Dimension *dim, Oid collation, Datum value, Oid const_datum_type, Oid *restype); diff --git a/src/ts_catalog/continuous_agg.c b/src/ts_catalog/continuous_agg.c index 159456f3c..dee9d9bbb 100644 --- a/src/ts_catalog/continuous_agg.c +++ b/src/ts_catalog/continuous_agg.c @@ -71,6 +71,10 @@ static const WithClauseDefinition continuous_aggregate_with_clause_def[] = { .type_id = BOOLOID, .default_val = (Datum)true, }, + [ContinuousViewOptionChunkTimeInterval] = { + .arg_names = {"chunk_time_interval", NULL}, + .type_id = INTERVALOID, + }, [ContinuousViewOptionCompressSegmentBy] = { .arg_names = {"segmentby", "compress_segmentby", NULL}, .type_id = TEXTOID, diff --git a/src/ts_catalog/continuous_agg.h b/src/ts_catalog/continuous_agg.h index 7c83d0668..9b9206c1a 100644 --- a/src/ts_catalog/continuous_agg.h +++ b/src/ts_catalog/continuous_agg.h @@ -53,6 +53,7 @@ typedef enum ContinuousAggViewOption ContinuousViewOptionMaterializedOnly, ContinuousViewOptionCompress, ContinuousViewOptionFinalized, + ContinuousViewOptionChunkTimeInterval, ContinuousViewOptionCompressSegmentBy, ContinuousViewOptionCompressOrderBy, ContinuousViewOptionCompressChunkTimeInterval, diff --git a/src/utils.h b/src/utils.h index fe8aa8b80..bd6c00e63 100644 --- a/src/utils.h +++ b/src/utils.h @@ -36,6 +36,13 @@ #define TS_DEBUG_LOG(FMT, ...) #endif +static inline int64 +interval_to_usec(Interval *interval) +{ + return (interval->month * DAYS_PER_MONTH * USECS_PER_DAY) + (interval->day * USECS_PER_DAY) + + interval->time; +} + #ifdef TS_DEBUG static inline const char * diff --git a/tsl/src/continuous_aggs/create.c b/tsl/src/continuous_aggs/create.c index 203456dbe..70bb01676 100644 --- a/tsl/src/continuous_aggs/create.c +++ b/tsl/src/continuous_aggs/create.c @@ -112,7 +112,7 @@ makeMaterializedTableName(char *buf, const char *prefix, int hypertable_id) static int32 mattablecolumninfo_create_materialization_table( MatTableColumnInfo *matcolinfo, int32 hypertable_id, RangeVar *mat_rel, CAggTimebucketInfo *bucket_info, bool create_addl_index, char *tablespacename, - char *table_access_method, ObjectAddress *mataddress); + char *table_access_method, int64 matpartcol_interval, ObjectAddress *mataddress); static Query *mattablecolumninfo_get_partial_select_query(MatTableColumnInfo *mattblinfo, Query *userview_query, bool finalized); @@ -419,6 +419,7 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, RangeVar *mat_rel, CAggTimebucketInfo *bucket_info, bool create_addl_index, char *const tablespacename, char *const table_access_method, + int64 matpartcol_interval, ObjectAddress *mataddress) { Oid uid, saved_uid; @@ -426,7 +427,6 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, char *matpartcolname = matcolinfo->matpartcolname; CreateStmt *create; Datum toast_options; - int64 matpartcol_interval; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; int32 mat_htid; Oid mat_relid; @@ -459,13 +459,6 @@ mattablecolumninfo_create_materialization_table(MatTableColumnInfo *matcolinfo, NewRelationCreateToastTable(mat_relid, toast_options); RESTORE_USER(uid, saved_uid, sec_ctx); - /* Convert the materialization table to a hypertable. */ - matpartcol_interval = bucket_info->htpartcol_interval_len; - - /* Apply the factor just for non-Hierachical CAggs */ - if (bucket_info->parent_mat_hypertable_id == INVALID_HYPERTABLE_ID) - matpartcol_interval *= MATPARTCOL_INTERVAL_FACTOR; - cagg_create_hypertable(hypertable_id, mat_relid, matpartcolname, matpartcol_interval); /* Retrieve the hypertable id from the cache. */ @@ -678,6 +671,21 @@ cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquer DatumGetBool(with_clause_options[ContinuousViewOptionMaterializedOnly].parsed); bool finalized = DatumGetBool(with_clause_options[ContinuousViewOptionFinalized].parsed); + int64 matpartcol_interval = 0; + if (!with_clause_options[ContinuousViewOptionChunkTimeInterval].is_default) + { + matpartcol_interval = interval_to_usec( + DatumGetIntervalP(with_clause_options[ContinuousViewOptionChunkTimeInterval].parsed)); + } + else + { + matpartcol_interval = bucket_info->htpartcol_interval_len; + + /* Apply the factor just for non-Hierachical CAggs */ + if (bucket_info->parent_mat_hypertable_id == INVALID_HYPERTABLE_ID) + matpartcol_interval *= MATPARTCOL_INTERVAL_FACTOR; + } + finalqinfo.finalized = finalized; /* @@ -714,6 +722,7 @@ cagg_create(const CreateTableAsStmt *create_stmt, ViewStmt *stmt, Query *panquer is_create_mattbl_index, create_stmt->into->tableSpaceName, create_stmt->into->accessMethod, + matpartcol_interval, &mataddress); /* * Step 2: Create view with select finalize from materialization table. diff --git a/tsl/src/continuous_aggs/options.c b/tsl/src/continuous_aggs/options.c index ab333f79b..724e7f731 100644 --- a/tsl/src/continuous_aggs/options.c +++ b/tsl/src/continuous_aggs/options.c @@ -185,6 +185,19 @@ continuous_agg_update_options(ContinuousAgg *agg, WithClauseResult *with_clause_ cagg_update_materialized_only(agg, materialized_only); ts_cache_release(hcache); } + if (!with_clause_options[ContinuousViewOptionChunkTimeInterval].is_default) + { + Cache *hcache = ts_hypertable_cache_pin(); + Hypertable *mat_ht = + ts_hypertable_cache_get_entry_by_id(hcache, agg->data.mat_hypertable_id); + + int64 interval = interval_to_usec( + DatumGetIntervalP(with_clause_options[ContinuousViewOptionChunkTimeInterval].parsed)); + Dimension *dim = ts_hyperspace_get_mutable_dimension(mat_ht->space, DIMENSION_TYPE_OPEN, 0); + + ts_dimension_set_chunk_interval(dim, interval); + ts_cache_release(hcache); + } List *compression_options = ts_continuous_agg_get_compression_defelems(with_clause_options); if (list_length(compression_options) > 0) diff --git a/tsl/test/expected/cagg_ddl-14.out b/tsl/test/expected/cagg_ddl-14.out index 1566edcbe..8a2281e17 100644 --- a/tsl/test/expected/cagg_ddl-14.out +++ b/tsl/test/expected/cagg_ddl-14.out @@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false); DROP MATERIALIZED VIEW cagg_alias; +-- test SET chunk_time_interval +CREATE MATERIALIZED VIEW cagg_set +WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS +SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA; +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 1 day +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 23 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 180 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 360 days +(1 row) + diff --git a/tsl/test/expected/cagg_ddl-15.out b/tsl/test/expected/cagg_ddl-15.out index 1566edcbe..8a2281e17 100644 --- a/tsl/test/expected/cagg_ddl-15.out +++ b/tsl/test/expected/cagg_ddl-15.out @@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false); DROP MATERIALIZED VIEW cagg_alias; +-- test SET chunk_time_interval +CREATE MATERIALIZED VIEW cagg_set +WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS +SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA; +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 1 day +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 23 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 180 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 360 days +(1 row) + diff --git a/tsl/test/expected/cagg_ddl-16.out b/tsl/test/expected/cagg_ddl-16.out index 9a0e66e75..38ae55129 100644 --- a/tsl/test/expected/cagg_ddl-16.out +++ b/tsl/test/expected/cagg_ddl-16.out @@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false); DROP MATERIALIZED VIEW cagg_alias; +-- test SET chunk_time_interval +CREATE MATERIALIZED VIEW cagg_set +WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS +SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA; +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 1 day +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 23 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 180 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 360 days +(1 row) + diff --git a/tsl/test/expected/cagg_ddl-17.out b/tsl/test/expected/cagg_ddl-17.out index 9a0e66e75..38ae55129 100644 --- a/tsl/test/expected/cagg_ddl-17.out +++ b/tsl/test/expected/cagg_ddl-17.out @@ -2129,3 +2129,34 @@ SELECT time_bucket(INTERVAL '1 day', time) FROM conditions GROUP BY 1 WITH NO DA ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false); DROP MATERIALIZED VIEW cagg_alias; +-- test SET chunk_time_interval +CREATE MATERIALIZED VIEW cagg_set +WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS +SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA; +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 1 day +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 23 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 180 days +(1 row) + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + column_name | time_interval +----------------------+--------------- + cagg_interval_setter | @ 360 days +(1 row) + diff --git a/tsl/test/sql/cagg_ddl.sql.in b/tsl/test/sql/cagg_ddl.sql.in index b617f5836..80d702ca9 100644 --- a/tsl/test/sql/cagg_ddl.sql.in +++ b/tsl/test/sql/cagg_ddl.sql.in @@ -1357,3 +1357,19 @@ ALTER MATERIALIZED VIEW cagg_alias SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW cagg_alias SET (tsdb.materialized_only=false); DROP MATERIALIZED VIEW cagg_alias; + +-- test SET chunk_time_interval +CREATE MATERIALIZED VIEW cagg_set +WITH (tsdb.continuous, tsdb.chunk_time_interval='1day') AS +SELECT time_bucket(INTERVAL '1 day', time) AS cagg_interval_setter FROM conditions GROUP BY 1 WITH NO DATA; + +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='23 day'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='6 month'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter'; + +ALTER MATERIALIZED VIEW cagg_set SET (tsdb.chunk_time_interval='1 year'); +SELECT column_name, time_interval FROM timescaledb_information.dimensions WHERE column_name='cagg_interval_setter';