Skip to the content.

TimescaleDB tool family — design

Status: implemented in the PR for issue #353 (2026-10-14); the open questions below were answered by the Phase 0 spike (see “Phase 0 results”). Spawned by issue #353 and the ALTER SYSTEM tools (PR #352).

Why now

MCPg’s TimescaleDB support (src/mcpg/timescaledb.py, shipped long ago) is five tools: list_hypertables, list_chunks (read) and create_hypertable, add_compression_policy, add_retention_policy (DDL-gated). Two things have changed:

  1. Issue #353 shows users want to query with Timescale functions (time_bucket, first/last, size/stats functions). The SQL-safety allowlist change for the read-only ones is a separate small PR.
  2. Everything else Timescale offers (drop chunks, manual compression, jobs, continuous-aggregate refresh, telemetry) is reachable only via run_ddl/run_sql, which cannot run most of it.

Finding while preparing this doc: there is no TimescaleDB lane in CI and no Timescale integration test (tests/integration and .github/workflows mention it nowhere). The five existing tools are covered by unit tests with a mocked driver only. Building more on that without a real instance is the main risk, hence Phase 0 below.

Verified facts vs. open questions

Verified against the vendor API reference (www.tigerdata.com/docs/api/latest, fetched 2026-10-14):

Not verified (docs silent) — must be settled by Phase 0 on a real instance:

Scope

In scope: read tools beyond hypertable/chunk listing; gated mutating tools; procedure calls; telemetry read; CI coverage. Out of scope: Timescale Cloud/Tiger-specific APIs, multi-node (removed upstream), timescaledb_pre_restore/post_restore (they flip global restore state; belongs to a dump/restore runbook, not an agent tool).

Proposed surface

All tools take schema/table as separate validated identifiers (existing _check_identifier/_regclass_literal helpers), validate intervals with the existing _check_interval, return typed dataclasses, and report available=false when the extension is missing — same conventions as today’s tools.

Tier R — reads (READ gate)

Tool Wraps
get_hypertable_stats hypertable_detailed_size, hypertable_compression_stats / hypertable_columnstore_stats (version-detected), approximate_row_count
list_timescale_jobs timescaledb_information.jobs + job_stats (next start, last status, failures)
list_continuous_aggregates timescaledb_information.continuous_aggregates
get_timescaledb_telemetry_report get_telemetry_report() — only after the Phase 0 check; otherwise dropped

Tier A — additive/reversible (DDL gate, as today)

add_dimension, set_chunk_time_interval, enable_chunk_skipping, add_continuous_aggregate_policy, add_reorder_policy, and the matching remove_*_policy tools. Same gate as create_hypertable: unrestricted mode + MCPG_ALLOW_DDL.

Tier B — destructive or heavy (separate gate + confirm)

drop_chunks, compress_chunk, decompress_chunk, reorder_chunk, move_chunk, alter_job, delete_job, run_job, refresh_continuous_aggregate, and the columnstore/merge/split procedures once verified.

Design follows the ALTER SYSTEM tools (see docs/alter-system.md on PR #352):

SQL-safety allowlist (separate, small PR)

Read-only function names go in sql/allowlist.py (ALLOWED_FUNCTIONS); mutating functions and procedures are never added there, since the safe driver is the read-only path. Done on branch fix/timescaledb-readonly-functions-353.

Phasing

  1. Spike + CI lane. Add a TimescaleDB integration lane (image with the extension, continue-on-error initially like PG 19/WarehousePG), first tests covering today’s five tools. Answer the open questions above and record the results here.
  2. Tier R tools (+ telemetry if cleared).
  3. Tier A tools.
  4. Tier B tools with confirm flow and gate flag. Each phase: module code, registration, bucket in about.py, tests, both contract snapshots, doc tables regenerated, CHANGELOG (docs/contributing/adding-tools.md).

Risks

Phase 0 results (TimescaleDB 2.30.2, PG 17, official image)

Run against a throwaway container, not from the vendor docs:

Question Result
Procedures in a transaction block? Cannot: refresh_continuous_aggregate, merge_chunks_concurrently, and the function reorder_chunk fail with “cannot run inside a transaction block”. Can: run_job, convert_to_rowstore/columnstore, merge_chunks, detach_chunk, split_chunk, drop_chunks (rolls back cleanly), compress_chunk, alter_job, delete_job, add_job, add_dimension, set_chunk_time_interval, the add_*_policy functions.
get_telemetry_report() sends data? No. It returns the locally built report with the server’s network disconnected. Uploading is the separate policy_telemetry job (job 1), governed by timescaledb.telemetry_level (default basic). The report includes db_uuid.
*_columnstore_* on 2.30.2? Present, alongside the *_compression_* names; the stats functions return no row for a hypertable without compression enabled.
Privileges A table owner (non-superuser) can create hypertables, add/alter policies, run_job, drop_chunks and read get_telemetry_report() for their own tables; another owner’s hypertable gives “must be owner”; deleting another owner’s job gives “insufficient permissions”. pg_file_settings is superuser-only (relevant to ALTER SYSTEM RESET ALL, which fails closed).
Other findings enable_chunk_skipping errors unless timescaledb.enable_chunk_skipping is on; recompress_chunk is deprecated in favour of compress_chunk; user/policy job ids start at 1000, system jobs are below; continuous_aggregates.finalized does not exist in 2.30.2.

Final scope

User-facing reference: docs/timescaledb.md.