Skip to content

Commit

Permalink
Add function to drop the osm chunk
Browse files Browse the repository at this point in the history
  • Loading branch information
konskov committed Apr 5, 2024
1 parent 8d9b062 commit fc86ea0
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 0 deletions.
6 changes: 6 additions & 0 deletions sql/chunk.sql
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ CREATE OR REPLACE FUNCTION _timescaledb_functions.attach_osm_table_chunk(
hypertable REGCLASS,
chunk REGCLASS)
RETURNS BOOL AS '@MODULE_PATHNAME@', 'ts_chunk_attach_osm_table_chunk' LANGUAGE C VOLATILE;

-- internal API used by OSM extension to drop an OSM chunk table from the hypertable
CREATE OR REPLACE FUNCTION _timescaledb_functions.drop_osm_table_chunk(
hypertable REGCLASS,
chunk REGCLASS)
RETURNS BOOL AS '@MODULE_PATHNAME@', 'ts_chunk_drop_osm_table_chunk' LANGUAGE C VOLATILE;
5 changes: 5 additions & 0 deletions sql/updates/latest-dev.sql
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,8 @@ DROP FUNCTION IF EXISTS _timescaledb_functions.policy_job_error_retention_check(
--
-- END bgw_job_stat_history
--

CREATE FUNCTION _timescaledb_functions.drop_osm_table_chunk(
hypertable REGCLASS,
chunk REGCLASS)
RETURNS BOOL AS '@MODULE_PATHNAME@', 'ts_chunk_drop_osm_table_chunk' LANGUAGE C VOLATILE;
2 changes: 2 additions & 0 deletions sql/updates/reverse-dev.sql
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,5 @@ SET
check_name = 'policy_job_error_retention_check'
WHERE
id = 2;

DROP FUNCTION IF EXISTS _timescaledb_functions.drop_osm_table_chunk(REGCLASS, REGCLASS);
40 changes: 40 additions & 0 deletions src/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ TS_FUNCTION_INFO_V1(ts_chunk_id_from_relid);
TS_FUNCTION_INFO_V1(ts_chunk_show);
TS_FUNCTION_INFO_V1(ts_chunk_create);
TS_FUNCTION_INFO_V1(ts_chunk_status);
TS_FUNCTION_INFO_V1(ts_chunk_drop_osm_table_chunk);

static bool ts_chunk_add_status(Chunk *chunk, int32 status);

Expand Down Expand Up @@ -5189,3 +5190,42 @@ get_chunks_in_creation_time_range(Hypertable *ht, int64 older_than, int64 newer_

return chunks;
}

Datum
ts_chunk_drop_osm_table_chunk(PG_FUNCTION_ARGS)
{
Oid hypertable_relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
Cache *hcache = ts_hypertable_cache_pin();
Hypertable *ht = ts_resolve_hypertable_from_table_or_cagg(hcache, hypertable_relid, true);

Oid chunk_relid = PG_ARGISNULL(1) ? InvalidOid : PG_GETARG_OID(1);
char *chunk_table_name = get_rel_name(chunk_relid);
char *chunk_schema_name = get_namespace_name(get_rel_namespace(chunk_relid));

const Chunk *ch = ts_chunk_get_by_name_with_memory_context(chunk_schema_name,
chunk_table_name,
CurrentMemoryContext,
true);
Assert(ch != NULL);
if (!ch->fd.osm_chunk)
ereport(ERROR,
(errcode(ERRCODE_TS_OPERATION_NOT_SUPPORTED),
errmsg("attempting to drop chunk which is not an OSM chunk"),
errhint("Use the drop_chunk() function instead")));
if (ch->fd.hypertable_id != ht->fd.id)
ereport(ERROR,
(errcode(ERRCODE_TS_UNEXPECTED),
errmsg("OSM chunk %s.%s does not correspond to hypertable %s.%s",
chunk_schema_name,
chunk_table_name,
ht->fd.schema_name.data,
ht->fd.table_name.data)));
ts_chunk_validate_chunk_status_for_operation(ch, CHUNK_DROP, true /*throw_error */);
/* do not drop any chunk dependencies */
ts_chunk_drop(ch, DROP_RESTRICT, LOG);
/* reset hypertable OSM status */
ht->fd.status = HYPERTABLE_STATUS_DEFAULT;
ts_hypertable_update(ht);
ts_cache_release(hcache);
PG_RETURN_BOOL(true);
}
106 changes: 106 additions & 0 deletions tsl/test/expected/chunk_utils_internal.out
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,112 @@ ERROR: Cannot insert into tiered chunk range of public.osm_slice_update - attem
INSERT INTO osm_slice_update VALUES (1);
ERROR: Cannot insert into tiered chunk range of public.osm_slice_update - attempt to create new chunk with range [0 10] failed
\set ON_ERROR_STOP 1
-- test the drop_osm_table_chunk function
-- should not appear in timescale catalogs, or PG catalogs, or in the inheritance tree
\c :TEST_DBNAME :ROLE_4;
\d+ test_chunkapp
Table "public.test_chunkapp"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+--------------------------+-----------+----------+---------+---------+--------------+-------------
time | timestamp with time zone | | not null | | plain | |
a | integer | | | | plain | |
Indexes:
"test_chunkapp_time_idx" btree ("time" DESC)
Check constraints:
"test_chunkapp_a_check" CHECK (a > 0)
Triggers:
ts_insert_blocker BEFORE INSERT ON test_chunkapp FOR EACH ROW EXECUTE FUNCTION _timescaledb_functions.insert_blocker()
Child tables: _timescaledb_internal._hyper_16_26_chunk,
_timescaledb_internal._hyper_16_27_chunk,
test_chunkapp_fdw_child

select id as htid from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp' \gset
select status from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp'; -- status should be 1
status
--------
1
(1 row)

SELECT FROM _timescaledb_catalog.chunk ch, _timescaledb_catalog.hypertable ht
WHERE ht.table_name = 'test_chunkapp' and ht.id = ch.hypertable_id AND ch.osm_chunk IS TRUE; -- expect 1 entry
--
(1 row)

SELECT cc.chunk_id, c.table_name, c.status, c.osm_chunk, cc.dimension_slice_id, ds.range_start, ds.range_end
FROM _timescaledb_catalog.chunk c, _timescaledb_catalog.chunk_constraint cc, _timescaledb_catalog.dimension_slice ds
WHERE c.hypertable_id = :htid AND cc.chunk_id = c.id AND ds.id = cc.dimension_slice_id ORDER BY cc.chunk_id;
chunk_id | table_name | status | osm_chunk | dimension_slice_id | range_start | range_end
----------+-------------------------+--------+-----------+--------------------+---------------------+---------------------
26 | _hyper_16_26_chunk | 0 | f | 23 | 1577836800000000 | 1577923200000000
27 | _hyper_16_27_chunk | 0 | f | 24 | 1577923200000000 | 1578009600000000
28 | test_chunkapp_fdw_child | 0 | t | 25 | 9223372036854775806 | 9223372036854775807
(3 rows)

-- it is empty so let's drop it
select * from test_chunkapp_fdw_child;
time | a
------+---
(0 rows)

\set ON_ERROR_STOP 0
begin;
select _timescaledb_functions.drop_osm_table_chunk('osm_int2', 'test_chunkapp_fdw_child');
ERROR: OSM chunk public.test_chunkapp_fdw_child does not correspond to hypertable public.osm_int2
rollback;
\set ON_ERROR_STOP 1
select _timescaledb_functions.drop_osm_table_chunk('test_chunkapp', 'test_chunkapp_fdw_child');
drop_osm_table_chunk
----------------------
t
(1 row)

-- foreign chunk no longer appears in the inheritance hierarchy
\d+ test_chunkapp
Table "public.test_chunkapp"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+--------------------------+-----------+----------+---------+---------+--------------+-------------
time | timestamp with time zone | | not null | | plain | |
a | integer | | | | plain | |
Indexes:
"test_chunkapp_time_idx" btree ("time" DESC)
Check constraints:
"test_chunkapp_a_check" CHECK (a > 0)
Triggers:
ts_insert_blocker BEFORE INSERT ON test_chunkapp FOR EACH ROW EXECUTE FUNCTION _timescaledb_functions.insert_blocker()
Child tables: _timescaledb_internal._hyper_16_26_chunk,
_timescaledb_internal._hyper_16_27_chunk

-- hypertable status is reset
select status from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp'; -- status 0
status
--------
0
(1 row)

SELECT FROM _timescaledb_catalog.chunk ch, _timescaledb_catalog.hypertable ht
WHERE ht.table_name = 'test_chunkapp' and ht.id = ch.hypertable_id AND ch.osm_chunk IS TRUE; -- expect 0 entries
--
(0 rows)

-- chunk constraint and dimension slice should have been cleaned up as well
SELECT cc.chunk_id, c.table_name, c.status, c.osm_chunk, cc.dimension_slice_id, ds.range_start, ds.range_end
FROM _timescaledb_catalog.chunk c, _timescaledb_catalog.chunk_constraint cc, _timescaledb_catalog.dimension_slice ds
WHERE c.hypertable_id = :htid AND cc.chunk_id = c.id AND ds.id = cc.dimension_slice_id ORDER BY cc.chunk_id;
chunk_id | table_name | status | osm_chunk | dimension_slice_id | range_start | range_end
----------+--------------------+--------+-----------+--------------------+------------------+------------------
26 | _hyper_16_26_chunk | 0 | f | 23 | 1577836800000000 | 1577923200000000
27 | _hyper_16_27_chunk | 0 | f | 24 | 1577923200000000 | 1578009600000000
(2 rows)

-- test selects work as expected
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) SELECT * FROM test_chunkapp;
QUERY PLAN
--------------------------------------------------------------
Append (actual rows=2 loops=1)
-> Seq Scan on _hyper_16_26_chunk (actual rows=1 loops=1)
-> Seq Scan on _hyper_16_27_chunk (actual rows=1 loops=1)
(3 rows)

