should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,120 @@
# name: test/sql/join/asof/test_asof_join.test
# description: Test As-Of join useage
# group: [asof]
# Use doubles for readable infinities
statement ok
CREATE TABLE events0 (begin DOUBLE, value INTEGER);
statement ok
INSERT INTO events0 VALUES
(1, 0),
(3, 1),
(6, 2),
(8, 3)
;
# Prevent optimiser from removing true inequalities
statement ok
create table prices("when" timestamp, symbol int, price int);
statement ok
insert into prices values ('2020-01-01 00:00:00', 1, 42);
statement ok
create table trades("when" timestamp, symbol int);
statement ok
insert into trades values ('2020-01-01 00:00:03', 1);
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
query III
SELECT t.*, p.price
FROM trades t ASOF JOIN prices p
ON t.symbol = p.symbol AND t.when >= p.when;
----
2020-01-01 00:00:03 1 42
# NLJ does not support IS NOT DISTINCT FROM
query II
EXPLAIN
SELECT t.*, p.price
FROM trades t ASOF JOIN prices p
ON t.symbol IS NOT DISTINCT FROM p.symbol AND t.when >= p.when;
----
physical_plan <!REGEX>:.*NESTED_LOOP_JOIN.*
# Ignore non-join conditions
query II
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN events0 e
ON 1 = 1 AND p.ts >= e.begin
ORDER BY p.ts ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
query II
WITH samples AS (
SELECT col0 AS starts, col1 AS ends
FROM (VALUES
(5, 9),
(10, 13),
(14, 20),
(21, 23)
)
)
SELECT
s1.starts as s1_starts,
s2.starts as s2_starts,
FROM samples AS s1 ASOF JOIN samples as s2 ON s2.ends >= (s1.ends - 5)
WHERE s1_starts <> s2_starts
ORDER BY ALL
----
10 5
21 14
endloop
#
# Errors
#
# Invalid ASOF JOIN comparison
statement error
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN events0 e
ON p.ts <> e.begin
ORDER BY p.ts ASC
----
Binder Error: Missing ASOF JOIN inequality
# Missing ASOF JOIN inequality
statement error
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN events0 e
ON p.ts = e.begin
ORDER BY p.ts ASC
----
Binder Error: Missing ASOF JOIN inequality
# Multiple ASOF JOIN inequalities
statement error
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN events0 e
ON p.ts >= e.begin AND p.ts >= e.value
ORDER BY p.ts ASC
----
Binder Error: Multiple ASOF JOIN inequalities

View File

@@ -0,0 +1,64 @@
# name: test/sql/join/asof/test_asof_join.test_slow
# description: Coverage tests for AsOf Joins
# group: [asof]
statement ok
PRAGMA enable_verification
statement ok
pragma verify_external
# Highly skewed data to trigger spin-waits
statement ok
CREATE TABLE build AS
SELECT
'1990-03-21 13:00:00'::TIMESTAMP + INTERVAL (range) MINUTE AS begin,
range % 4 AS key,
range AS value,
FROM range(0, 10000000);
statement ok
CREATE TABLE skewed_probe (begin TIMESTAMP, key INTEGER);
statement ok
INSERT INTO skewed_probe
SELECT
'1990-04-21 13:00:01'::TIMESTAMP + INTERVAL (range) MINUTE AS begin,
0::INTEGER AS key,
FROM range(0, 5);
statement ok
INSERT INTO skewed_probe
SELECT
'1990-05-21 13:00:01'::TIMESTAMP + INTERVAL (range) MINUTE AS begin,
1::INTEGER AS key,
FROM range(0, 10);
statement ok
INSERT INTO skewed_probe
SELECT
'1990-06-21 13:00:01'::TIMESTAMP + INTERVAL (range) MINUTE AS begin,
2::INTEGER AS key,
FROM range(0, 20);
statement ok
INSERT INTO skewed_probe
SELECT
'1990-03-21 13:00:01'::TIMESTAMP + INTERVAL (range) MINUTE AS begin,
3::INTEGER AS key,
FROM range(0, 10000000);
# Early finish to some left partition scans: Highly skewed data
query II
SELECT SUM(value), COUNT(*)
FROM skewed_probe ASOF JOIN build USING(key, begin);
----
49999983751397 10000032
# Blocked until all left scans are completed
query II
SELECT SUM(value), COUNT(*)
FROM skewed_probe ASOF RIGHT JOIN build USING(key, begin);
----
87499975015813 17500020

