Skip to content

Commit 0e92652

Browse files
committed
Add compatibility API for OSM
Add some helper function to decouple OSM from direct catalog access: _timescaledb_functions.get_hypertable_info _timescaledb_functions.get_primary_dimension _timescaledb_functions.get_chunk_info _timescaledb_functions.get_chunk_info_by_id _timescaledb_functions.get_chunk_primary_range _timescaledb_functions.get_chunk_primary_range_by_id
1 parent a9708f5 commit 0e92652

6 files changed

Lines changed: 357 additions & 3 deletions

File tree

sql/osm_api.sql

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,94 @@ CREATE OR REPLACE FUNCTION _timescaledb_functions.lock_osm_chunk_dimension_slice
2121
htoid REGCLASS
2222
) RETURNS VOID AS '@MODULE_PATHNAME@',
2323
'ts_lock_osm_chunk_dimension_slice' LANGUAGE C VOLATILE;
24+
25+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_hypertable_info(IN relation REGCLASS, OUT hypertable_id INTEGER, OUT schema_name name, OUT table_name name, OUT is_cagg BOOLEAN) AS $$
26+
SELECT ht.id, ht.schema_name, ht.table_name, false AS is_cagg
27+
FROM _timescaledb_catalog.hypertable ht
28+
JOIN pg_class c ON ht.table_name = c.relname AND c.oid = $1
29+
JOIN pg_namespace ns ON ns.oid = c.relnamespace AND ns.nspname = ht.schema_name;
30+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
31+
32+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_hypertable_info_by_id(IN hypertable_id INTEGER, OUT hypertable_id INTEGER, OUT schema_name name, OUT table_name name, OUT is_cagg BOOLEAN) AS $$
33+
SELECT ht.id, ht.schema_name, ht.table_name, false AS is_cagg
34+
FROM _timescaledb_catalog.hypertable ht
35+
WHERE ht.id = $1;
36+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
37+
38+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_integer_now_func(IN htid INTEGER, OUT hypertable_id INTEGER, OUT integer_func REGPROC)
39+
AS $$
40+
DECLARE
41+
func_name TEXT;
42+
func_schema TEXT;
43+
raw_ht_id INTEGER;
44+
BEGIN
45+
SELECT integer_now_func_schema, integer_now_func INTO func_schema, func_name
46+
FROM _timescaledb_catalog.dimension d
47+
WHERE d.hypertable_id = $1 ORDER BY id LIMIT 1;
48+
IF func_schema IS NOT NULL AND func_name IS NOT NULL THEN
49+
hypertable_id := $1;
50+
integer_func := to_regproc(format('%I.%I', func_schema, func_name));
51+
RETURN;
52+
END IF;
53+
54+
SELECT raw_hypertable_id INTO raw_ht_id FROM _timescaledb_catalog.continuous_agg WHERE mat_hypertable_id = htid;
55+
IF raw_ht_id IS NOT NULL THEN
56+
SELECT * INTO hypertable_id, integer_func FROM _timescaledb_functions.get_integer_now_func(raw_ht_id);
57+
RETURN;
58+
END IF;
59+
60+
RETURN;
61+
END
62+
$$ LANGUAGE plpgsql STABLE SET search_path = pg_catalog, pg_temp;
63+
64+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_primary_dimension(IN hypertable_id INTEGER, OUT column_name NAME, OUT column_type REGTYPE, OUT integer_now_func regproc) AS $$
65+
SELECT
66+
d.column_name,
67+
d.column_type,
68+
(_timescaledb_functions.get_integer_now_func(d.hypertable_id)).integer_func AS integer_now_func
69+
FROM _timescaledb_catalog.dimension d
70+
WHERE d.hypertable_id = $1 ORDER BY d.id LIMIT 1;
71+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
72+
73+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_chunk_info(IN chunk REGCLASS, OUT chunk_id INTEGER, OUT hypertable_id INTEGER, OUT ht_schema_name NAME, OUT ht_table_name NAME, OUT chunk_schema NAME, OUT chunk_name NAME, OUT is_osm_chunk BOOLEAN, OUT is_frozen BOOLEAN) AS $$
74+
SELECT
75+
ch.id AS chunk_id,
76+
ch.hypertable_id, ht.schema_name AS ht_schema_name, ht.table_name AS ht_table_name,
77+
ch.schema_name AS chunk_schema, ch.table_name AS chunk_name,
78+
ch.osm_chunk AS is_osm_chunk,
79+
(ch.status & 4)::bool AS is_frozen
80+
FROM _timescaledb_catalog.chunk ch
81+
JOIN pg_class c ON c.oid=$1 AND ch.table_name=c.relname
82+
JOIN pg_namespace ns ON ns.oid = c.relnamespace AND ns.nspname = ch.schema_name
83+
JOIN _timescaledb_catalog.hypertable ht ON ht.id=ch.hypertable_id;
84+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
85+
86+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_chunk_info_by_id(IN chunk_id INTEGER, OUT chunk_id INTEGER, OUT hypertable_id INTEGER, OUT ht_schema_name NAME, OUT ht_table_name NAME, OUT chunk_schema NAME, OUT chunk_name NAME, OUT is_osm_chunk BOOLEAN, OUT is_frozen BOOLEAN) AS $$
87+
SELECT
88+
ch.id AS chunk_id,
89+
ch.hypertable_id, ht.schema_name AS ht_schema_name, ht.table_name AS ht_table_name,
90+
ch.schema_name AS chunk_schema, ch.table_name AS chunk_name,
91+
ch.osm_chunk AS is_osm_chunk,
92+
(ch.status & 4)::bool AS is_frozen
93+
FROM _timescaledb_catalog.chunk ch
94+
JOIN _timescaledb_catalog.hypertable ht ON ht.id=ch.hypertable_id
95+
WHERE ch.id = $1;
96+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
97+
98+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_chunk_primary_range(IN chunk REGCLASS, OUT range_start BIGINT, OUT range_end BIGINT)
99+
AS $$
100+
SELECT range_start, range_end
101+
FROM _timescaledb_catalog.dimension_slice d
102+
JOIN _timescaledb_catalog.chunk ch ON ch.id = d.chunk_id
103+
JOIN pg_class c ON c.oid=$1 AND ch.table_name=c.relname
104+
JOIN pg_namespace ns ON ns.oid = c.relnamespace AND ns.nspname = ch.schema_name
105+
ORDER BY dimension_id LIMIT 1;
106+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
107+
108+
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_chunk_primary_range_by_id(IN chunk_id INTEGER, OUT range_start BIGINT, OUT range_end BIGINT)
109+
AS $$
110+
SELECT range_start, range_end
111+
FROM _timescaledb_catalog.dimension_slice d
112+
WHERE chunk_id = $1 ORDER BY dimension_id LIMIT 1;
113+
$$ LANGUAGE SQL STABLE SET search_path = pg_catalog, pg_temp;
114+