-- clean up databases created
\c :TEST_DBNAME :ROLE_SUPERUSER
DROP DATABASE postgres_fdw_db WITH (FORCE);
1 change: 1 addition & 0 deletions tsl/test/shared/expected/extension.out
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
_timescaledb_functions.dimension_info_in(cstring)
_timescaledb_functions.dimension_info_out(_timescaledb_internal.dimension_info)
_timescaledb_functions.drop_chunk(regclass)
_timescaledb_functions.drop_osm_table_chunk(regclass,regclass)
_timescaledb_functions.finalize_agg(text,name,name,name[],bytea,anyelement)
_timescaledb_functions.finalize_agg_ffunc(internal,text,name,name,name[],bytea,anyelement)
_timescaledb_functions.finalize_agg_sfunc(internal,text,name,name,name[],bytea,anyelement)
Expand Down
34 changes: 34 additions & 0 deletions tsl/test/sql/chunk_utils_internal.sql
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,40 @@ INSERT INTO osm_slice_update VALUES (1);
INSERT INTO osm_slice_update VALUES (1);
\set ON_ERROR_STOP 1

-- test the drop_osm_table_chunk function
-- should not appear in timescale catalogs, or PG catalogs, or in the inheritance tree
\c :TEST_DBNAME :ROLE_4;
\d+ test_chunkapp
select id as htid from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp' \gset
select status from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp'; -- status should be 1
SELECT FROM _timescaledb_catalog.chunk ch, _timescaledb_catalog.hypertable ht
WHERE ht.table_name = 'test_chunkapp' and ht.id = ch.hypertable_id AND ch.osm_chunk IS TRUE; -- expect 1 entry
SELECT cc.chunk_id, c.table_name, c.status, c.osm_chunk, cc.dimension_slice_id, ds.range_start, ds.range_end
FROM _timescaledb_catalog.chunk c, _timescaledb_catalog.chunk_constraint cc, _timescaledb_catalog.dimension_slice ds
WHERE c.hypertable_id = :htid AND cc.chunk_id = c.id AND ds.id = cc.dimension_slice_id ORDER BY cc.chunk_id;
-- it is empty so let's drop it
select * from test_chunkapp_fdw_child;
\set ON_ERROR_STOP 0
begin;
select _timescaledb_functions.drop_osm_table_chunk('osm_int2', 'test_chunkapp_fdw_child');
rollback;
\set ON_ERROR_STOP 1

