Skip to content

Commit

Permalink
Fix catalog corruption on Continuous Aggregate
Browse files Browse the repository at this point in the history
Unfortunately the code-path for `ALTER TABLE...{RENAME | SET SCHEMA}`
over a Continuous Aggregate was not handled very well in the process
utility hook leading to a catalog corruption because it was not
updating properly the internal metadata information.

Fixed it by properly update the catalog information.
  • Loading branch information
fabriziomello committed Jun 17, 2024
1 parent c978c69 commit 738ca4e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 44 deletions.
85 changes: 52 additions & 33 deletions src/process_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,30 @@ process_drop_trigger_start(ProcessUtilityArgs *args, DropStmt *stmt)
ts_cache_release(hcache);
}

/* We use this for both materialized views and views. */
static void
process_alterviewschema(ProcessUtilityArgs *args)
{
AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) args->parsetree;
Oid relid;
char *schema;
char *name;

Assert(stmt->objectType == OBJECT_MATVIEW || stmt->objectType == OBJECT_VIEW);

if (NULL == stmt->relation)
return;

relid = RangeVarGetRelid(stmt->relation, NoLock, true);
if (!OidIsValid(relid))
return;

schema = get_namespace_name(get_rel_namespace(relid));
name = get_rel_name(relid);

ts_continuous_agg_rename_view(schema, name, stmt->newschema, name, &stmt->objectType);
}

static void
process_altertableschema(ProcessUtilityArgs *args)
{
Expand All @@ -448,6 +472,16 @@ process_altertableschema(ProcessUtilityArgs *args)

if (ht == NULL)
{
ContinuousAgg *cagg = ts_continuous_agg_find_by_relid(relid);

if (cagg)
{
alterstmt->objectType = OBJECT_MATVIEW;
process_alterviewschema(args);
ts_cache_release(hcache);
return;
}

Chunk *chunk = ts_chunk_get_by_relid(relid, false);

if (NULL != chunk)
Expand All @@ -463,30 +497,6 @@ process_altertableschema(ProcessUtilityArgs *args)
ts_cache_release(hcache);
}

/* We use this for both materialized views and views. */
static void
process_alterviewschema(ProcessUtilityArgs *args)
{
AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) args->parsetree;
Oid relid;
char *schema;
char *name;

Assert(stmt->objectType == OBJECT_MATVIEW || stmt->objectType == OBJECT_VIEW);

if (NULL == stmt->relation)
return;

relid = RangeVarGetRelid(stmt->relation, NoLock, true);
if (!OidIsValid(relid))
return;

schema = get_namespace_name(get_rel_namespace(relid));
name = get_rel_name(relid);

ts_continuous_agg_rename_view(schema, name, stmt->newschema, name, &stmt->objectType);
}

/* Change the schema of a hypertable or a chunk */
static DDLResult
process_alterobjectschema(ProcessUtilityArgs *args)
Expand Down Expand Up @@ -1820,8 +1830,16 @@ process_reindex(ProcessUtilityArgs *args)
return result;
}

static void
process_rename_view(Oid relid, RenameStmt *stmt)
{
char *schema = get_namespace_name(get_rel_namespace(relid));
char *name = get_rel_name(relid);
ts_continuous_agg_rename_view(schema, name, schema, stmt->newname, &stmt->renameType);
}

