Skip to content

Commit

Permalink
Simplify hypertable DDL APIs
Browse files Browse the repository at this point in the history
The current hypertable creation interface is heavily focused on a time
column, but since hypertables are focused on partitioning of not only
time columns, we introduce a more generic API that support different
types of keys for partitioning.

The new interface introduced new versions of create_hypertable,
add_dimension, and a replacement function `set_partitioning_interval`
that replaces `set_chunk_time_interval`. The new functions accept an
instance of dimension_info that can be constructed using constructor
functions `by_range` and `by_hash`, allowing a more versatile and
future-proof API.

For examples:

    SELECT create_hypertable('conditions', by_range('time'));
    SELECT add_dimension('conditions', by_hash('device'));

The old API remains, but will eventually be deprecated.
  • Loading branch information
pdipesh02 authored and mkindahl committed Sep 27, 2023
1 parent d07cb91 commit e7340e3
Show file tree
Hide file tree
Showing 29 changed files with 1,628 additions and 335 deletions.
2 changes: 2 additions & 0 deletions .unreleased/feature_5761
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Implements: #5761 Simplify hypertable DDL API
Thanks: @pdipesh02 for contributing to the implementation of the generalized hypertable API
66 changes: 60 additions & 6 deletions sql/ddl_api.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ CREATE OR REPLACE FUNCTION @[email protected]_distributed_hypertable(
data_nodes NAME[] = NULL
) RETURNS TABLE(hypertable_id INT, schema_name NAME, table_name NAME, created BOOL) AS '@MODULE_PATHNAME@', 'ts_hypertable_distributed_create' LANGUAGE C VOLATILE;

-- A generalized hypertable creation API that can be used to convert a PostgreSQL table
-- with TIME/SERIAL/BIGSERIAL columns to a hypertable.
--
-- relation - The OID of the table to be converted
-- dimension - The dimension to use for partitioning
-- create_default_indexes (Optional) Whether or not to create the default indexes
-- if_not_exists (Optional) Do not fail if table is already a hypertable
-- migrate_data (Optional) Set to true to migrate any existing data in the table to chunks
CREATE OR REPLACE FUNCTION @[email protected]_hypertable(
relation REGCLASS,
dimension _timescaledb_internal.dimension_info,
create_default_indexes BOOLEAN = TRUE,
if_not_exists BOOLEAN = FALSE,
migrate_data BOOLEAN = FALSE
) RETURNS TABLE(hypertable_id INT, created BOOL) AS '@MODULE_PATHNAME@', 'ts_hypertable_create_general' LANGUAGE C VOLATILE;