select _timescaledb_functions.drop_osm_table_chunk('test_chunkapp', 'test_chunkapp_fdw_child');
-- foreign chunk no longer appears in the inheritance hierarchy
\d+ test_chunkapp
-- hypertable status is reset
select status from _timescaledb_catalog.hypertable where table_name = 'test_chunkapp'; -- status 0
SELECT FROM _timescaledb_catalog.chunk ch, _timescaledb_catalog.hypertable ht
WHERE ht.table_name = 'test_chunkapp' and ht.id = ch.hypertable_id AND ch.osm_chunk IS TRUE; -- expect 0 entries

-- chunk constraint and dimension slice should have been cleaned up as well
SELECT cc.chunk_id, c.table_name, c.status, c.osm_chunk, cc.dimension_slice_id, ds.range_start, ds.range_end
FROM _timescaledb_catalog.chunk c, _timescaledb_catalog.chunk_constraint cc, _timescaledb_catalog.dimension_slice ds
WHERE c.hypertable_id = :htid AND cc.chunk_id = c.id AND ds.id = cc.dimension_slice_id ORDER BY cc.chunk_id;
-- test selects work as expected
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) SELECT * FROM test_chunkapp;

-- clean up databases created
\c :TEST_DBNAME :ROLE_SUPERUSER
DROP DATABASE postgres_fdw_db WITH (FORCE);

0 comments on commit fc86ea0

Please sign in to comment.