sql/updates/reverse-dev.sql

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ $$;
2020
DROP VIEW IF EXISTS _timescaledb_catalog.chunk_constraint;
2121
DROP FUNCTION IF EXISTS _timescaledb_functions.chunk_constraint_add_table_constraint( integer, name, name);
2222

23-
DROP FUNCTION IF EXISTS _timescaledb_functions.lock_osm_chunk_dimension_slice(regclass);
24-
2523
ALTER TABLE _timescaledb_catalog.hypertable RESET (user_catalog_table);
2624
ALTER TABLE _timescaledb_catalog.chunk RESET (user_catalog_table);
2725

@@ -193,7 +191,7 @@ DROP FUNCTION IF EXISTS _timescaledb_functions.chunk_statistics_reset();
193191

194192
DROP FUNCTION IF EXISTS @extschema@.create_hypertable(relation REGCLASS, time_column_name NAME, partitioning_column NAME, number_partitions INTEGER, associated_schema_name NAME, associated_table_prefix NAME, chunk_time_interval ANYELEMENT, create_default_indexes BOOLEAN, if_not_exists BOOLEAN, partitioning_func REGPROC, migrate_data BOOLEAN, time_partitioning_func REGPROC);
195193

196-
-- Restore the chunk_target_size check constraint dropped in the forward path.
194+
-- Restore the chunk_target_size check constraint
197195
ALTER TABLE _timescaledb_catalog.hypertable
198196
ADD CONSTRAINT hypertable_chunk_target_size_check CHECK (chunk_target_size >= 0);
199197