View File

@@ -0,0 +1,354 @@
# name: test/sql/join/asof/test_asof_join_doubles.test
# description: Test As-Of joins for floating point
# group: [asof]
#
# Inequality only
#
statement ok
PRAGMA asof_loop_join_threshold=0;
# Use doubles for readable infinities
statement ok
CREATE TABLE events0 (begin DOUBLE, value INTEGER);
statement ok
INSERT INTO events0 VALUES
(1, 0),
(3, 1),
(6, 2),
(8, 3)
;
# INNER Window version
query II nosort inner_inequality
SELECT p.ts, e.value
FROM
range(0,10) p(ts)
JOIN (
SELECT value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (ORDER BY begin ASC) AS end
FROM events0
) e
ON p.ts >= e.begin AND p.ts < e.end
ORDER BY p.ts ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# INNER ON inequality only
query II nosort inner_inequality
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN events0 e
ON p.ts >= e.begin
ORDER BY p.ts ASC
----
# INNER USING inequality only
query II nosort inner_inequality
SELECT p.begin, e.value
FROM range(0,10) p(begin) ASOF JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
# LEFT Window version
query II nosort left_inequality
SELECT p.ts, e.value
FROM
range(0,10) p(ts)
LEFT JOIN (
SELECT value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (ORDER BY begin ASC) AS end
FROM events0
) e
ON p.ts >= e.begin AND p.ts < e.end
ORDER BY p.ts ASC NULLS FIRST
----
0 NULL
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# LEFT ON inequality only
query II nosort left_inequality
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF LEFT JOIN events0 e
ON p.ts >= e.begin
ORDER BY p.ts ASC NULLS FIRST
----
# LEFT USING inequality only
query II nosort left_inequality
SELECT p.begin, e.value
FROM range(0,10) p(begin) ASOF LEFT JOIN events0 e
USING (begin)
ORDER BY p.begin ASC NULLS FIRST
----
# Add unmatched right event
statement ok
INSERT INTO events0 VALUES (10, 4);
# RIGHT Window version
query II nosort
SELECT p.ts, e.value
FROM
range(0,10) p(ts)
RIGHT JOIN (
SELECT value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (ORDER BY begin ASC) AS end
FROM events0
) e
ON p.ts >= e.begin AND p.ts < e.end
ORDER BY p.ts ASC NULLS LAST
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL 4
# RIGHT ON inequality only
query II nosort
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF RIGHT JOIN events0 e
ON p.ts >= e.begin
ORDER BY p.ts ASC NULLS LAST
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL 4
# RIGHT USING inequality only
query II nosort
SELECT p.begin, e.value
FROM range(0,10) p(begin) ASOF RIGHT JOIN events0 e
USING (begin)
ORDER BY p.begin ASC NULLS LAST
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL 4
#
# With equality
#
statement ok
CREATE TABLE events (key INTEGER, begin DOUBLE, value INTEGER);
statement ok
INSERT INTO events VALUES
(1, 1, 0),
(1, 3, 1),
(1, 6, 2),
(1, 8, 3),
(2, 0, 10),
(2, 7, 20),
(2, 11, 30),
;
statement ok
CREATE TABLE probes AS
SELECT key, ts
FROM range(1,3) k(key) CROSS JOIN range(0,10) t(ts)
# INNER Window version
query III nosort inner_equality
SELECT p.key, p.ts, e.value
FROM
probes p
JOIN (
SELECT key, value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (PARTITION BY key ORDER BY begin ASC) AS end
FROM events
) e
ON p.key = e.key AND p.ts >= e.begin AND p.ts < e.end
ORDER BY 1, 2 ASC
----
1 1 0
1 2 0
1 3 1
1 4 1
1 5 1
1 6 2
1 7 2
1 8 3
1 9 3
2 0 10
2 1 10
2 2 10
2 3 10
2 4 10
2 5 10
2 6 10
2 7 20
2 8 20
2 9 20
# INNER ON with equality
query III nosort inner_equality
SELECT p.key, p.ts, e.value
FROM probes p ASOF JOIN events e
ON p.key = e.key AND p.ts >= e.begin
ORDER BY 1, 2 ASC
----
# INNER USING with equality
query III nosort inner_equality
SELECT p.key, p.begin, e.value
FROM
(SELECT key, ts AS begin FROM probes) p
ASOF JOIN
events e
USING (key, begin)
ORDER BY 1, 2 ASC
----
# LEFT Window version
query III nosort left_equality
SELECT p.key, p.ts, e.value
FROM
probes p
LEFT JOIN (
SELECT key, value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (PARTITION BY key ORDER BY begin ASC) AS end
FROM events
) e
ON p.key = e.key AND p.ts >= e.begin AND p.ts < e.end
ORDER BY 1, 2 ASC NULLS FIRST
----
1 0 NULL
1 1 0
1 2 0
1 3 1
1 4 1
1 5 1
1 6 2
1 7 2
1 8 3
1 9 3
2 0 10
2 1 10
2 2 10
2 3 10
2 4 10
2 5 10
2 6 10
2 7 20
2 8 20
2 9 20
# LEFT ON with equality
query III nosort left_equality
SELECT p.key, p.ts, e.value
FROM probes p ASOF LEFT JOIN events e
ON p.key = e.key AND p.ts >= e.begin
ORDER BY 1, 2, 3 ASC NULLS FIRST
----
# LEFT USING with equality
query III nosort left_equality
SELECT p.key, p.begin, e.value
FROM
(SELECT key, ts AS begin FROM probes) p
ASOF LEFT JOIN
events e
USING (key, begin)
ORDER BY 1, 2 ASC NULLS FIRST
----
# RIGHT Window version
query III nosort right_equality
SELECT p.key, p.ts, e.value
FROM
probes p
RIGHT JOIN (
SELECT key, value, begin,
LEAD(begin, 1, 'infinity'::DOUBLE) OVER (PARTITION BY key ORDER BY begin ASC) AS end
FROM events
) e
ON p.key = e.key AND p.ts >= e.begin AND p.ts < e.end
ORDER BY 1 ASC NULLS FIRST, 2
----
1 1 0
1 2 0
1 3 1
1 4 1
1 5 1
1 6 2
1 7 2
1 8 3
1 9 3
2 0 10
2 1 10
2 2 10
2 3 10
2 4 10
2 5 10
2 6 10
2 7 20
2 8 20
2 9 20
NULL NULL 30
# RIGHT ON with equality
query III nosort right_equality
SELECT p.key, p.ts, e.value
FROM probes p ASOF RIGHT JOIN events e
ON p.key = e.key AND p.ts >= e.begin
ORDER BY 1 ASC NULLS FIRST, 2
----
# RIGHT USING with equality
query III nosort right_equality
SELECT p.key, p.begin, e.value
FROM
(SELECT key, ts AS begin FROM probes) p
ASOF RIGHT JOIN
events e
USING (key, begin)
ORDER BY 1 ASC NULLS FIRST, 2
----
# INNER with empty RHS
query II
SELECT p.ts, e.value
FROM range(0,10) p(ts) ASOF JOIN (from events0 where value < 0) e
ON p.ts >= e.begin
ORDER BY p.ts ASC
----

