Files
email-tracker/external/duckdb/test/sql/window/test_fill.test
2025-10-24 19:21:19 -05:00

433 lines
8.0 KiB
SQL

# name: test/sql/window/test_fill.test
# description: Test Fill function
# group: [window]
#
# Error checks
#
# Only one ordering allowed
statement error
select fill(i) over (order by i, 10-i) from range(3) tbl(i);
----
FILL functions must have only one ORDER BY expression
# Streaming not supported because the interpolation values might be too far away.
statement error
select fill(i) over () from range(3) tbl(i);
----
FILL functions must have only one ORDER BY expression
# Argument must be numeric
statement error
select fill(i::VARCHAR) over (order by i) from range(3) tbl(i);
----
FILL argument must support subtraction
# Ordering must be numeric
statement error
select fill(i) over (order by i::VARCHAR) from range(3) tbl(i);
----
FILL ordering must support subtraction
#
# Simple interpolation coverage tests
#
foreach ordertype tinyint smallint integer bigint hugeint float double utinyint usmallint uinteger ubigint uhugeint
foreach filltype tinyint smallint integer bigint hugeint float double utinyint usmallint uinteger ubigint uhugeint
loop nulled 0 3
# Between, before and after
query II
select
i,
fill(if(i = ${nulled}, NULL, i)::${filltype}) over(order by i::${ordertype}) as f
from range(3) tbl(i)
qualify i is distinct from f
----
endloop
# Single values
query II
select
i,
fill(if(i > 0, NULL, i)::${filltype}) over(order by i::${ordertype}) as f
from range(3) tbl(i)
qualify f is distinct from 0
----
# No values in partition
query II
select
i,
fill(if(i < 4, NULL, i)::${filltype}) over(partition by i // 2 order by i::${ordertype}) f
from range(8) tbl(i)
order by i
----
0 NULL
1 NULL
2 NULL
3 NULL
4 4
5 5
6 6
7 7
# Outside valid sort values
query II
select
i,
fill(if(i = 2, NULL, i)::${filltype}) over(order by if(i < 4, NULL, i)::${ordertype}) f
from range(8) tbl(i)
qualify i is distinct from f
order by i
----
2 NULL
foreach sense asc desc
foreach nulls first last
# NULL sort key coverage
query II
select
i,
fill(i::${filltype}) over(order by i::${ordertype} ${sense} nulls ${nulls}) f
from (
from range(3) r(i)
union all
select NULL as i
) tbl(i)
qualify i is distinct from f
order by i
----
endloop
endloop
endloop
endloop
foreach ordertype smallint integer bigint hugeint float double usmallint uinteger ubigint uhugeint
foreach filltype smallint integer bigint hugeint float double usmallint uinteger ubigint uhugeint
# Previous in another chunk
query II
select
i,
fill(if(i = 2048, NULL, i)::${filltype}) over(order by i::${ordertype}) f
from range(2060) tbl(i)
qualify i <> f
----
endloop
endloop
#
# Temporal coverage
#
foreach ordertype date timestamp timestamptz
foreach filltype date timestamp timestamptz
loop nulled 1 4
# Before, Between and After values
query II
select
i,
fill(if(day(i) = ${nulled}, NULL, i)::${filltype}) over(order by i::${ordertype}) f
from range('2025-01-01'::DATE, '2025-01-04'::DATE, INTERVAL 1 DAY) tbl(i)
qualify f <> i
----
endloop
foreach sense asc desc
foreach nulls first last
# NULL sort key coverage
query II
select
i,
fill(i::${filltype}) over(order by i::${ordertype} ${sense} nulls ${nulls}) f
from (
from range('2025-01-01'::DATE, '2025-01-04'::DATE, INTERVAL 1 DAY) r(i)
union all
select NULL as i
) tbl(i)
qualify i is distinct from f
order by i
----
endloop
endloop
# Single values
query II
select
i,
fill(if(day(i) > 1, NULL, i)::${filltype}) over(order by i::${ordertype}) f
from range('2025-01-01'::DATE, '2025-01-04'::DATE, INTERVAL 1 DAY) tbl(i)
qualify f <> '2025-01-01'::DATE
----
# No values in partition
query II
select
i,
fill(if(day(i) < 5, NULL, i)::${filltype}) over(partition by (day(i) - 1) // 2 order by i::${ordertype}) f
from range('2025-01-01'::DATE, '2025-01-09'::DATE, INTERVAL 1 DAY) tbl(i)
qualify f is NULL
order by i
----
2025-01-01 00:00:00 NULL
2025-01-02 00:00:00 NULL
2025-01-03 00:00:00 NULL
2025-01-04 00:00:00 NULL
# Outside valid sort values
query II
select
i,
fill(if(day(i) = 3, NULL, i)::${filltype}) over(order by if(day(i) < 5, NULL, i)::${ordertype}) f
from range('2025-01-01'::DATE, '2025-01-09'::DATE, INTERVAL 1 DAY) tbl(i)
qualify i is distinct from f
order by i
----
2025-01-03 00:00:00 NULL
# Previous in another chunk
query II
select
i,
fill(if(i = '2015-01-01'::DATE + 2048, NULL, i)::${filltype}) over(order by i::${ordertype}) f
from range('2025-01-01'::DATE, '2020-08-22'::DATE, INTERVAL 1 DAY) tbl(i)
qualify i <> f
----
endloop
endloop
# Time
loop nulled 1 4
# Before, Between and After values
query II
select
i::TIME t,
fill(if(minute(i) = ${nulled}, NULL, i)::TIME) over(order by i::TIME) f
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:03'::TIMESTAMP, INTERVAL 1 MINUTE) tbl(i)
qualify f <> t
----
endloop
foreach sense asc desc
foreach nulls first last
# NULL sort key coverage
query II
select
i::TIME t,
fill(t) over(order by t ${sense} nulls ${nulls}) f
from (
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:03'::TIMESTAMP, INTERVAL 1 MINUTE) r(i)
union all
select NULL as i
) tbl(i)
qualify t is distinct from f
order by t
----
endloop
endloop
# Single values
query II
select
i::TIME t,
fill(if(minute(i) > 0, NULL, i)::TIME) over(order by i::TIME) f
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:03'::TIMESTAMP, INTERVAL 1 MINUTE) tbl(i)
qualify f <> '00:00:00'::TIME
----
# No values in partition
query II
select
i::TIME t,
fill(if(minute(i) < 4, NULL, i)::TIME) over(partition by minute(i) // 2 order by i::TIME) f
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:09'::TIMESTAMP, INTERVAL 1 MINUTE) tbl(i)
qualify f is not NULL
order by t
----
00:04:00 00:04:00
00:05:00 00:05:00
00:06:00 00:06:00
00:07:00 00:07:00
00:08:00 00:08:00
# Outside valid sort values
query II
select
i::TIME t,
fill(if(minute(i) = 3, NULL, i)::TIME) over(order by if(minute(i) < 4, NULL, i)::TIME) f
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:09'::TIMESTAMP, INTERVAL 1 MINUTE) tbl(i)
qualify t is distinct from f
order by t
----
00:03:00 NULL
# Previous in another chunk
query II
select
i::TIME t,
fill(if(i = '2015-01-01'::TIMESTAMP + INTERVAL 2048 SECOND, NULL, i)::TIME) over(order by i::TIME) f
from range('2025-01-01'::TIMESTAMP, '2025-01-01 00:34:20'::TIMESTAMP, INTERVAL 1 SECOND) tbl(i)
qualify t <> f
----
#
# Extrapolation failures
#
# Signed
query II
with source as (
select
i,
if(i = -129, NULL, i)::TINYINT as missing
from range(-129, -120) tbl(i)
)
select
i,
fill(missing) over (order by i) as filled
from source
qualify filled is distinct from i
----
-129 NULL
query II
with source as (
select
i,
if(i = 128, NULL, i)::TINYINT as missing
from range(120, 129) tbl(i)
)
select
i,
fill(missing) over (order by i) as filled
from source
qualify filled is distinct from i
----
128 NULL
# Unsigned
query II
with source as (
select
i,
if(i = -1, NULL, i)::UTINYINT as missing
from range(-1, 10) tbl(i)
)
select
i,
fill(missing) over (order by i) as filled
from source
qualify filled is distinct from i
----
-1 NULL
query II
with source as (
select
i,
if(i = 256, NULL, i)::UTINYINT as missing
from range(250, 257) tbl(i)
)
select
i,
fill(missing) over (order by i) as filled
from source
qualify filled is distinct from i
----
256 NULL
#
# Unusable values
#
# If we use an unsuable value, the interpolation will produce strange values
# Infinity/NaN
foreach ordertype float double
foreach unusable 'infinity' '-infinity' 'NaN'
loop nullable 0 5
query II
select
i,
fill(if(i = ${nullable}, NULL, i)) over(order by i) f
from (
from range(5) r(i)
union all
select ${unusable}::${ordertype} as i
) tbl(i)
qualify i is distinct from f
order by i
----
endloop
endloop
endloop
# Temporal infinities
foreach ordertype date timestamp
foreach filltype date timestamp
foreach unusable 'infinity' '-infinity'
loop nulled 1 4
query II
select
i,
fill(if(day(i) = ${nulled}, NULL, i)::${filltype}) over(order by i::${ordertype}) f
from (
from range('2025-01-01'::DATE, '2025-01-05'::DATE, INTERVAL 1 DAY) r(i)
union all
select ${unusable}::${ordertype} as i
) tbl(i)
qualify f is NULL
order by i
----
endloop
endloop
endloop
endloop