forked from timescale/timescaledb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil_internal_table_ddl.sql
158 lines (139 loc) · 5.35 KB
/
util_internal_table_ddl.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
-- This file contains functions associated with creating new
-- hypertables.
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_is_finite(
val BIGINT
)
RETURNS BOOLEAN LANGUAGE SQL IMMUTABLE PARALLEL SAFE AS
$BODY$
--end values of bigint reserved for infinite
SELECT val > (-9223372036854775808)::bigint AND val < 9223372036854775807::bigint
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_slice_get_constraint_sql(
dimension_slice_id INTEGER
)
RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
dimension_slice_row _timescaledb_catalog.dimension_slice;
dimension_row _timescaledb_catalog.dimension;
parts TEXT[];
BEGIN
SELECT * INTO STRICT dimension_slice_row
FROM _timescaledb_catalog.dimension_slice
WHERE id = dimension_slice_id;
SELECT * INTO STRICT dimension_row
FROM _timescaledb_catalog.dimension
WHERE id = dimension_slice_row.dimension_id;
IF dimension_row.partitioning_func IS NOT NULL THEN
IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_start) THEN
parts = parts || format(
$$
%1$I.%2$I(%3$I) >= %4$L
$$,
dimension_row.partitioning_func_schema,
dimension_row.partitioning_func,
dimension_row.column_name,
dimension_slice_row.range_start);
END IF;
IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_end) THEN
parts = parts || format(
$$
%1$I.%2$I(%3$I) < %4$L
$$,
dimension_row.partitioning_func_schema,
dimension_row.partitioning_func,
dimension_row.column_name,
dimension_slice_row.range_end);
END IF;
IF array_length(parts, 1) = 0 THEN
RETURN NULL;
END IF;
return array_to_string(parts, 'AND');
ELSE
--TODO: only works with time for now
IF _timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type) =
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type) THEN
RAISE 'Time based constraints have the same start and end values for column "%": %',
dimension_row.column_name,
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type);
END IF;
parts = ARRAY[]::text[];
IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_start) THEN
parts = parts || format(
$$
%1$I >= %2$s
$$,
dimension_row.column_name,
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type));
END IF;
IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_end) THEN
parts = parts || format(
$$
%1$I < %2$s
$$,
dimension_row.column_name,
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type));
END IF;
return array_to_string(parts, 'AND');
END IF;
END
$BODY$;
-- Outputs the create_hypertable command to recreate the given hypertable.
--
-- This is currently used internally for our single hypertable backup tool
-- so that it knows how to restore the hypertable without user intervention.
--
-- It only works for hypertables with up to 2 dimensions.
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_create_command(
table_name NAME
)
RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
h_id INTEGER;
schema_name NAME;
time_column NAME;
time_interval BIGINT;
space_column NAME;
space_partitions INTEGER;
dimension_cnt INTEGER;
dimension_row record;
ret TEXT;
BEGIN
SELECT h.id, h.schema_name
FROM _timescaledb_catalog.hypertable AS h
WHERE h.table_name = get_create_command.table_name
INTO h_id, schema_name;
IF h_id IS NULL THEN
RAISE EXCEPTION 'hypertable % not found', table_name
USING ERRCODE = 'IO101';
END IF;
SELECT COUNT(*)
FROM _timescaledb_catalog.dimension d
WHERE d.hypertable_id = h_id
INTO STRICT dimension_cnt;
IF dimension_cnt > 2 THEN
RAISE EXCEPTION 'get_create_command only supports hypertables with up to 2 dimensions'
USING ERRCODE = 'IO101';
END IF;
FOR dimension_row IN
SELECT *
FROM _timescaledb_catalog.dimension d
WHERE d.hypertable_id = h_id
LOOP
IF dimension_row.interval_length IS NOT NULL THEN
time_column := dimension_row.column_name;
time_interval := dimension_row.interval_length;
ELSIF dimension_row.num_slices IS NOT NULL THEN
space_column := dimension_row.column_name;
space_partitions := dimension_row.num_slices;
END IF;
END LOOP;
ret := format($$SELECT create_hypertable('%I.%I', '%I'$$, schema_name, table_name, time_column);
IF space_column IS NOT NULL THEN
ret := ret || format($$, '%I', %s$$, space_column, space_partitions);
END IF;
ret := ret || format($$, chunk_time_interval => %s, create_default_indexes=>FALSE);$$, time_interval);
RETURN ret;
END
$BODY$;