View File

@@ -0,0 +1,236 @@
# name: test/sql/join/asof/test_asof_join_inequalities.test
# description: Test As-Of joins for greater than and less thans
# group: [asof]
# Join on a timestamp range
statement ok
CREATE TABLE events0 AS
SELECT '2023-03-21 13:00:00'::TIMESTAMP + INTERVAL (range) HOUR AS begin, range AS value
FROM range(0, 4);
statement ok
INSERT INTO events0 VALUES
(NULL, -10),
('infinity', 9),
('-infinity', -1)
;
statement ok
CREATE TABLE probe0 AS
SELECT *
FROM range('2023-03-21 12:00:00'::TIMESTAMP, '2023-03-21 22:00:00'::TIMESTAMP, INTERVAL 1 HOUR) p(begin)
;
statement ok
INSERT INTO probe0 VALUES
(NULL),
('infinity')
;
# Check results against IEJoin
foreach debug False True
statement ok
PRAGMA debug_asof_iejoin=${debug}
# Check NLJ results against both
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
#
# Strictly Greater Than
#
# INNER
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin > e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 -infinity -1
2023-03-21 13:00:00 -infinity -1
2023-03-21 14:00:00 2023-03-21 13:00:00 0
2023-03-21 15:00:00 2023-03-21 14:00:00 1
2023-03-21 16:00:00 2023-03-21 15:00:00 2
2023-03-21 17:00:00 2023-03-21 16:00:00 3
2023-03-21 18:00:00 2023-03-21 16:00:00 3
2023-03-21 19:00:00 2023-03-21 16:00:00 3
2023-03-21 20:00:00 2023-03-21 16:00:00 3
2023-03-21 21:00:00 2023-03-21 16:00:00 3
infinity 2023-03-21 16:00:00 3
# LEFT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin > e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 -infinity -1
2023-03-21 13:00:00 -infinity -1
2023-03-21 14:00:00 2023-03-21 13:00:00 0
2023-03-21 15:00:00 2023-03-21 14:00:00 1
2023-03-21 16:00:00 2023-03-21 15:00:00 2
2023-03-21 17:00:00 2023-03-21 16:00:00 3
2023-03-21 18:00:00 2023-03-21 16:00:00 3
2023-03-21 19:00:00 2023-03-21 16:00:00 3
2023-03-21 20:00:00 2023-03-21 16:00:00 3
2023-03-21 21:00:00 2023-03-21 16:00:00 3
infinity 2023-03-21 16:00:00 3
NULL NULL NULL
# RIGHT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin > e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 -infinity -1
2023-03-21 13:00:00 -infinity -1
2023-03-21 14:00:00 2023-03-21 13:00:00 0
2023-03-21 15:00:00 2023-03-21 14:00:00 1
2023-03-21 16:00:00 2023-03-21 15:00:00 2
2023-03-21 17:00:00 2023-03-21 16:00:00 3
2023-03-21 18:00:00 2023-03-21 16:00:00 3
2023-03-21 19:00:00 2023-03-21 16:00:00 3
2023-03-21 20:00:00 2023-03-21 16:00:00 3
2023-03-21 21:00:00 2023-03-21 16:00:00 3
infinity 2023-03-21 16:00:00 3
NULL infinity 9
NULL NULL -10
#
# Less Than or Equal
#
# INNER
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin <= e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 13:00:00 0
2023-03-21 14:00:00 2023-03-21 14:00:00 1
2023-03-21 15:00:00 2023-03-21 15:00:00 2
2023-03-21 16:00:00 2023-03-21 16:00:00 3
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
infinity infinity 9
# LEFT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin <= e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 13:00:00 0
2023-03-21 14:00:00 2023-03-21 14:00:00 1
2023-03-21 15:00:00 2023-03-21 15:00:00 2
2023-03-21 16:00:00 2023-03-21 16:00:00 3
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
infinity infinity 9
NULL NULL NULL
# RIGHT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin <= e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 13:00:00 0
2023-03-21 14:00:00 2023-03-21 14:00:00 1
2023-03-21 15:00:00 2023-03-21 15:00:00 2
2023-03-21 16:00:00 2023-03-21 16:00:00 3
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
infinity infinity 9
NULL -infinity -1
NULL NULL -10
#
# Strictly Less Than
#
# INNER
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin < e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 14:00:00 1
2023-03-21 14:00:00 2023-03-21 15:00:00 2
2023-03-21 15:00:00 2023-03-21 16:00:00 3
2023-03-21 16:00:00 infinity 9
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
# LEFT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin < e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 14:00:00 1
2023-03-21 14:00:00 2023-03-21 15:00:00 2
2023-03-21 15:00:00 2023-03-21 16:00:00 3
2023-03-21 16:00:00 infinity 9
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
infinity NULL NULL
NULL NULL NULL
# RIGHT
query III
SELECT p.begin, e.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin < e.begin
ORDER BY ALL ASC
----
2023-03-21 12:00:00 2023-03-21 13:00:00 0
2023-03-21 13:00:00 2023-03-21 14:00:00 1
2023-03-21 14:00:00 2023-03-21 15:00:00 2
2023-03-21 15:00:00 2023-03-21 16:00:00 3
2023-03-21 16:00:00 infinity 9
2023-03-21 17:00:00 infinity 9
2023-03-21 18:00:00 infinity 9
2023-03-21 19:00:00 infinity 9
2023-03-21 20:00:00 infinity 9
2023-03-21 21:00:00 infinity 9
NULL -infinity -1
NULL NULL -10
endloop
endloop