/*
* Rename a hypertable or a chunk.
* Rename a hypertable, chunk or continuous aggregate.
*/
static void
process_rename_table(ProcessUtilityArgs *args, Cache *hcache, Oid relid, RenameStmt *stmt)
Expand All @@ -1830,6 +1848,15 @@ process_rename_table(ProcessUtilityArgs *args, Cache *hcache, Oid relid, RenameS

if (NULL == ht)
{
ContinuousAgg *cagg = ts_continuous_agg_find_by_relid(relid);

if (cagg)
{
stmt->renameType = OBJECT_MATVIEW;
process_rename_view(relid, stmt);
return;
}

Chunk *chunk = ts_chunk_get_by_relid(relid, false);

if (NULL != chunk)
Expand Down Expand Up @@ -1955,14 +1982,6 @@ process_rename_index(ProcessUtilityArgs *args, Cache *hcache, Oid relid, RenameS
}
}

static void
process_rename_view(Oid relid, RenameStmt *stmt)
{
char *schema = get_namespace_name(get_rel_namespace(relid));
char *name = get_rel_name(relid);
ts_continuous_agg_rename_view(schema, name, schema, stmt->newname, &stmt->renameType);
}

/* Visit all internal catalog tables with a schema column to check for applicable rename */
static void
process_rename_schema(RenameStmt *stmt)
Expand Down
17 changes: 14 additions & 3 deletions tsl/test/expected/cagg_ddl-14.out
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLE
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;
CREATE SCHEMA test_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER;
SET ROLE :ROLE_DEFAULT_PERM_USER;
CREATE TABLE foo(time TIMESTAMPTZ NOT NULL, data INTEGER);
SELECT create_hypertable('foo', 'time');
Expand All @@ -39,19 +40,29 @@ SELECT create_hypertable('foo', 'time');
(2,public,foo,t)
(1 row)

CREATE MATERIALIZED VIEW rename_test
CREATE MATERIALIZED VIEW rename_test_old
WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('1week', time), COUNT(data)
FROM foo
GROUP BY 1 WITH NO DATA;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+-----------------+-----------------------+-------------------
public | rename_test_old | _timescaledb_internal | _partial_view_3
(1 row)

ALTER TABLE rename_test_old RENAME TO rename_test;
ALTER TABLE rename_test SET SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+----------------+-----------------------+-------------------
public | rename_test | _timescaledb_internal | _partial_view_3
test_schema | rename_test | _timescaledb_internal | _partial_view_3
(1 row)

ALTER MATERIALIZED VIEW rename_test SET SCHEMA rename_schema;
ALTER MATERIALIZED VIEW test_schema.rename_test SET SCHEMA rename_schema;
DROP SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
Expand Down
17 changes: 14 additions & 3 deletions tsl/test/expected/cagg_ddl-15.out
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLE
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;
CREATE SCHEMA test_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER;
SET ROLE :ROLE_DEFAULT_PERM_USER;
CREATE TABLE foo(time TIMESTAMPTZ NOT NULL, data INTEGER);
SELECT create_hypertable('foo', 'time');
Expand All @@ -39,19 +40,29 @@ SELECT create_hypertable('foo', 'time');
(2,public,foo,t)
(1 row)

CREATE MATERIALIZED VIEW rename_test
CREATE MATERIALIZED VIEW rename_test_old
WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('1week', time), COUNT(data)
FROM foo
GROUP BY 1 WITH NO DATA;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+-----------------+-----------------------+-------------------
public | rename_test_old | _timescaledb_internal | _partial_view_3
(1 row)

ALTER TABLE rename_test_old RENAME TO rename_test;
ALTER TABLE rename_test SET SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+----------------+-----------------------+-------------------
public | rename_test | _timescaledb_internal | _partial_view_3
test_schema | rename_test | _timescaledb_internal | _partial_view_3
(1 row)

ALTER MATERIALIZED VIEW rename_test SET SCHEMA rename_schema;
ALTER MATERIALIZED VIEW test_schema.rename_test SET SCHEMA rename_schema;
DROP SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
Expand Down
17 changes: 14 additions & 3 deletions tsl/test/expected/cagg_ddl-16.out
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLE
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;
CREATE SCHEMA test_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER;
SET ROLE :ROLE_DEFAULT_PERM_USER;
CREATE TABLE foo(time TIMESTAMPTZ NOT NULL, data INTEGER);
SELECT create_hypertable('foo', 'time');
Expand All @@ -39,19 +40,29 @@ SELECT create_hypertable('foo', 'time');
(2,public,foo,t)
(1 row)

CREATE MATERIALIZED VIEW rename_test
CREATE MATERIALIZED VIEW rename_test_old
WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('1week', time), COUNT(data)
FROM foo
GROUP BY 1 WITH NO DATA;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+-----------------+-----------------------+-------------------
public | rename_test_old | _timescaledb_internal | _partial_view_3
(1 row)

ALTER TABLE rename_test_old RENAME TO rename_test;
ALTER TABLE rename_test SET SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
------------------+----------------+-----------------------+-------------------
public | rename_test | _timescaledb_internal | _partial_view_3
test_schema | rename_test | _timescaledb_internal | _partial_view_3
(1 row)

ALTER MATERIALIZED VIEW rename_test SET SCHEMA rename_schema;
ALTER MATERIALIZED VIEW test_schema.rename_test SET SCHEMA rename_schema;
DROP SCHEMA test_schema;
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
user_view_schema | user_view_name | partial_view_schema | partial_view_name
Expand Down
13 changes: 11 additions & 2 deletions tsl/test/sql/cagg_ddl.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLE
CREATE SCHEMA rename_schema;
GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER;

CREATE SCHEMA test_schema AUTHORIZATION :ROLE_DEFAULT_PERM_USER;

SET ROLE :ROLE_DEFAULT_PERM_USER;

CREATE TABLE foo(time TIMESTAMPTZ NOT NULL, data INTEGER);

SELECT create_hypertable('foo', 'time');

CREATE MATERIALIZED VIEW rename_test
CREATE MATERIALIZED VIEW rename_test_old
WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('1week', time), COUNT(data)
FROM foo
Expand All @@ -50,7 +52,14 @@ AS SELECT time_bucket('1week', time), COUNT(data)
SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;

ALTER MATERIALIZED VIEW rename_test SET SCHEMA rename_schema;
ALTER TABLE rename_test_old RENAME TO rename_test;
ALTER TABLE rename_test SET SCHEMA test_schema;

SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;

ALTER MATERIALIZED VIEW test_schema.rename_test SET SCHEMA rename_schema;
DROP SCHEMA test_schema;

SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name
FROM _timescaledb_catalog.continuous_agg;
Expand Down

0 comments on commit 738ca4e

Please sign in to comment.