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:
Ruslan Fomkin 2020-12-09 13:11:03 +01:00 committed by Ruslan Fomkin
parent 494fe90801
commit 2e352664ba
5 changed files with 1068 additions and 890 deletions

View File

@ -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

View File

@ -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

View File

@ -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),

View 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;