View File

@@ -0,0 +1,138 @@
# name: test/sql/join/asof/test_asof_join_integers.test
# description: Test As-Of joins for integers
# group: [asof]
# Join on an integer range
statement ok
CREATE TABLE events0 (begin INTEGER, value INTEGER);
statement ok
INSERT INTO events0 VALUES
(NULL, -1),
(1, 0),
(3, 1),
(6, 2),
(8, 3),
(999999, 9)
;
statement ok
CREATE TABLE probe0 AS
SELECT range::INTEGER AS begin
FROM range(0,10)
;
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
# INNER ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
query II
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# LEFT ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
0 NULL
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
query II
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
0 NULL
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# RIGHT ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin >= e.begin
ORDER BY ALL
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL -1
NULL 9
# RIGHT USING inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
USING (begin)
ORDER BY ALL
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL -1
NULL 9
endloop

View File

@@ -0,0 +1,29 @@
# name: test/sql/join/asof/test_asof_join_merge.test_slow
# description: Test merge queue and repartitioning
# group: [asof]
statement ok
PRAGMA memory_limit='400M'
statement ok
PRAGMA threads=4
statement ok
SET temp_directory='__TEST_DIR__/temp.tmp'
# Force PhysicalAsOfJoin
statement ok
PRAGMA asof_loop_join_threshold = 0;
query II
WITH build AS (
SELECT k, ('2021-01-01'::TIMESTAMP + INTERVAL (i) SECOND) AS t, i % 37 AS v
FROM range(3000000) t(i), range(2) tk(k)
), probe AS (
SELECT k, t
FROM range(2) tk(k),
range('2021-01-01 00:00:30'::TIMESTAMP, '2021-02-01 00:00:30'::TIMESTAMP, INTERVAL 1 HOUR) tt(t)
) SELECT SUM(v) AS v, COUNT(*) AS n
FROM probe ASOF JOIN build USING(k, t)
----
26790 1488

