Skip to content

Commit 71962b8

Browse files
committed
Refactor dimension-related API functions
The functions for adding and updating dimensions have been refactored in C to: - improve usage of proper error codes - make messages that better conform with the PostgreSQL standard. - improve security by avoiding that lots of code run under SECURITY DEFINER A new if_not_exists option has also been added to add_dimension() and a the number of partitions can now be set using the new set_number_partitions() function. A bug in the validation of smallint time intervals has been fixed. The previous code didn't check for intervals > 0 and smallint intervals accepted values up to UINT16_MAX instead of INT16_MAX.
1 parent cc254a9 commit 71962b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1183
-554
lines changed

sql/ddl_api.sql

Lines changed: 32 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ BEGIN
8484

8585
EXECUTE format('SELECT TRUE FROM %s LIMIT 1', main_table) INTO main_table_has_items;
8686

87-
PERFORM _timescaledb_internal.set_time_column_constraint(main_table, time_column_name);
88-
8987
IF main_table_has_items THEN
9088
RAISE EXCEPTION 'the table being converted to a hypertable must be empty'
9189
USING ERRCODE = 'IO102';
@@ -94,11 +92,6 @@ BEGIN
9492
-- Validate that the hypertable supports the triggers in the main table
9593
PERFORM _timescaledb_internal.validate_triggers(main_table);
9694

97-
time_type := _timescaledb_internal.dimension_type(main_table, time_column_name, true);
98-
99-
chunk_time_interval_actual := _timescaledb_internal.time_interval_specification_to_internal_with_default_time(
100-
time_type, chunk_time_interval, 'chunk_time_interval');
101-
10295
BEGIN
10396
SELECT *
10497
INTO hypertable_row
@@ -111,7 +104,7 @@ BEGIN
111104
number_partitions,
112105
associated_schema_name,
113106
associated_table_prefix,
114-
chunk_time_interval_actual,
107+
chunk_time_interval,
115108
tablespace_name,
116109
create_default_indexes,
117110
partitioning_func
@@ -132,58 +125,6 @@ BEGIN
132125
END
133126
$BODY$;
134127

135-
-- Add a dimension (of partitioning) to a hypertable
136-
--
137-
-- main_table - OID of the table to add a dimension to
138-
-- column_name - NAME of the column to use in partitioning for this dimension
139-
-- number_partitions - Number of partitions, for non-time dimensions
140-
-- interval_length - Size of intervals for time dimensions (can be integral or INTERVAL)
141-
-- partitioning_func - Function used to partition the column
142-
CREATE OR REPLACE FUNCTION add_dimension(
143-
main_table REGCLASS,
144-
column_name NAME,
145-
number_partitions INTEGER = NULL,
146-
interval_length anyelement = NULL::BIGINT,
147-
partitioning_func REGPROC = NULL
148-
)
149-
RETURNS VOID LANGUAGE PLPGSQL VOLATILE
150-
SECURITY DEFINER SET search_path = '_timescaledb_catalog'
151-
AS
152-
$BODY$
153-
<<main_block>>
154-
DECLARE
155-
table_name NAME;
156-
schema_name NAME;
157-
hypertable_row _timescaledb_catalog.hypertable;
158-
BEGIN
159-
PERFORM _timescaledb_internal.check_role(main_table);
160-
161-
SELECT relname, nspname
162-
INTO STRICT table_name, schema_name
163-
FROM pg_class c
164-
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
165-
WHERE c.OID = main_table;
166-
167-
SELECT *
168-
INTO STRICT hypertable_row
169-
FROM _timescaledb_catalog.hypertable h
170-
WHERE h.schema_name = main_block.schema_name
171-
AND h.table_name = main_block.table_name
172-
FOR UPDATE;
173-
174-
PERFORM _timescaledb_internal.add_dimension(main_table,
175-
hypertable_row,
176-
column_name,
177-
number_partitions,
178-
interval_length,
179-
partitioning_func);
180-
EXCEPTION
181-
WHEN NO_DATA_FOUND THEN
182-
RAISE EXCEPTION '"%" is not a hypertable; cannot add dimension', main_block.table_name
183-
USING ERRCODE = 'IO102';
184-
END
185-
$BODY$;
186-
187128
-- Update chunk_time_interval for a hypertable.
188129
--
189130
-- main_table - The OID of the table corresponding to a hypertable whose time
@@ -194,50 +135,15 @@ $BODY$;
194135
-- microseconds, or an INTERVAL type.
195136
CREATE OR REPLACE FUNCTION set_chunk_time_interval(
196137
main_table REGCLASS,
197-
chunk_time_interval anyelement
198-
)
199-
RETURNS VOID LANGUAGE PLPGSQL VOLATILE
200-
SECURITY DEFINER SET search_path='_timescaledb_catalog'
201-
AS
202-
$BODY$
203-
DECLARE
204-
main_table_name NAME;
205-
main_schema_name NAME;
206-
chunk_time_interval_actual BIGINT;
207-
time_dimension _timescaledb_catalog.dimension;
208-
time_type REGTYPE;
209-
BEGIN
210-
PERFORM _timescaledb_internal.check_role(main_table);
211-
IF chunk_time_interval IS NULL THEN
212-
RAISE EXCEPTION 'chunk_time_interval cannot be NULL'
213-
USING ERRCODE = 'IO102';
214-
END IF;
215-
216-
SELECT relname, nspname
217-
INTO STRICT main_table_name, main_schema_name
218-
FROM pg_class c
219-
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
220-
WHERE c.OID = main_table;
138+
chunk_time_interval ANYELEMENT,
139+
dimension_name NAME = NULL
140+
) RETURNS VOID AS '@MODULE_PATHNAME@', 'dimension_set_interval' LANGUAGE C VOLATILE;
221141

