mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 18:43:18 +08:00
Run same table gapfill test on multinode
This commit moves all gapfill tests, which was against a table, into a separate include test file, which is then used to run the test against a distributed hypertable. It is also run in the original test and the test results were moved inside the expected output. Also all the tests with errors in the original test file were moved to single location in the file. This commit also tests gapfill queries on a hypertable distributed only to one data node. dist_gapfill.sql was reorganized according the database setup, not tests. As the result of this commit all planned tests of gapfill on a distributed hypertable are added.
This commit is contained in:
parent
494fe90801
commit
2e352664ba
@ -175,6 +175,28 @@ GROUP BY 1;
|
||||
2 | public | conditions | t
|
||||
(1 row)
|
||||
|
||||
create_distributed_hypertable
|
||||
-------------------------------
|
||||
(3,public,metrics_int,t)
|
||||
(1 row)
|
||||
|
||||
:DIFF_CMD_PARTITIONWISE_OFF
|
||||
:DIFF_CMD_PARTITIONWISE_ON
|
||||
:DIFF_CMD_METRICS_PARTITIONWISE_OFF
|
||||
-- Distributed hypertables with one data nodes
|
||||
\set ECHO errors
|
||||
WARNING: only one data node was assigned to the hypertable
|
||||
hypertable_id | schema_name | table_name | created
|
||||
---------------+-------------+------------+---------
|
||||
4 | public | conditions | t
|
||||
(1 row)
|
||||
|
||||
WARNING: only one data node was assigned to the hypertable
|
||||
create_distributed_hypertable
|
||||
-------------------------------
|
||||
(5,public,metrics_int,t)
|
||||
(1 row)
|
||||
|
||||
delete_data_node
|
||||
------------------
|
||||
t
|
||||
@ -192,3 +214,4 @@ GROUP BY 1;
|
||||
|
||||
:DIFF_CMD_PARTITIONWISE_OFF
|
||||
:DIFF_CMD_PARTITIONWISE_ON
|
||||
:DIFF_CMD_METRICS_PARTITIONWISE_OFF
|
||||
|
File diff suppressed because one or more lines are too long
@ -3,20 +3,36 @@
|
||||
-- LICENSE-TIMESCALE for a copy of the license.
|
||||
|
||||
\set ECHO errors
|
||||
\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER;
|
||||
SET ROLE :ROLE_1;
|
||||
|
||||
\set TEST_BASE_NAME dist_gapfill
|
||||
\set TEST_METRICS_NAME gapfill_metrics
|
||||
\set DATA_NODE_1 :TEST_BASE_NAME _1
|
||||
\set DATA_NODE_2 :TEST_BASE_NAME _2
|
||||
\set DATA_NODE_3 :TEST_BASE_NAME _3
|
||||
SELECT format('include/%s_query.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME",
|
||||
format('%s/results/%s_singlenode.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_SINGLENODE",
|
||||
format('%s/results/%s_partitionwise_off.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_PARTITIONWISE_OFF",
|
||||
format('%s/results/%s_partitionwise_on.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_PARTITIONWISE_ON" \gset
|
||||
format('%s/results/%s_partitionwise_on.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_PARTITIONWISE_ON",
|
||||
format('include/%s_query.sql', :'TEST_METRICS_NAME') AS "TEST_METRICS_QUERY_NAME",
|
||||
format('%s/results/%s_nohyper.out', :'TEST_OUTPUT_DIR', :'TEST_METRICS_NAME') AS "TEST_METRICS_NOHYPER",
|
||||
format('%s/results/%s_partitionwise_off.out', :'TEST_OUTPUT_DIR', :'TEST_METRICS_NAME') AS "TEST_METRICS_PARTITIONWISE_OFF" \gset
|
||||
|
||||
SELECT format('\! diff %s %s', :'TEST_SINGLENODE', :'TEST_PARTITIONWISE_OFF') AS "DIFF_CMD_PARTITIONWISE_OFF",
|
||||
format('\! diff %s %s', :'TEST_SINGLENODE', :'TEST_PARTITIONWISE_ON') AS "DIFF_CMD_PARTITIONWISE_ON" \gset
|
||||
format('\! diff %s %s', :'TEST_SINGLENODE', :'TEST_PARTITIONWISE_ON') AS "DIFF_CMD_PARTITIONWISE_ON",
|
||||
format('\! diff %s %s', :'TEST_METRICS_NOHYPER', :'TEST_METRICS_PARTITIONWISE_OFF') AS "DIFF_CMD_METRICS_PARTITIONWISE_OFF" \gset
|
||||
|
||||
-- Non-distributed hypertable
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP TABLE IF EXISTS metrics_int;
|
||||
DROP TABLE IF EXISTS conditions;
|
||||
DROP TABLE IF EXISTS devices;
|
||||
DROP TABLE IF EXISTS sensors;
|
||||
SET client_min_messages TO NOTICE;
|
||||
|
||||
-- Non-distributed hypertables
|
||||
|
||||
-- dist_gapfill_query
|
||||
CREATE TABLE conditions(
|
||||
time timestamptz NOT NULL,
|
||||
device int,
|
||||
@ -41,8 +57,38 @@ INSERT INTO conditions VALUES
|
||||
|
||||
DROP TABLE conditions CASCADE;
|
||||
|
||||
-- Distributed hypertable
|
||||
\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER;
|
||||
-- Run gapfill on a table as in gapfill.sql, where the result is verified
|
||||
|
||||
CREATE TABLE metrics_int(
|
||||
time int NOT NULL,
|
||||
device_id int,
|
||||
sensor_id int,
|
||||
value float);
|
||||
|
||||
INSERT INTO metrics_int VALUES
|
||||
(-100,1,1,0.0),
|
||||
(-100,1,2,-100.0),
|
||||
(0,1,1,5.0),
|
||||
(5,1,2,10.0),
|
||||
(100,1,1,0.0),
|
||||
(100,1,2,-100.0);
|
||||
|
||||
CREATE TABLE devices(device_id INT, name TEXT);
|
||||
INSERT INTO devices VALUES (1,'Device 1'),(2,'Device 2'),(3,'Device 3');
|
||||
|
||||
CREATE TABLE sensors(sensor_id INT, name TEXT);
|
||||
INSERT INTO sensors VALUES (1,'Sensor 1'),(2,'Sensor 2'),(3,'Sensor 3');
|
||||
|
||||
\o :TEST_METRICS_NOHYPER
|
||||
\ir :TEST_METRICS_QUERY_NAME
|
||||
\o
|
||||
|
||||
DROP TABLE metrics_int CASCADE;
|
||||
|
||||
-- Distributed hypertables with three data nodes
|
||||
|
||||
-- dist_gapfill_query
|
||||
SET ROLE :ROLE_CLUSTER_SUPERUSER;
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP DATABASE IF EXISTS :DATA_NODE_1;
|
||||
DROP DATABASE IF EXISTS :DATA_NODE_2;
|
||||
@ -85,15 +131,108 @@ SET enable_partitionwise_aggregate = 'on';
|
||||
|
||||
SET enable_partitionwise_aggregate = 'off';
|
||||
|
||||
-- gapfill_metrics_query
|
||||
|
||||
CREATE TABLE metrics_int(
|
||||
time int NOT NULL,
|
||||
device_id int,
|
||||
sensor_id int,
|
||||
value float);
|
||||
|
||||
SELECT create_distributed_hypertable('metrics_int','time','device_id',chunk_time_interval => 50);
|
||||
|
||||
INSERT INTO metrics_int VALUES
|
||||
(-100,1,1,0.0),
|
||||
(-100,1,2,-100.0),
|
||||
(0,1,1,5.0),
|
||||
(5,1,2,10.0),
|
||||
(100,1,1,0.0),
|
||||
(100,1,2,-100.0);
|
||||
|
||||
\o :TEST_METRICS_PARTITIONWISE_OFF
|
||||
\ir :TEST_METRICS_QUERY_NAME
|
||||
\o
|
||||
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP TABLE conditions CASCADE;
|
||||
\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER;
|
||||
DROP TABLE metrics_int CASCADE;
|
||||
SET client_min_messages TO NOTICE;
|
||||
|
||||
\set ECHO all
|
||||
|
||||
:DIFF_CMD_PARTITIONWISE_OFF
|
||||
:DIFF_CMD_PARTITIONWISE_ON
|
||||
:DIFF_CMD_METRICS_PARTITIONWISE_OFF
|
||||
|
||||
-- Distributed hypertables with one data nodes
|
||||
|
||||
\set ECHO errors
|
||||
|
||||
-- dist_gapfill_query
|
||||
CREATE TABLE conditions(
|
||||
time timestamptz NOT NULL,
|
||||
device int,
|
||||
value float
|
||||
);
|
||||
SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 1,
|
||||
data_nodes => ARRAY[:'DATA_NODE_1']);
|
||||
INSERT INTO conditions VALUES
|
||||
('2017-01-01 06:01', 1, 1.2),
|
||||
('2017-01-01 09:11', 3, 4.3),
|
||||
('2017-01-01 08:01', 1, 7.3),
|
||||
('2017-01-02 08:01', 2, 0.23),
|
||||
('2018-07-02 08:01', 87, 0.0),
|
||||
('2018-07-01 06:01', 13, 3.1),
|
||||
('2018-07-01 09:11', 90, 10303.12),
|
||||
('2018-07-01 08:01', 29, 64);
|
||||
|
||||
SET enable_partitionwise_aggregate = 'off';
|
||||
\o :TEST_PARTITIONWISE_OFF
|
||||
\ir :TEST_QUERY_NAME
|
||||
\o
|
||||
|
||||
SET enable_partitionwise_aggregate = 'on';
|
||||
\o :TEST_PARTITIONWISE_ON
|
||||
\ir :TEST_QUERY_NAME
|
||||
\o
|
||||
|
||||
SET enable_partitionwise_aggregate = 'off';
|
||||
|
||||
-- gapfill_metrics_query
|
||||
|
||||
CREATE TABLE metrics_int(
|
||||
time int NOT NULL,
|
||||
device_id int,
|
||||
sensor_id int,
|
||||
value float);
|
||||
|
||||
SELECT create_distributed_hypertable('metrics_int', 'time', 'device_id', chunk_time_interval => 50,
|
||||
data_nodes => ARRAY[:'DATA_NODE_1']);
|
||||
|
||||
INSERT INTO metrics_int VALUES
|
||||
(-100,1,1,0.0),
|
||||
(-100,1,2,-100.0),
|
||||
(0,1,1,5.0),
|
||||
(5,1,2,10.0),
|
||||
(100,1,1,0.0),
|
||||
(100,1,2,-100.0);
|
||||
|
||||
\o :TEST_METRICS_PARTITIONWISE_OFF
|
||||
\ir :TEST_METRICS_QUERY_NAME
|
||||
\o
|
||||
|
||||
SET client_min_messages TO ERROR;
|
||||
DROP TABLE conditions CASCADE;
|
||||
DROP TABLE metrics_int CASCADE;
|
||||
DROP TABLE devices;
|
||||
DROP TABLE sensors;
|
||||
SET ROLE :ROLE_CLUSTER_SUPERUSER;
|
||||
SELECT delete_data_node(:'DATA_NODE_1');
|
||||
SELECT delete_data_node(:'DATA_NODE_2');
|
||||
SELECT delete_data_node(:'DATA_NODE_3');
|
||||
DROP DATABASE IF EXISTS :DATA_NODE_1;
|
||||
DROP DATABASE IF EXISTS :DATA_NODE_2;
|
||||
DROP DATABASE IF EXISTS :DATA_NODE_3;
|
||||
DROP DATABASE :DATA_NODE_1;
|
||||
DROP DATABASE :DATA_NODE_2;
|
||||
DROP DATABASE :DATA_NODE_3;
|
||||
SET ROLE :ROLE_1;
|
||||
SET client_min_messages TO NOTICE;
|
||||
|
||||
@ -101,3 +240,4 @@ SET client_min_messages TO NOTICE;
|
||||
|
||||
:DIFF_CMD_PARTITIONWISE_OFF
|
||||
:DIFF_CMD_PARTITIONWISE_ON
|
||||
:DIFF_CMD_METRICS_PARTITIONWISE_OFF
|
||||
|
@ -155,6 +155,59 @@ INSERT INTO devices VALUES (1,'Device 1'),(2,'Device 2'),(3,'Device 3');
|
||||
CREATE TABLE sensors(sensor_id INT, name TEXT);
|
||||
INSERT INTO sensors VALUES (1,'Sensor 1'),(2,'Sensor 2'),(3,'Sensor 3');
|
||||
|
||||
-- All test against table metrics_int first
|
||||
|
||||
\set ON_ERROR_STOP 0
|
||||
-- inverse of previous test query to confirm an error is actually thrown
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time = 5
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test window functions with multiple column references
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time,1,2),
|
||||
first(min(time),min(time)) OVER ()
|
||||
FROM metrics_int
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with unsupported operator
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int
|
||||
WHERE time =0 AND time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with 2 tables and where clause doesnt match gapfill argument
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m, metrics_int m2
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test inner join and where clause doesnt match gapfill argument
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m1 INNER JOIN metrics_int m2 ON m1.time=m2.time
|
||||
WHERE m1.time >=0 AND m1.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test outer join with constraints in join condition
|
||||
-- not usable as start/stop
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m1.time)
|
||||
FROM metrics_int m1 LEFT OUTER JOIN metrics_int m2 ON m1.time=m2.time AND m1.time >=0 AND m1.time < 2
|
||||
GROUP BY 1;
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
\ir include/gapfill_metrics_query.sql
|
||||
|
||||
-- Tests without tables
|
||||
|
||||
-- test locf and interpolate call without gapfill
|
||||
SELECT locf(1);
|
||||
SELECT interpolate(1);
|
||||
@ -303,13 +356,6 @@ SELECT
|
||||
FROM (VALUES (1),(2)) v(time)
|
||||
GROUP BY 1;
|
||||
|
||||
-- test window functions with multiple column references
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time,1,2),
|
||||
first(min(time),min(time)) OVER ()
|
||||
FROM metrics_int
|
||||
GROUP BY 1;
|
||||
|
||||
-- test locf not toplevel
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time,1,11),
|
||||
@ -571,20 +617,6 @@ FROM (VALUES (1,'blue',1),(2,'red',2)) v(time,color,value)
|
||||
WHERE false
|
||||
GROUP BY 1,color ORDER BY 2,1;
|
||||
|
||||
-- test JOINs
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time,0,5) as time,
|
||||
device_id,
|
||||
d.name,
|
||||
sensor_id,
|
||||
s.name,
|
||||
avg(m.value)
|
||||
FROM metrics_int m
|
||||
INNER JOIN devices d USING(device_id)
|
||||
INNER JOIN sensors s USING(sensor_id)
|
||||
WHERE time BETWEEN 0 AND 5
|
||||
GROUP BY 1,2,3,4,5;
|
||||
|
||||
-- test insert into SELECT
|
||||
CREATE TABLE insert_test(id INT);
|
||||
INSERT INTO insert_test SELECT time_bucket_gapfill(1,time,1,5) FROM (VALUES (1),(2)) v(time) GROUP BY 1 ORDER BY 1;
|
||||
@ -725,71 +757,6 @@ FROM (VALUES
|
||||
) v(time,v1,v2,v3)
|
||||
GROUP BY 1;
|
||||
|
||||
-- test locf lookup query does not trigger when not needed
|
||||
--
|
||||
-- 1/(SELECT 0) will throw an error in the lookup query but in order to not
|
||||
-- always trigger evaluation it needs to be correlated otherwise postgres will
|
||||
-- always run it once even if the value is never used
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 5
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
\set ON_ERROR_STOP 0
|
||||
-- inverse of previous test query to confirm an error is actually thrown
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time = 5
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
-- test locf with correlated subquery
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
locf(min(value)) AS locf,
|
||||
locf(min(value)::int,23) AS locf1,
|
||||
locf(min(value)::int,(SELECT 42)) AS locf2,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test locf with correlated subquery and "wrong order"
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
locf(min(value)) AS locf,
|
||||
locf(min(value),23::float) AS locf1,
|
||||
locf(min(value),(SELECT 42::float)) AS locf2,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 1,2,3;
|
||||
|
||||
-- test locf with correlated subquery and window functions
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)),
|
||||
sum(locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1))) OVER (PARTITION BY device_id, sensor_id ROWS 1 PRECEDING)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3;
|
||||
|
||||
-- test interpolate
|
||||
SELECT
|
||||
time_bucket_gapfill(10,time,0,50) AS time,
|
||||
@ -834,55 +801,6 @@ SELECT
|
||||
FROM (VALUES (5,1,0),(5,2,0)) as v(time,device,v1)
|
||||
GROUP BY 1,2 ORDER BY 2,1;
|
||||
|
||||
-- test interpolate with correlated subquery
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
interpolate(min(value)) AS ip,
|
||||
interpolate(min(value),(-5,-5.0::float),(15,20.0::float)) AS ip1,
|
||||
interpolate(min(value),(SELECT (-10,-10.0::float)),(SELECT (15,20.0::float))) AS ip2,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
) AS ip3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test interpolate with correlated subquery and window function
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
),
|
||||
sum(interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
)) OVER (PARTITION BY device_id, sensor_id ROWS 1 PRECEDING)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test cte with gap filling in outer query
|
||||
WITH data AS (
|
||||
SELECT * FROM (VALUES (1,1,1),(2,2,2)) v(time,id,value)
|
||||
@ -1257,13 +1175,6 @@ FROM (VALUES (1,2),(2,2)) v(t1,t2)
|
||||
WHERE t1 > 0 AND t1 < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with unsupported operator
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int
|
||||
WHERE time =0 AND time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- time_bucket_gapfill with constraints ORed
|
||||
SELECT
|
||||
time_bucket_gapfill(1::int8,t::int8)
|
||||
@ -1272,44 +1183,8 @@ WHERE
|
||||
t >= -1 OR t < 3
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with 2 tables and where clause doesnt match gapfill argument
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m, metrics_int m2
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test inner join and where clause doesnt match gapfill argument
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m1 INNER JOIN metrics_int m2 ON m1.time=m2.time
|
||||
WHERE m1.time >=0 AND m1.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test outer join with constraints in join condition
|
||||
-- not usable as start/stop
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m1.time)
|
||||
FROM metrics_int m1 LEFT OUTER JOIN metrics_int m2 ON m1.time=m2.time AND m1.time >=0 AND m1.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
-- test subqueries
|
||||
-- subqueries will alter the shape of the plan and top-level constraints
|
||||
-- might not end up in top-level of jointree
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m1.time)
|
||||
FROM metrics_int m1
|
||||
WHERE m1.time >=0 AND m1.time < 2 AND device_id IN (SELECT device_id FROM metrics_int)
|
||||
GROUP BY 1;
|
||||
|
||||
-- test inner join with constraints in join condition
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m1 INNER JOIN metrics_int m2 ON m1.time=m2.time AND m2.time >=0 AND m2.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- int32 time_bucket_gapfill with no start/finish
|
||||
SELECT
|
||||
time_bucket_gapfill(1,t)
|
||||
@ -1422,27 +1297,6 @@ WHERE
|
||||
t > -2 AND t < 3
|
||||
GROUP BY 1;
|
||||
|
||||
-- test actual table
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int
|
||||
WHERE time >=0 AND time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with table alias
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int m
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with 2 tables
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m.time)
|
||||
FROM metrics_int m, metrics_int m2
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test DISTINCT
|
||||
SELECT DISTINCT ON (color)
|
||||
time_bucket_gapfill(1,time,0,5) as time,
|
||||
@ -1516,90 +1370,6 @@ EXECUTE prep_gapfill;
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test prepared statement with locf with lookup query
|
||||
PREPARE prep_gapfill AS
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1))
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 5
|
||||
GROUP BY 1,2,3;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test prepared statement with interpolate with lookup query
|
||||
PREPARE prep_gapfill AS
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test prepared statement with variable gapfill arguments
|
||||
PREPARE prep_gapfill(int,int,int) AS
|
||||
|
||||
SELECT
|
||||
time_bucket_gapfill($1,time,$2,$3) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
min(value)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= $2 AND time < $3 AND device_id=1 AND sensor_id=1
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test column references with TIME_COLUMN last
|
||||
SELECT
|
||||
row_number() OVER (PARTITION BY color),
|
||||
|
239
tsl/test/sql/include/gapfill_metrics_query.sql
Normal file
239
tsl/test/sql/include/gapfill_metrics_query.sql
Normal file
@ -0,0 +1,239 @@
|
||||
-- This file and its contents are licensed under the Timescale License.
|
||||
-- Please see the included NOTICE for copyright information and
|
||||
-- LICENSE-TIMESCALE for a copy of the license.
|
||||
|
||||
-- test locf lookup query does not trigger when not needed
|
||||
--
|
||||
-- 1/(SELECT 0) will throw an error in the lookup query but in order to not
|
||||
-- always trigger evaluation it needs to be correlated otherwise postgres will
|
||||
-- always run it once even if the value is never used
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 5
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test locf with correlated subquery
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
locf(min(value)) AS locf,
|
||||
locf(min(value)::int,23) AS locf1,
|
||||
locf(min(value)::int,(SELECT 42)) AS locf2,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test locf with correlated subquery and "wrong order"
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
locf(min(value)) AS locf,
|
||||
locf(min(value),23::float) AS locf1,
|
||||
locf(min(value),(SELECT 42::float)) AS locf2,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)) AS locf3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 1,2,3;
|
||||
|
||||
-- test locf with correlated subquery and window functions
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1)),
|
||||
sum(locf(min(value),(SELECT value FROM metrics_int m2 WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1))) OVER (PARTITION BY device_id, sensor_id ROWS 1 PRECEDING)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3;
|
||||
|
||||
-- test JOINs
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time,0,5) as time,
|
||||
device_id,
|
||||
d.name,
|
||||
sensor_id,
|
||||
s.name,
|
||||
avg(m.value)
|
||||
FROM metrics_int m
|
||||
INNER JOIN devices d USING(device_id)
|
||||
INNER JOIN sensors s USING(sensor_id)
|
||||
WHERE time BETWEEN 0 AND 5
|
||||
GROUP BY 1,2,3,4,5;
|
||||
|
||||
-- test interpolate with correlated subquery
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
avg(value),
|
||||
interpolate(min(value)) AS ip,
|
||||
interpolate(min(value),(-5,-5.0::float),(15,20.0::float)) AS ip1,
|
||||
interpolate(min(value),(SELECT (-10,-10.0::float)),(SELECT (15,20.0::float))) AS ip2,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
) AS ip3
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test interpolate with correlated subquery and window function
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
),
|
||||
sum(interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
)) OVER (PARTITION BY device_id, sensor_id ROWS 1 PRECEDING)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- test subqueries
|
||||
-- subqueries will alter the shape of the plan and top-level constraints
|
||||
-- might not end up in top-level of jointree
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m1.time)
|
||||
FROM metrics_int m1
|
||||
WHERE m1.time >=0 AND m1.time < 2 AND device_id IN (SELECT device_id FROM metrics_int)
|
||||
GROUP BY 1;
|
||||
|
||||
-- test inner join with constraints in join condition
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m2.time)
|
||||
FROM metrics_int m1 INNER JOIN metrics_int m2 ON m1.time=m2.time AND m2.time >=0 AND m2.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test actual table
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int
|
||||
WHERE time >=0 AND time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with table alias
|
||||
SELECT
|
||||
time_bucket_gapfill(1,time)
|
||||
FROM metrics_int m
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test with 2 tables
|
||||
SELECT
|
||||
time_bucket_gapfill(1,m.time)
|
||||
FROM metrics_int m, metrics_int m2
|
||||
WHERE m.time >=0 AND m.time < 2
|
||||
GROUP BY 1;
|
||||
|
||||
-- test prepared statement with locf with lookup query
|
||||
PREPARE prep_gapfill AS
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
locf(min(value)::int,(SELECT 1/(SELECT 0) FROM metrics_int m2 WHERE m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id ORDER BY time DESC LIMIT 1))
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 5
|
||||
GROUP BY 1,2,3;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test prepared statement with interpolate with lookup query
|
||||
PREPARE prep_gapfill AS
|
||||
SELECT
|
||||
time_bucket_gapfill(5,time,0,11) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
interpolate(
|
||||
min(value),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time<0 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time DESC LIMIT 1),
|
||||
(SELECT (time,value) FROM metrics_int m2
|
||||
WHERE time>10 AND m2.device_id=m1.device_id AND m2.sensor_id=m1.sensor_id
|
||||
ORDER BY time LIMIT 1)
|
||||
)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= 0 AND time < 10
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
EXECUTE prep_gapfill;
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
||||
|
||||
-- test prepared statement with variable gapfill arguments
|
||||
PREPARE prep_gapfill(int,int,int) AS
|
||||
|
||||
SELECT
|
||||
time_bucket_gapfill($1,time,$2,$3) AS time,
|
||||
device_id,
|
||||
sensor_id,
|
||||
min(value)
|
||||
FROM metrics_int m1
|
||||
WHERE time >= $2 AND time < $3 AND device_id=1 AND sensor_id=1
|
||||
GROUP BY 1,2,3 ORDER BY 2,3,1;
|
||||
|
||||
-- execute 10 times to make sure turning it into generic plan works
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
EXECUTE prep_gapfill(5,0,10);
|
||||
EXECUTE prep_gapfill(4,100,110);
|
||||
|
||||
DEALLOCATE prep_gapfill;
|
Loading…
x
Reference in New Issue
Block a user