View File

@@ -0,0 +1,165 @@
# name: test/sql/join/asof/test_asof_join_missing.test_slow
# description: Test As-Of join with missing matches
# group: [asof]
statement ok
PRAGMA enable_verification
# These test stress several aspects of the matching:
# * Probe inequality less than the minimum (no match)
# * Probe equality missing (no match)
# * More than 64 valid probe entries (mask => SV construction)
# * First radix bin empty.
# * First payload bin empty
# * Multiple scanned payload blocks
statement ok
PRAGMA asof_loop_join_threshold=0;
# Check results against IEJoin
foreach debug False True
statement ok
PRAGMA debug_asof_iejoin=${debug}
# 10 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,10) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
108
# Coverage: Missing right side bin
query II
WITH build AS (
SELECT k * 2 as k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,10) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k / 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v), COUNT(*)
FROM probe ASOF JOIN build USING(k, t);
----
108 27
# 20 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,20) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
513
# 30 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,30) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
1218
# 50 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,50) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
3528
# 100 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,100) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
14553
# 100 dates, 50 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,100) vals(v), range(0,50) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
121275
# 1000 dates, 5 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,1000) vals(v), range(0,5) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
1495503
# 1000 dates, 50 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,1000) vals(v), range(0,50) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
12462525
# 10000 dates, 50 keys
query I
WITH build AS (
SELECT k, '2001-01-01 00:00:00'::TIMESTAMP + INTERVAL (v) MINUTE AS t, v
FROM range(0,10000) vals(v), range(0,50) keys(k)
), probe AS (
SELECT k * 2 AS k, t - INTERVAL (30) SECOND AS t
FROM build
)
SELECT SUM(v)
FROM probe ASOF JOIN build USING(k, t);
----
1249625025
endloop

View File