222-
SELECT *
223-
INTO STRICT time_dimension
224-
FROM _timescaledb_internal.dimension_get_time(
225-
(
226-
SELECT id
227-
FROM _timescaledb_catalog.hypertable h
228-
WHERE h.schema_name = main_schema_name AND
229-
h.table_name = main_table_name
230-
));
231-
232-
time_type := _timescaledb_internal.dimension_type(main_table, time_dimension.column_name, true);
233-
chunk_time_interval_actual := _timescaledb_internal.time_interval_specification_to_internal_with_default_time(
234-
time_type, chunk_time_interval, 'chunk_time_interval');
235-
236-
UPDATE _timescaledb_catalog.dimension d
237-
SET interval_length = chunk_time_interval_actual
238-
WHERE time_dimension.id = d.id;
239-
END
240-
$BODY$;
142+
CREATE OR REPLACE FUNCTION set_number_partitions(
143+
main_table REGCLASS,
144+
number_partitions INTEGER,
145+
dimension_name NAME = NULL
146+
) RETURNS VOID AS '@MODULE_PATHNAME@', 'dimension_set_num_slices' LANGUAGE C VOLATILE;
241147

242148
-- Drop chunks that are older than a timestamp.
243149
CREATE OR REPLACE FUNCTION drop_chunks(
@@ -303,6 +209,29 @@ BEGIN
303209
END
304210
$BODY$;
305211

212+
-- Add a dimension (of partitioning) to a hypertable
213+
--
214+
-- main_table - OID of the table to add a dimension to
215+
-- column_name - NAME of the column to use in partitioning for this dimension
216+
-- number_partitions - Number of partitions, for non-time dimensions
217+
-- interval_length - Size of intervals for time dimensions (can be integral or INTERVAL)
218+
-- partitioning_func - Function used to partition the column
219+
-- if_not_exists - If set, and the dimension already exists, generate a notice instead of an error
220+
CREATE OR REPLACE FUNCTION add_dimension(
221+
main_table REGCLASS,
222+
column_name NAME,
223+
number_partitions INTEGER = NULL,
224+
chunk_time_interval ANYELEMENT = NULL::BIGINT,
225+
partitioning_func REGPROC = NULL,
226+
if_not_exists BOOLEAN = FALSE
227+
)
228+
RETURNS VOID LANGUAGE SQL AS
229+
$BODY$
230+
SELECT * FROM _timescaledb_internal.add_dimension(main_table, column_name, number_partitions,
231+
chunk_time_interval, partitioning_func, if_not_exists);
232+
$BODY$;
233+
234+
306235
CREATE OR REPLACE FUNCTION attach_tablespace(tablespace NAME, hypertable REGCLASS)
307236
RETURNS VOID LANGUAGE SQL AS
308237
$BODY$

0 commit comments

Comments
 (0)