-- Gaps listed in docs/COVERAGE.md section 9 (operators/aggregates not -- exercised elsewhere). SET client_min_messages = warning; CREATE EXTENSION IF NOT EXISTS pg_nanotime; RESET client_min_messages; SET TimeZone = 'Asia/Taipei'; SET extra_float_digits = 0; -- interval + ts (commutator of ts + interval) SELECT interval '1 day 2 hours' + '2026-03-01 00:00:00.123456789+08'::nanotimestamptz AS tz16; tz16 ---------------------------------- 2026-03-02 02:00:00.123456789+08 (1 row) SELECT interval '1 day 2 hours' + '2026-03-01 00:00:00.123456789+08'::nanotimestamptz = '2026-03-01 00:00:00.123456789+08'::nanotimestamptz + interval '1 day 2 hours' AS tz16_commutes; tz16_commutes --------------- t (1 row) SELECT interval '1 month' + '2026-01-31 12:00:00.000000001+08'::nanotimestamptz8 AS tz8; tz8 ---------------------------------- 2026-02-28 12:00:00.000000001+08 (1 row) SELECT interval '1 day' + '2026-03-01 00:00:00.5+08'::nanotimestamptz8 = '2026-03-01 00:00:00.5+08'::nanotimestamptz8 + interval '1 day' AS tz8_commutes; tz8_commutes -------------- t (1 row) SELECT pg_typeof(interval '1 day' + '2026-03-01'::nanotimestamptz8) AS tz8_type; tz8_type ------------------ nanotimestamptz8 (1 row) -- nanotimestamptz8 - interval SELECT '2026-03-01 00:00:00.000000007+08'::nanotimestamptz8 - interval '1 month' AS tz8_minus_month; tz8_minus_month ---------------------------------- 2026-02-01 00:00:00.000000007+08 (1 row) SELECT '2026-03-01 00:00:00.000000007+08'::nanotimestamptz8 - interval '1.5 seconds' AS tz8_minus_sec; tz8_minus_sec ---------------------------------- 2026-02-28 23:59:58.500000007+08 (1 row) SELECT pg_typeof('2026-03-01'::nanotimestamptz8 - interval '1 day') AS tz8_minus_type; tz8_minus_type ------------------ nanotimestamptz8 (1 row) SELECT ('2026-03-01'::nanotimestamptz8 - interval '-1 day') = ('2026-03-01'::nanotimestamptz8 + interval '1 day') AS neg_ok; neg_ok -------- t (1 row) -- out of range for the 8 B type SELECT '1677-09-22 00:00:00+00'::nanotimestamptz8 - interval '2 days'; ERROR: nanotimestamptz8 out of range DETAIL: nanotimestamptz8 covers only 1677-09-21 00:12:43.145224192 to 2262-04-11 23:47:16.854775807 UTC. HINT: Use nanotimestamptz (16 bytes) for values outside this range. -- bigint * nanointerval SELECT 3::bigint * '1.000000001 s'::nanointerval AS bigint_mul; bigint_mul -------------------- 00:00:03.000000003 (1 row) SELECT (3::bigint * '1.000000001 s'::nanointerval) = ('1.000000001 s'::nanointerval * 3::bigint) AS mul_commutes; mul_commutes -------------- t (1 row) SELECT (-2)::bigint * '5 ns'::nanointerval AS bigint_mul_neg; bigint_mul_neg --------------------- -00:00:00.000000010 (1 row) SELECT 9223372036854775807::bigint * '2 s'::nanointerval; ERROR: nanointerval out of range CONTEXT: SQL function "int8_mul_nanointerval" statement 1 -- nanointerval / bigint (direct, not through int4) SELECT '10 ns'::nanointerval / 3::bigint AS div3; div3 -------------------- 00:00:00.000000003 (1 row) SELECT '11 ns'::nanointerval / 2::bigint AS div_round_up; div_round_up -------------------- 00:00:00.000000006 (1 row) SELECT '-11 ns'::nanointerval / 2::bigint AS div_round_away; div_round_away --------------------- -00:00:00.000000006 (1 row) SELECT '1 s'::nanointerval / 4000000000::bigint AS div_big; div_big -------------------- 00:00:00.000000000 (1 row) SELECT '1 s'::nanointerval / 0::bigint; ERROR: division by zero -- <> on the remaining types SELECT '2026-03-01 00:00:00.000000001+08'::nanotimestamptz8 <> '2026-03-01 00:00:00.000000002+08'::nanotimestamptz8 AS tz8_ne, '2026-03-01 00:00:00.000000001+08'::nanotimestamptz8 <> '2026-03-01 00:00:00.000000001+08'::nanotimestamptz8 AS tz8_ne_same; tz8_ne | tz8_ne_same --------+------------- t | f (1 row) SELECT '2026-03-01 00:00:00.000000001'::nanotimestamp <> '2026-03-01 00:00:00.000000002'::nanotimestamp AS notz_ne, '2026-03-01 00:00:00.000000001'::nanotimestamp <> '2026-03-01 00:00:00.000000001'::nanotimestamp AS notz_ne_same; notz_ne | notz_ne_same ---------+-------------- t | f (1 row) SELECT '1 ns'::nanointerval <> '2 ns'::nanointerval AS ni_ne, '1 s'::nanointerval <> '1000000000 ns'::nanointerval AS ni_ne_same; ni_ne | ni_ne_same -------+------------ t | f (1 row) SELECT count(*) FILTER (WHERE a <> b) AS ne, count(*) FILTER (WHERE NOT a = b) AS not_eq FROM (VALUES ('1 ns'::nanointerval, '1 ns'::nanointerval), ('1 ns', '2 ns'), ('-1 ns', '1 ns')) v(a, b); ne | not_eq ----+-------- 2 | 2 (1 row) -- percentile_disc directly on nanointerval CREATE TEMP TABLE lat (d nanointerval); INSERT INTO lat SELECT nanointerval_from_ns(g * 1000 + 7) FROM generate_series(1, 100) g; INSERT INTO lat VALUES (NULL); SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY d) AS p50, percentile_disc(0.99) WITHIN GROUP (ORDER BY d) AS p99, percentile_disc(ARRAY[0, 0.9, 1]) WITHIN GROUP (ORDER BY d) AS ps FROM lat; p50 | p99 | ps --------------------+--------------------+------------------------------------------------------------ 00:00:00.000050007 | 00:00:00.000099007 | {00:00:00.000001007,00:00:00.000090007,00:00:00.000100007} (1 row) SELECT pg_typeof(percentile_disc(0.5) WITHIN GROUP (ORDER BY d)) FROM lat; pg_typeof -------------- nanointerval (1 row) SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY d)::bigint = percentile_disc(0.5) WITHIN GROUP (ORDER BY d::bigint) AS matches_bigint FROM lat; matches_bigint ---------------- t (1 row) -- percentile_cont needs interpolation: not supported SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY d) FROM lat; ERROR: function percentile_cont(numeric, nanointerval) does not exist LINE 1: SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY d) FROM l... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. DROP TABLE lat;