@@ -0,0 +1,114 @@
# name: test/sql/join/asof/test_asof_join_predicates.test
# description: Test As-Of join NLJ rewrite for non-comparison predicates
# group: [asof]
statement ok
PRAGMA enable_verification;
# Issue 18309
statement ok
CREATE TABLE tt1 (i INTEGER, j VARCHAR);
statement ok
INSERT INTO tt1 VALUES
(2, 'A'),
(4, 'B'),
(5, 'A');
statement ok
CREATE TABLE tt2 (i INTEGER, j VARCHAR, k VARCHAR);
statement ok
INSERT INTO tt2 VALUES
(1, 'A', 'I'),
(3, 'B', 'II');
query II
explain
SELECT tt1.i, tt2.k
FROM tt1
ASOF JOIN tt2 ON
tt1.j = tt2.j AND tt1.i >= tt2.i
ORDER BY tt1.i;
----
physical_plan <REGEX>:.*NESTED_LOOP_JOIN.*
query II
SELECT tt1.i, tt2.k
FROM tt1
ASOF JOIN tt2 ON
(tt1.j = tt2.j OR tt1.j = tt2.j) AND tt1.i >= tt2.i
ORDER BY tt1.i;
----
2 I
4 II
5 I
# Issue 19027
statement ok
create table l (id integer, date timestamp, item varchar);
statement ok
insert into l values
(0, '2025-01-01', 'A');
statement ok
create table r (id integer, date timestamp, item varchar, valuei double);
statement ok
insert into r values
(0, '2025-01-01', 'A', 8.0),
(0, '2025-01-01', 'B', 12.0);
query II
explain
select
l.id,
l.date,
l.item as litem,
r.item as ritem,
valuei
from l
asof left join r
on l.id = r.id and l.date >= r.date
and (l.item = r.item or l.item = '*');
----
physical_plan <REGEX>:.*NESTED_LOOP_JOIN.*
query IIIII
select
l.id,
l.date,
l.item as litem,
r.item as ritem,
valuei
from l
asof left join r
on l.id = r.id and l.date >= r.date
and (l.item = r.item or l.item = '*');
----
0 2025-01-01 00:00:00 A A 8.0
# Issue 19251
statement ok
create temp table tbl1 as
select unnest(range(1000)) % 10 as x, '2022-01-01'::timestamp + to_days(unnest(range(1000))) as ts;
statement ok
create temp table tbl2 as
select unnest(range(1000)) % 10 as x, '2022-01-01'::timestamp + to_hours(unnest(range(1000))) as ts;
query II
explain
from tbl1 asof join
tbl2 on tbl1.x = tbl2.x
and tbl1.ts >= tbl2.ts
and (tbl1.ts - tbl2.ts) < interval '1' hours;
----
physical_plan <REGEX>:.*NESTED_LOOP_JOIN.*
statement ok
from tbl1 asof join
tbl2 on tbl1.x = tbl2.x
and tbl1.ts >= tbl2.ts
and (tbl1.ts - tbl2.ts) < interval '1' hours;

View File

@@ -0,0 +1,201 @@
# name: test/sql/join/asof/test_asof_join_pushdown.test
# description: Test predicate pushdown for ASOF joins
# group: [asof]
statement ok
CREATE OR REPLACE TABLE right_pushdown(time INTEGER, value FLOAT);
statement ok
INSERT INTO right_pushdown VALUES
(0, 0),
(1, NULL),
;
statement ok
CREATE TABLE issue13899(seq_no INT, amount DECIMAL(10,2));
statement ok
INSERT INTO issue13899 VALUES
(1,1.00),
(2,null),
(3,null),
(4,null),
(5,2.00),
(6,null),
(7,null),
(8,3.00),
(9,null),
(10,null),
(11,5.00);
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
query IIII
SELECT
d1.time,
d2.time,
d1.value,
d2.value
FROM right_pushdown d1
ASOF JOIN (
SELECT * FROM right_pushdown WHERE value is not NULL
) d2
ON d1.time >= d2.time
ORDER BY ALL;
----
0 0 0.0 0.0
1 0 NULL 0.0
query IIII
SELECT
d1.time,
d2.time,
d1.value,
d2.value
FROM right_pushdown d1
ASOF LEFT JOIN (
SELECT * FROM right_pushdown WHERE value is not NULL
) d2
ON d1.time >= d2.time
ORDER BY ALL;
----
0 0 0.0 0.0
1 0 NULL 0.0
statement ok
CREATE OR REPLACE TABLE issue12215 AS
SELECT col0 AS starts, col1 AS ends
FROM (VALUES
(5, 9),
(10, 13),
(14, 20),
(21, 23)
);
query II
SELECT
s1.starts as s1_starts,
s2.starts as s2_starts,
FROM issue12215 AS s1
ASOF JOIN issue12215 as s2
ON s2.ends >= (s1.ends - 5)
WHERE s1_starts <> s2_starts
ORDER BY ALL
----
10 5
21 14
query II
WITH t as (
SELECT
t1.col0 AS left_val,
t2.col0 AS right_val,
FROM
(VALUES (0), (5), (10), (15)) AS t1
ASOF JOIN (VALUES (1), (6), (11), (16)) AS t2
ON t2.col0 > t1.col0
)
SELECT *
FROM t
WHERE right_val BETWEEN 3 AND 12
ORDER BY ALL
----
5 6
10 11
query II
WITH t as (
SELECT
t1.col0 AS left_val,
t2.col0 AS right_val,
FROM
(VALUES (0), (5), (10), (15)) AS t1
ASOF LEFT JOIN (VALUES (1), (6), (11), (16)) AS t2
ON t2.col0 > t1.col0
)
SELECT *
FROM t
WHERE right_val BETWEEN 3 AND 12
ORDER BY ALL
----
5 6
10 11
query III
select
a.seq_no,
a.amount,
b.amount
from issue13899 as a
asof join issue13899 as b
on a.seq_no>=b.seq_no
and b.amount is not null
ORDER BY 1
----
1 1.00 1.00
2 NULL 1.00
3 NULL 1.00
4 NULL 1.00
5 2.00 2.00
6 NULL 2.00
7 NULL 2.00
8 3.00 3.00
9 NULL 3.00
10 NULL 3.00
11 5.00 5.00
endloop
query IIII
WITH t1 AS (
FROM (VALUES (1,2),(2,4)) t1(id, value)
),
t2 AS (
FROM (VALUES (1,3)) t2(id, value)
)
FROM t1
ASOF LEFT JOIN t2
ON t1.id <= t2.id
ORDER BY 1
----
1 2 1 3
2 4 NULL NULL
query IIII
WITH t1 AS (
FROM (VALUES (1,2),(2,4)) t1(id, value)
),
t2 AS (
FROM (VALUES (1,3)) t2(id, value)
)
FROM t1
ASOF LEFT JOIN t2
ON t1.id >= t2.id AND t1.id = 1
ORDER BY 1
----
1 2 1 3
2 4 NULL NULL
statement error
WITH t1 AS (
FROM VALUES
(1::INT, '2020-01-01 00:00:00'::TIMESTAMP),
(2, '2020-01-02 00:00:00')
AS t1(a, b)
), t2 AS (
FROM VALUES
(1::INT, '2020-01-01 00:01:00'::TIMESTAMP),
(2, '2020-01-02 00:00:00')
t2(c, d)
)
SELECT *
FROM t1
ASOF JOIN t2
ON t1=b == t2.d
AND t1.b >= t2.d - INTERVAL '1' SECOND;
----
Unimplemented type for cast