@@ -293,4 +291,15 @@ CREATE TABLE _timescaledb_catalog.telemetry_event (
293291
);
294292
GRANT SELECT ON _timescaledb_catalog.telemetry_event TO PUBLIC;
295293

294+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_hypertable_info;
295+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_hypertable_info_by_id;
296+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_primary_dimension;
297+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_chunk_info;
298+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_chunk_info_by_id;
299+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_chunk_primary_range;
300+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_chunk_primary_range_by_id;
301+
DROP FUNCTION IF EXISTS _timescaledb_functions.get_integer_now_func;
302+
DROP FUNCTION IF EXISTS _timescaledb_functions.lock_osm_chunk_dimension_slice(regclass);
303+
296304
DROP FUNCTION IF EXISTS _timescaledb_functions.decompress_batch(record);
305+

tsl/test/shared/expected/extension.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,23 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
7070
_timescaledb_functions.freeze_chunk(regclass)
7171
_timescaledb_functions.generate_uuid()
7272
_timescaledb_functions.get_approx_row_count(regclass)
73+
_timescaledb_functions.get_chunk_info(regclass)
74+
_timescaledb_functions.get_chunk_info_by_id(integer)
75+
_timescaledb_functions.get_chunk_primary_range(regclass)
76+
_timescaledb_functions.get_chunk_primary_range_by_id(integer)
7377
_timescaledb_functions.get_compressed_chunk_index_for_recompression(regclass)
7478
_timescaledb_functions.get_create_command(name)
7579
_timescaledb_functions.get_git_commit()
80+
_timescaledb_functions.get_hypertable_info(regclass)
81+
_timescaledb_functions.get_hypertable_info_by_id(integer)
82+
_timescaledb_functions.get_integer_now_func(integer)
7683
_timescaledb_functions.get_internal_time_max(regtype)
7784
_timescaledb_functions.get_internal_time_min(regtype)
7885
_timescaledb_functions.get_orderby_defaults(regclass,text[])
7986
_timescaledb_functions.get_os_info()
8087
_timescaledb_functions.get_partition_for_key(anyelement)
8188
_timescaledb_functions.get_partition_hash(anyelement)
89+
_timescaledb_functions.get_primary_dimension(integer)
8290
_timescaledb_functions.get_segmentby_defaults(regclass)
8391
_timescaledb_functions.hist_combinefunc(internal,internal)
8492
_timescaledb_functions.hist_deserializefunc(bytea,internal)
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
-- This file and its contents are licensed under the Timescale License.
2+
-- Please see the included NOTICE for copyright information and
3+
-- LICENSE-TIMESCALE for a copy of the license.
4+
\pset null '<NULL>'
5+
SELECT * FROM _timescaledb_functions.get_hypertable_info('public.metrics'::regclass);
6+
hypertable_id | schema_name | table_name | is_cagg
7+
---------------+-------------+------------+---------
8+
1 | public | metrics | f
9+
10+
SELECT * FROM _timescaledb_functions.get_hypertable_info('public.hourly_device_metrics'::regclass);
11+
hypertable_id | schema_name | table_name | is_cagg
12+
---------------+-------------+------------+---------
13+
<NULL> | <NULL> | <NULL> | <NULL>
14+
15+
SELECT * FROM _timescaledb_functions.get_hypertable_info(NULL);
16+
hypertable_id | schema_name | table_name | is_cagg
17+
---------------+-------------+------------+---------
18+
<NULL> | <NULL> | <NULL> | <NULL>
19+
20+
SELECT * FROM _timescaledb_functions.get_hypertable_info(0);
21+
hypertable_id | schema_name | table_name | is_cagg
22+
---------------+-------------+------------+---------
23+
<NULL> | <NULL> | <NULL> | <NULL>
24+
25+
SELECT * FROM _timescaledb_functions.get_hypertable_info('pg_catalog.pg_class'::regclass);
26+
hypertable_id | schema_name | table_name | is_cagg
27+
---------------+-------------+------------+---------
28+
<NULL> | <NULL> | <NULL> | <NULL>
29+
30+
SELECT * FROM _timescaledb_functions.get_hypertable_info_by_id(1);
31+
hypertable_id | schema_name | table_name | is_cagg
32+
---------------+-------------+------------+---------
33+
1 | public | metrics | f
34+
35+
SELECT * FROM _timescaledb_functions.get_hypertable_info_by_id(8);
36+
hypertable_id | schema_name | table_name | is_cagg
37+
---------------+-----------------------+----------------------------+---------
38+
8 | _timescaledb_internal | _materialized_hypertable_X | f
39+
40+
SELECT * FROM _timescaledb_functions.get_hypertable_info_by_id(0);
41+
hypertable_id | schema_name | table_name | is_cagg
42+
---------------+-------------+------------+---------
43+
<NULL> | <NULL> | <NULL> | <NULL>
44+
45+
SELECT * FROM _timescaledb_functions.get_hypertable_info_by_id(NULL);
46+
hypertable_id | schema_name | table_name | is_cagg
47+
---------------+-------------+------------+---------
48+
<NULL> | <NULL> | <NULL> | <NULL>
49+
50+
SELECT * FROM _timescaledb_functions.get_primary_dimension(1);
51+
column_name | column_type | integer_now_func
52+
-------------+--------------------------+------------------
53+
time | timestamp with time zone | <NULL>
54+
55+
SELECT * FROM _timescaledb_functions.get_primary_dimension(8);
56+
column_name | column_type | integer_now_func
57+
-------------+--------------------------+------------------
58+
hour | timestamp with time zone | <NULL>
59+
60+
SELECT * FROM _timescaledb_functions.get_primary_dimension(0);
61+
column_name | column_type | integer_now_func
62+
-------------+-------------+------------------
63+
<NULL> | <NULL> | <NULL>
64+
65+
SELECT * FROM _timescaledb_functions.get_primary_dimension(NULL);
66+
column_name | column_type | integer_now_func
67+
-------------+-------------+------------------
68+
<NULL> | <NULL> | <NULL>
69+
70+
SELECT * FROM _timescaledb_functions.get_chunk_info('_timescaledb_internal._hyper_X_X_chunk');
71+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
72+
----------+---------------+----------------+---------------+-----------------------+------------------+--------------+-----------
73+
3 | 1 | public | metrics | _timescaledb_internal | _hyper_X_X_chunk | f | f
74+
75+
SELECT * FROM _timescaledb_functions.get_chunk_info('_timescaledb_internal._hyper_X_X_chunk'::regclass);
76+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
77+
----------+---------------+----------------+---------------+-----------------------+------------------+--------------+-----------
78+
3 | 1 | public | metrics | _timescaledb_internal | _hyper_X_X_chunk | f | f
79+
80+
SELECT * FROM _timescaledb_functions.get_chunk_info(0);
81+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
82+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
83+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
84+
85+
SELECT * FROM _timescaledb_functions.get_chunk_info(NULL);
86+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
87+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
88+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
89+
90+
SELECT * FROM _timescaledb_functions.get_chunk_info('pg_catalog.pg_class'::regclass);
91+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
92+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
93+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
94+
95+
SELECT * FROM _timescaledb_functions.get_chunk_info_by_id(3);
96+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
97+
----------+---------------+----------------+---------------+-----------------------+------------------+--------------+-----------
98+
3 | 1 | public | metrics | _timescaledb_internal | _hyper_X_X_chunk | f | f
99+
100+
SELECT * FROM _timescaledb_functions.get_chunk_info_by_id(38);
101+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
102+
----------+---------------+-----------------------+----------------------------+-----------------------+-------------------+--------------+-----------
103+
38 | 8 | _timescaledb_internal | _materialized_hypertable_X | _timescaledb_internal | _hyper_X_X_chunk | f | f
104+
105+
SELECT * FROM _timescaledb_functions.get_chunk_info_by_id(0);
106+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
107+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
108+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
109+
110+
SELECT * FROM _timescaledb_functions.get_chunk_info_by_id(-1);
111+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
112+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
113+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
114+
115+
SELECT * FROM _timescaledb_functions.get_chunk_info_by_id(NULL);
116+
chunk_id | hypertable_id | ht_schema_name | ht_table_name | chunk_schema | chunk_name | is_osm_chunk | is_frozen
117+
----------+---------------+----------------+---------------+--------------+------------+--------------+-----------
118+
<NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL> | <NULL>
119+
120+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range('_timescaledb_internal._hyper_X_X_chunk'::regclass);
121+
range_start | range_end
122+
-----------------+-----------------
123+
947721600000000 | 948326400000000
124+
125+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range(0::regclass);
126+
range_start | range_end
127+
-------------+-----------
128+
<NULL> | <NULL>
129+
130+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range(1::regclass);
131+
range_start | range_end
132+
-------------+-----------
133+
<NULL> | <NULL>
134+
135+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range('pg_catalog.pg_class'::regclass);
136+
range_start | range_end
137+
-------------+-----------
138+
<NULL> | <NULL>
139+
140+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range(NULL::regclass);
141+
range_start | range_end
142+
-------------+-----------
143+
<NULL> | <NULL>
144+
145+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range_by_id(3);
146+
range_start | range_end
147+
-----------------+-----------------
148+
947721600000000 | 948326400000000
149+
150+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range_by_id(38);
151+
range_start | range_end
152+
-----------------+-----------------
153+
943488000000000 | 949536000000000
154+
155+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range_by_id(0::int);
156+
range_start | range_end
157+
-------------+-----------
158+
<NULL> | <NULL>
159+
160+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range_by_id(-1::int);
161+
range_start | range_end
162+
-------------+-----------
163+
<NULL> | <NULL>
164+
165+
SELECT * FROM _timescaledb_functions.get_chunk_primary_range_by_id(NULL::int);
166+
range_start | range_end
167+
-------------+-----------
168+
<NULL> | <NULL>
169+
170+
SELECT * FROM _timescaledb_functions.get_integer_now_func(1);
171+
hypertable_id | integer_func
172+
---------------+--------------
173+
<NULL> | <NULL>
174+
175+
SELECT * FROM _timescaledb_functions.get_integer_now_func(8);
176+
hypertable_id | integer_func
177+
---------------+--------------
178+
<NULL> | <NULL>
179+
180+
SELECT * FROM _timescaledb_functions.get_integer_now_func(0);
181+
hypertable_id | integer_func
182+
---------------+--------------
183+
<NULL> | <NULL>
184+
185+
SELECT * FROM _timescaledb_functions.get_integer_now_func(-1);
186+
hypertable_id | integer_func
187+
---------------+--------------
188+
<NULL> | <NULL>
189+
190+
SELECT * FROM _timescaledb_functions.get_integer_now_func(NULL);
191+
hypertable_id | integer_func
192+
---------------+--------------
193+
<NULL> | <NULL>
194+

tsl/test/shared/sql/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ set(TEST_FILES_SHARED
1313
gapfill_bug.sql
1414
generated_columns.sql
1515
memoize.sql
16+
osm_api.sql
1617
parameterized_chunkappend.sql
1718
security_barrier.sql
1819
subtract_integer_from_now.sql)

0 commit comments

Comments
 (0)