-- Set adaptive chunking. To disable, set chunk_target_size => 'off'.
CREATE OR REPLACE FUNCTION @[email protected]_adaptive_chunking(
hypertable REGCLASS,
Expand All @@ -70,7 +87,7 @@ CREATE OR REPLACE FUNCTION @[email protected]_adaptive_chunking(
OUT chunk_target_size BIGINT
) RETURNS RECORD AS '@MODULE_PATHNAME@', 'ts_chunk_adaptive_set' LANGUAGE C VOLATILE;

-- Update chunk_time_interval for a hypertable.
-- Update chunk_time_interval for a hypertable [DEPRECATED].
--
-- hypertable - The OID of the table corresponding to a hypertable whose time
-- interval should be updated
Expand All @@ -84,6 +101,20 @@ CREATE OR REPLACE FUNCTION @[email protected]_chunk_time_interval(
dimension_name NAME = NULL
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_dimension_set_interval' LANGUAGE C VOLATILE;

-- Update partition_interval for a hypertable.
--
-- hypertable - The OID of the table corresponding to a hypertable whose
-- partition interval should be updated
-- partition_interval - The new interval. For hypertables with integral/serial/bigserial
-- time columns, this must be an integral type. For hypertables with a
-- TIMESTAMP/TIMESTAMPTZ/DATE type, it can be integral which is treated as
-- microseconds, or an INTERVAL type.
CREATE OR REPLACE FUNCTION @[email protected]_partitioning_interval(
hypertable REGCLASS,
partition_interval ANYELEMENT,
dimension_name NAME = NULL
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_dimension_set_interval' LANGUAGE C VOLATILE;

CREATE OR REPLACE FUNCTION @[email protected]_number_partitions(
hypertable REGCLASS,
number_partitions INTEGER,
Expand All @@ -109,12 +140,12 @@ CREATE OR REPLACE FUNCTION @[email protected]_chunks(
) RETURNS SETOF REGCLASS AS '@MODULE_PATHNAME@', 'ts_chunk_show_chunks'
LANGUAGE C STABLE PARALLEL SAFE;

-- Add a dimension (of partitioning) to a hypertable
-- Add a dimension (of partitioning) to a hypertable [DEPRECATED]
--
-- hypertable - OID of the table to add a dimension to
-- column_name - NAME of the column to use in partitioning for this dimension
-- number_partitions - Number of partitions, for non-time dimensions
-- interval_length - Size of intervals for time dimensions (can be integral or INTERVAL)
-- chunk_time_interval - Size of intervals for time dimensions (can be integral or INTERVAL)
-- partitioning_func - Function used to partition the column
-- if_not_exists - If set, and the dimension already exists, generate a notice instead of an error
CREATE OR REPLACE FUNCTION @[email protected]_dimension(
Expand All @@ -127,6 +158,29 @@ CREATE OR REPLACE FUNCTION @[email protected]_dimension(
) RETURNS TABLE(dimension_id INT, schema_name NAME, table_name NAME, column_name NAME, created BOOL)
AS '@MODULE_PATHNAME@', 'ts_dimension_add' LANGUAGE C VOLATILE;

-- Add a dimension (of partitioning) to a hypertable.
--
-- hypertable - OID of the table to add a dimension to
-- dimension - Dimension to add
-- if_not_exists - If set, and the dimension already exists, generate a notice instead of an error
CREATE OR REPLACE FUNCTION @[email protected]_dimension(
hypertable REGCLASS,
dimension _timescaledb_internal.dimension_info,
if_not_exists BOOLEAN = FALSE
) RETURNS TABLE(dimension_id INT, created BOOL)
AS '@MODULE_PATHNAME@', 'ts_dimension_add_general' LANGUAGE C VOLATILE;

CREATE OR REPLACE FUNCTION @[email protected]_hash(column_name NAME, number_partitions INTEGER,
partition_func regproc = NULL)
RETURNS _timescaledb_internal.dimension_info LANGUAGE C
AS '@MODULE_PATHNAME@', 'ts_hash_dimension';

CREATE OR REPLACE FUNCTION @[email protected]_range(column_name NAME,
partition_interval ANYELEMENT = NULL::bigint,
partition_func regproc = NULL)
RETURNS _timescaledb_internal.dimension_info LANGUAGE C
AS '@MODULE_PATHNAME@', 'ts_range_dimension';

CREATE OR REPLACE FUNCTION @[email protected]_tablespace(
tablespace NAME,
hypertable REGCLASS,
Expand Down Expand Up @@ -166,7 +220,7 @@ CREATE OR REPLACE FUNCTION @[email protected]_data_node(
if_exists BOOLEAN = FALSE,
force BOOLEAN = FALSE,
repartition BOOLEAN = TRUE,
drop_database BOOLEAN = FALSE
drop_database BOOLEAN = FALSE
) RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'ts_data_node_delete' LANGUAGE C VOLATILE;

-- Attach a data node to a distributed hypertable
Expand All @@ -185,7 +239,7 @@ CREATE OR REPLACE FUNCTION @[email protected]_data_node(
if_attached BOOLEAN = FALSE,
force BOOLEAN = FALSE,
repartition BOOLEAN = TRUE,
drop_remote_data BOOLEAN = FALSE
drop_remote_data BOOLEAN = FALSE
) RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_data_node_detach' LANGUAGE C VOLATILE;

Expand Down Expand Up @@ -222,6 +276,6 @@ CREATE OR REPLACE FUNCTION @[email protected]_data_node(
host TEXT = NULL,
database NAME = NULL,
port INTEGER = NULL,
available BOOLEAN = NULL
available BOOLEAN = NULL
) RETURNS TABLE(node_name NAME, host TEXT, port INTEGER, database NAME, available BOOLEAN)
AS '@MODULE_PATHNAME@', 'ts_data_node_alter' LANGUAGE C VOLATILE;
1 change: 0 additions & 1 deletion sql/partitioning.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ CREATE OR REPLACE FUNCTION _timescaledb_functions.get_partition_for_key(val anye
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_partition_hash(val anyelement)
RETURNS int
AS '@MODULE_PATHNAME@', 'ts_get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

11 changes: 11 additions & 0 deletions sql/pre_install/types.functions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_functions.rxid_in(cstring) RETURNS @exts

CREATE OR REPLACE FUNCTION _timescaledb_functions.rxid_out(@[email protected]) RETURNS cstring
AS '@MODULE_PATHNAME@', 'ts_remote_txn_id_out' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE OR REPLACE FUNCTION _timescaledb_functions.dimension_info_in(cstring)
RETURNS _timescaledb_internal.dimension_info
LANGUAGE C STRICT IMMUTABLE
AS '@MODULE_PATHNAME@', 'ts_dimension_info_in';

CREATE OR REPLACE FUNCTION _timescaledb_functions.dimension_info_out(_timescaledb_internal.dimension_info)
RETURNS cstring
LANGUAGE C STRICT IMMUTABLE
AS '@MODULE_PATHNAME@', 'ts_dimension_info_out';

9 changes: 9 additions & 0 deletions sql/pre_install/types.post.sql
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ CREATE TYPE @[email protected] (
input = _timescaledb_functions.rxid_in,
output = _timescaledb_functions.rxid_out
);

-- Dimension type used in create_hypertable, add_dimension, etc. It is
-- deliberately an opaque type.
CREATE TYPE _timescaledb_internal.dimension_info (
INPUT = _timescaledb_functions.dimension_info_in,
OUTPUT = _timescaledb_functions.dimension_info_out,
INTERNALLENGTH = VARIABLE
);

3 changes: 3 additions & 0 deletions sql/pre_install/types.pre.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ CREATE TYPE _timescaledb_internal.compressed_data;
CREATE TYPE @[email protected];

--placeholder to allow creation of functions below

CREATE TYPE _timescaledb_internal.dimension_info;

50 changes: 50 additions & 0 deletions sql/updates/latest-dev.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

CREATE TYPE _timescaledb_internal.dimension_info;

CREATE OR REPLACE FUNCTION _timescaledb_functions.dimension_info_in(cstring)
RETURNS _timescaledb_internal.dimension_info
LANGUAGE C STRICT IMMUTABLE
AS '@MODULE_PATHNAME@', 'ts_dimension_info_in';

CREATE OR REPLACE FUNCTION _timescaledb_functions.dimension_info_out(_timescaledb_internal.dimension_info)
RETURNS cstring
LANGUAGE C STRICT IMMUTABLE
AS '@MODULE_PATHNAME@', 'ts_dimension_info_out';

CREATE TYPE _timescaledb_internal.dimension_info (
INPUT = _timescaledb_functions.dimension_info_in,
OUTPUT = _timescaledb_functions.dimension_info_out,
INTERNALLENGTH = VARIABLE
);

CREATE FUNCTION @[email protected]_hypertable(
relation REGCLASS,
dimension _timescaledb_internal.dimension_info,
create_default_indexes BOOLEAN = TRUE,
if_not_exists BOOLEAN = FALSE,
migrate_data BOOLEAN = FALSE
) RETURNS TABLE(hypertable_id INT, created BOOL) AS '@MODULE_PATHNAME@', 'ts_hypertable_create_general' LANGUAGE C VOLATILE;

CREATE FUNCTION @[email protected]_dimension(
hypertable REGCLASS,
dimension _timescaledb_internal.dimension_info,
if_not_exists BOOLEAN = FALSE
) RETURNS TABLE(dimension_id INT, created BOOL)
AS '@MODULE_PATHNAME@', 'ts_dimension_add_general' LANGUAGE C VOLATILE;

CREATE FUNCTION @[email protected]_partitioning_interval(
hypertable REGCLASS,
partition_interval ANYELEMENT,
dimension_name NAME = NULL
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_dimension_set_interval' LANGUAGE C VOLATILE;

CREATE FUNCTION @[email protected]_hash(column_name NAME, number_partitions INTEGER,
partition_func regproc = NULL)
RETURNS _timescaledb_internal.dimension_info LANGUAGE C
AS '@MODULE_PATHNAME@', 'ts_hash_dimension';

CREATE FUNCTION @[email protected]_range(column_name NAME,
partition_interval ANYELEMENT = NULL::bigint,
partition_func regproc = NULL)
RETURNS _timescaledb_internal.dimension_info LANGUAGE C
AS '@MODULE_PATHNAME@', 'ts_range_dimension';
8 changes: 8 additions & 0 deletions sql/updates/reverse-dev.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- API changes related to hypertable generalization
DROP FUNCTION IF EXISTS @[email protected]_dimension(regclass,dimension_info,boolean);
DROP FUNCTION IF EXISTS @[email protected]_hypertable(regclass,dimension_info,boolean,boolean,boolean);
DROP FUNCTION IF EXISTS @[email protected]_partitioning_interval(regclass,anyelement,name);
DROP FUNCTION IF EXISTS @[email protected]_hash(name,integer,regproc);
DROP FUNCTION IF EXISTS @[email protected]_range(name,anyelement,regproc);

DROP TYPE IF EXISTS _timescaledb_internal.dimension_info CASCADE;
Loading

0 comments on commit e7340e3

Please sign in to comment.