View File

@@ -0,0 +1,41 @@
# name: test/sql/join/asof/test_asof_join_subquery.test
# description: Test As-Of correlated subqueries
# group: [asof]
statement ok
CREATE TABLE events (begin DOUBLE, value INTEGER);
statement ok
INSERT INTO events VALUES
(1, 0),
(3, 1),
(6, 2),
(8, 3)
;
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
query II
SELECT begin, value IN (
SELECT e1.value
FROM (
SELECT *
FROM events e1
WHERE e1.value = events.value) e1
ASOF JOIN
range(1, 10) tbl(begin)
USING (begin)
)
FROM events
ORDER BY ALL;
----
1.0 true
3.0 true
6.0 true
8.0 true
endloop

View File

@@ -0,0 +1,232 @@
# name: test/sql/join/asof/test_asof_join_timestamps.test
# description: Test As-Of joins for timestamps
# group: [asof]
# Join on a timestamp range
statement ok
CREATE TABLE events0 AS
SELECT '2023-03-21 13:00:00'::TIMESTAMP + INTERVAL (range) HOUR AS begin, range AS value
FROM range(0, 4);
# Could we add some tests where we have NULL values in the tables?
# Could we add some tests where we have infinity values (e.g. NaN, or infinity::timestamp) in the tables?
statement ok
INSERT INTO events0 VALUES
(NULL, -1),
('infinity', 9)
;
statement ok
CREATE TABLE probe0 AS
SELECT *
FROM range('2023-03-21 12:00:00'::TIMESTAMP, '2023-03-21 22:00:00'::TIMESTAMP, INTERVAL 1 HOUR) p(begin)
;
statement ok
INSERT INTO probe0 VALUES
(NULL),
('infinity')
;
statement ok
CREATE TABLE asof_nulls (
time TIMESTAMP,
value FLOAT
);
statement ok
INSERT INTO asof_nulls (time, value) VALUES ('2025-07-15 00:00:00', 42);
statement ok
INSERT INTO asof_nulls (time, value) VALUES ('2025-07-15 01:00:00', null);
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
# INNER ON inequality only
query II nosort
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
# INNER USING inequality only
query II nosort
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
# LEFT ON inequality only
query II nosort
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
2023-03-21 12:00:00 NULL
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
NULL NULL
# LEFT USING inequality only
query II nosort left_inequality
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
2023-03-21 12:00:00 NULL
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
NULL NULL
# RIGHT ON inequality only
query II nosort
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin >= e.begin
ORDER BY ALL
----
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
NULL -1
# RIGHT USING inequality only
query II nosort
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
USING (begin)
ORDER BY ALL
----
2023-03-21 13:00:00 0
2023-03-21 14:00:00 1
2023-03-21 15:00:00 2
2023-03-21 16:00:00 3
2023-03-21 17:00:00 3
2023-03-21 18:00:00 3
2023-03-21 19:00:00 3
2023-03-21 20:00:00 3
2023-03-21 21:00:00 3
infinity 9
NULL -1
#
# Coverage
#
# rhs_sink.count == 0
query II
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN (SELECT * FROM events0 WHERE log(value + 5) > 10) e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
2023-03-21 12:00:00 NULL
2023-03-21 13:00:00 NULL
2023-03-21 14:00:00 NULL
2023-03-21 15:00:00 NULL
2023-03-21 16:00:00 NULL
2023-03-21 17:00:00 NULL
2023-03-21 18:00:00 NULL
2023-03-21 19:00:00 NULL
2023-03-21 20:00:00 NULL
2023-03-21 21:00:00 NULL
infinity NULL
NULL NULL
# EmptyResultIfRHSIsEmpty
query II
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN (SELECT * FROM events0 WHERE log(value + 5) > 10) e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
# SEMI JOIN
query I
SELECT p.begin
FROM probe0 p ASOF SEMI JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
2023-03-21 13:00:00
2023-03-21 14:00:00
2023-03-21 15:00:00
2023-03-21 16:00:00
2023-03-21 17:00:00
2023-03-21 18:00:00
2023-03-21 19:00:00
2023-03-21 20:00:00
2023-03-21 21:00:00
infinity
# ANTI JOIN
query I
SELECT p.begin
FROM probe0 p ASOF ANTI JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
2023-03-21 12:00:00
NULL
# Return NULLs
query II
SELECT time_series.time, asof_nulls.value
FROM (VALUES ('2025-07-15 02:00:00'::TIMESTAMP)) as time_series(time)
ASOF LEFT JOIN asof_nulls ON asof_nulls.time <= time_series.time;
----
2025-07-15 02:00:00 NULL
endloop

View File

@@ -0,0 +1,25 @@
# name: test/sql/join/asof/test_asof_join_tpch.test_slow
# description: AsOf Join using floating point keys in TPC-H
# group: [asof]
require tpch
statement ok
CALL dbgen(sf=0.1, suffix='_normal');
statement ok
CREATE TABLE lineitem_dbl AS SELECT * REPLACE (l_orderkey::DOUBLE + 0.25 AS l_orderkey) FROM lineitem_normal;
statement ok
CREATE TABLE orders_dbl AS SELECT * REPLACE (o_orderkey::DOUBLE AS o_orderkey) FROM orders_normal;
query I
SELECT COUNT(*) from lineitem_normal join orders_normal on (l_orderkey=o_orderkey);
----
600572
query I
SELECT COUNT(*)
FROM lineitem_dbl ASOF JOIN orders_dbl ON (l_orderkey >= o_orderkey);
----
600572

View File

@@ -0,0 +1,138 @@
# name: test/sql/join/asof/test_asof_join_varchar.test
# description: Test As-Of joins for strings
# group: [asof]
# Join on a string range
statement ok
CREATE TABLE events0 (begin VARCHAR, value INTEGER);
statement ok
INSERT INTO events0 VALUES
(NULL, -1),
(1, 0),
(3, 1),
(6, 2),
(8, 3),
('infinity', 9)
;
statement ok
CREATE TABLE probe0 AS
SELECT range::VARCHAR AS begin
FROM range(0,10)
;
# Compare NLJ optimisation to operator
foreach threshold 0 32
statement ok
PRAGMA asof_loop_join_threshold = ${threshold};
# INNER ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
query II
SELECT p.begin, e.value
FROM probe0 p ASOF JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# LEFT ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
ON p.begin >= e.begin
ORDER BY p.begin ASC
----
0 NULL
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
query II
SELECT p.begin, e.value
FROM probe0 p ASOF LEFT JOIN events0 e
USING (begin)
ORDER BY p.begin ASC
----
0 NULL
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
# RIGHT ON inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
ON p.begin >= e.begin
ORDER BY ALL
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL -1
NULL 9
# RIGHT USING inequality only
query II
SELECT p.begin, e.value
FROM probe0 p ASOF RIGHT JOIN events0 e
USING (begin)
ORDER BY ALL
----
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 3
9 3
NULL -1
NULL 9
endloop