From 8b1f4eb95847482787e325079286b09876615f31 Mon Sep 17 00:00:00 2001 From: dennis zhuang Date: Thu, 24 Aug 2023 11:26:19 +0800 Subject: [PATCH] feat: types sqlness tests (#2073) * feat: timestamp types sqlness tests * feat: adds timestamp tests * test: add string tests * test: comment a case in timestamp * test: add float type tests * chore: adds TODO * feat: set TZ=UTC for sqlness test --- .../common/types/{ => blob}/blob.result | 0 .../common/types/{ => blob}/blob.sql | 0 .../common/types/float/infinity.result | 429 ++++++++++++++++++ .../common/types/float/infinity.sql | 129 ++++++ .../standalone/common/types/float/nan.result | 316 +++++++++++++ .../standalone/common/types/float/nan.sql | 124 +++++ .../common/types/float/nan_aggregate.result | 137 ++++++ .../common/types/float/nan_aggregate.sql | 46 ++ .../common/types/float/nan_aggregates.result | 91 ++++ .../common/types/float/nan_aggregates.sql | 29 ++ .../common/types/float/nan_arithmetic.result | 368 +++++++++++++++ .../common/types/float/nan_arithmetic.sql | 108 +++++ .../common/types/float/nan_cast.result | 273 +++++++++++ .../common/types/float/nan_cast.sql | 70 +++ .../common/types/float/nan_join.result | 68 +++ .../common/types/float/nan_join.sql | 39 ++ .../common/types/float/nan_ordering.result | 199 ++++++++ .../common/types/float/nan_ordering.sql | 59 +++ .../common/types/float/nan_window.result | 131 ++++++ .../common/types/float/nan_window.sql | 32 ++ .../common/types/string/bigstring.result | 38 ++ .../common/types/string/bigstring.sql | 17 + .../types/string/scan_big_varchar.result | 232 ++++++++++ .../common/types/string/scan_big_varchar.sql | 90 ++++ .../common/types/string/unicode.result | 68 +++ .../common/types/string/unicode.sql | 23 + .../timestamp/incorrect_timestamp.result | 64 +++ .../types/timestamp/incorrect_timestamp.sql | 31 ++ .../common/types/timestamp/timestamp.result | 177 ++++++++ .../common/types/timestamp/timestamp.sql | 58 +++ .../types/timestamp/timestamp_join.result | 32 ++ .../common/types/timestamp/timestamp_join.sql | 13 + .../types/timestamp/timestamp_limits.result | 81 ++++ .../types/timestamp/timestamp_limits.sql | 49 ++ .../timestamp/timestamp_precision.result | 61 +++ .../types/timestamp/timestamp_precision.sql | 33 ++ .../types/timestamp/timestamp_tz.result | 32 ++ .../common/types/timestamp/timestamp_tz.sql | 7 + tests/runner/src/env.rs | 1 + 39 files changed, 3755 insertions(+) rename tests/cases/standalone/common/types/{ => blob}/blob.result (100%) rename tests/cases/standalone/common/types/{ => blob}/blob.sql (100%) create mode 100644 tests/cases/standalone/common/types/float/infinity.result create mode 100644 tests/cases/standalone/common/types/float/infinity.sql create mode 100644 tests/cases/standalone/common/types/float/nan.result create mode 100644 tests/cases/standalone/common/types/float/nan.sql create mode 100644 tests/cases/standalone/common/types/float/nan_aggregate.result create mode 100644 tests/cases/standalone/common/types/float/nan_aggregate.sql create mode 100644 tests/cases/standalone/common/types/float/nan_aggregates.result create mode 100644 tests/cases/standalone/common/types/float/nan_aggregates.sql create mode 100644 tests/cases/standalone/common/types/float/nan_arithmetic.result create mode 100644 tests/cases/standalone/common/types/float/nan_arithmetic.sql create mode 100644 tests/cases/standalone/common/types/float/nan_cast.result create mode 100644 tests/cases/standalone/common/types/float/nan_cast.sql create mode 100644 tests/cases/standalone/common/types/float/nan_join.result create mode 100644 tests/cases/standalone/common/types/float/nan_join.sql create mode 100644 tests/cases/standalone/common/types/float/nan_ordering.result create mode 100644 tests/cases/standalone/common/types/float/nan_ordering.sql create mode 100644 tests/cases/standalone/common/types/float/nan_window.result create mode 100644 tests/cases/standalone/common/types/float/nan_window.sql create mode 100644 tests/cases/standalone/common/types/string/bigstring.result create mode 100644 tests/cases/standalone/common/types/string/bigstring.sql create mode 100644 tests/cases/standalone/common/types/string/scan_big_varchar.result create mode 100644 tests/cases/standalone/common/types/string/scan_big_varchar.sql create mode 100644 tests/cases/standalone/common/types/string/unicode.result create mode 100644 tests/cases/standalone/common/types/string/unicode.sql create mode 100644 tests/cases/standalone/common/types/timestamp/incorrect_timestamp.result create mode 100644 tests/cases/standalone/common/types/timestamp/incorrect_timestamp.sql create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp.result create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp.sql create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_join.result create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_join.sql create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_limits.result create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_limits.sql create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_precision.result create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_precision.sql create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_tz.result create mode 100644 tests/cases/standalone/common/types/timestamp/timestamp_tz.sql diff --git a/tests/cases/standalone/common/types/blob.result b/tests/cases/standalone/common/types/blob/blob.result similarity index 100% rename from tests/cases/standalone/common/types/blob.result rename to tests/cases/standalone/common/types/blob/blob.result diff --git a/tests/cases/standalone/common/types/blob.sql b/tests/cases/standalone/common/types/blob/blob.sql similarity index 100% rename from tests/cases/standalone/common/types/blob.sql rename to tests/cases/standalone/common/types/blob/blob.sql diff --git a/tests/cases/standalone/common/types/float/infinity.result b/tests/cases/standalone/common/types/float/infinity.result new file mode 100644 index 0000000000..06102ca2cc --- /dev/null +++ b/tests/cases/standalone/common/types/float/infinity.result @@ -0,0 +1,429 @@ +-- description: Test usage of the INF value +-- FLOAT type +-- inf as a constant +SELECT 'INF'::FLOAT, '-INF'::FLOAT; + ++-------------+--------------+ +| Utf8("INF") | Utf8("-INF") | ++-------------+--------------+ +| inf | -inf | ++-------------+--------------+ + +-- inf comparison +SELECT 'inf'::FLOAT = 'inf'::FLOAT; + ++---------------------------+ +| Utf8("inf") = Utf8("inf") | ++---------------------------+ +| true | ++---------------------------+ + +SELECT 'inf'::FLOAT <> 'inf'::FLOAT; + ++----------------------------+ +| Utf8("inf") != Utf8("inf") | ++----------------------------+ +| false | ++----------------------------+ + +SELECT 'inf'::FLOAT <> 3.0::FLOAT; + ++---------------------------+ +| Utf8("inf") != Float64(3) | ++---------------------------+ +| true | ++---------------------------+ + +-- storing inf in a table +CREATE TABLE floats(f FLOAT PRIMARY KEY, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('INF'::FLOAT, 1), (1::FLOAT, 2), ('-INF'::FLOAT, 3); + +Affected Rows: 3 + +SELECT * FROM floats; + ++------+-------------------------+ +| f | ts | ++------+-------------------------+ +| -inf | 1970-01-01T00:00:00.003 | +| 1.0 | 1970-01-01T00:00:00.002 | +| inf | 1970-01-01T00:00:00.001 | ++------+-------------------------+ + +-- table filters on inf +-- = +SELECT f FROM floats WHERE f=1; + ++-----+ +| f | ++-----+ +| 1.0 | ++-----+ + +SELECT f FROM floats WHERE f='inf'::FLOAT; + ++-----+ +| f | ++-----+ +| inf | ++-----+ + +SELECT f FROM floats WHERE f='-inf'::FLOAT; + ++------+ +| f | ++------+ +| -inf | ++------+ + +-- <> +SELECT f FROM floats WHERE f<>1 ORDER BY 1; + ++------+ +| f | ++------+ +| -inf | +| inf | ++------+ + +SELECT f FROM floats WHERE f<>'inf'::FLOAT ORDER BY 1; + ++------+ +| f | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT f FROM floats WHERE f<>'-inf'::FLOAT ORDER BY 1; + ++-----+ +| f | ++-----+ +| 1.0 | +| inf | ++-----+ + +-- > +SELECT f FROM floats WHERE f>1 ORDER BY 1; + ++-----+ +| f | ++-----+ +| inf | ++-----+ + +SELECT f FROM floats WHERE f>'-inf'::FLOAT ORDER BY 1; + ++-----+ +| f | ++-----+ +| 1.0 | +| inf | ++-----+ + +SELECT f FROM floats WHERE f>'inf'::FLOAT; + +++ +++ + +-- >= +SELECT f FROM floats WHERE f>=1 ORDER BY f; + ++-----+ +| f | ++-----+ +| 1.0 | +| inf | ++-----+ + +SELECT f FROM floats WHERE f>='-inf'::FLOAT ORDER BY f; + ++------+ +| f | ++------+ +| -inf | +| 1.0 | +| inf | ++------+ + +SELECT f FROM floats WHERE f>='inf'::FLOAT ORDER BY f; + ++-----+ +| f | ++-----+ +| inf | ++-----+ + +-- < +SELECT f FROM floats WHERE f<1; + ++------+ +| f | ++------+ +| -inf | ++------+ + +SELECT f FROM floats WHERE f<'inf'::FLOAT ORDER BY f; + ++------+ +| f | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT f FROM floats WHERE f<'-inf'::FLOAT; + +++ +++ + +-- <= +SELECT f FROM floats WHERE f<=1 ORDER BY f; + ++------+ +| f | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT f FROM floats WHERE f<='inf'::FLOAT ORDER BY f; + ++------+ +| f | ++------+ +| -inf | +| 1.0 | +| inf | ++------+ + +SELECT f FROM floats WHERE f<='-inf'::FLOAT ORDER BY f; + ++------+ +| f | ++------+ +| -inf | ++------+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- DOUBLE type +-- inf as a constant +SELECT 'INF'::DOUBLE, '-INF'::DOUBLE; + ++-------------+--------------+ +| Utf8("INF") | Utf8("-INF") | ++-------------+--------------+ +| inf | -inf | ++-------------+--------------+ + +-- inf comparison +SELECT 'inf'::DOUBLE = 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("inf") = Utf8("inf") | ++---------------------------+ +| true | ++---------------------------+ + +SELECT 'inf'::DOUBLE <> 'inf'::DOUBLE; + ++----------------------------+ +| Utf8("inf") != Utf8("inf") | ++----------------------------+ +| false | ++----------------------------+ + +SELECT 'inf'::DOUBLE <> 3.0::DOUBLE; + ++---------------------------+ +| Utf8("inf") != Float64(3) | ++---------------------------+ +| true | ++---------------------------+ + +-- storing inf in a table +CREATE TABLE doubles(d DOUBLE PRIMARY KEY, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('INF'::DOUBLE, 1), (1::DOUBLE, 2), ('-INF'::DOUBLE, 3); + +Affected Rows: 3 + +SELECT * FROM doubles; + ++------+-------------------------+ +| d | ts | ++------+-------------------------+ +| -inf | 1970-01-01T00:00:00.003 | +| 1.0 | 1970-01-01T00:00:00.002 | +| inf | 1970-01-01T00:00:00.001 | ++------+-------------------------+ + +-- table filters on inf +-- = +SELECT d FROM doubles WHERE d=1; + ++-----+ +| d | ++-----+ +| 1.0 | ++-----+ + +SELECT d FROM doubles WHERE d='inf'::DOUBLE; + ++-----+ +| d | ++-----+ +| inf | ++-----+ + +SELECT d FROM doubles WHERE d='-inf'::DOUBLE; + ++------+ +| d | ++------+ +| -inf | ++------+ + +-- <> +SELECT d FROM doubles WHERE d<>1 ORDER BY 1; + ++------+ +| d | ++------+ +| -inf | +| inf | ++------+ + +SELECT d FROM doubles WHERE d<>'inf'::DOUBLE ORDER BY 1; + ++------+ +| d | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT d FROM doubles WHERE d<>'-inf'::DOUBLE ORDER BY 1; + ++-----+ +| d | ++-----+ +| 1.0 | +| inf | ++-----+ + +-- > +SELECT d FROM doubles WHERE d>1 ORDER BY 1; + ++-----+ +| d | ++-----+ +| inf | ++-----+ + +SELECT d FROM doubles WHERE d>'-inf'::DOUBLE ORDER BY 1; + ++-----+ +| d | ++-----+ +| 1.0 | +| inf | ++-----+ + +SELECT d FROM doubles WHERE d>'inf'::DOUBLE; + +++ +++ + +-- >= +SELECT d FROM doubles WHERE d>=1 ORDER BY d; + ++-----+ +| d | ++-----+ +| 1.0 | +| inf | ++-----+ + +SELECT d FROM doubles WHERE d>='-inf'::DOUBLE ORDER BY d; + ++------+ +| d | ++------+ +| -inf | +| 1.0 | +| inf | ++------+ + +SELECT d FROM doubles WHERE d>='inf'::DOUBLE ORDER BY d; + ++-----+ +| d | ++-----+ +| inf | ++-----+ + +-- < +SELECT d FROM doubles WHERE d<1; + ++------+ +| d | ++------+ +| -inf | ++------+ + +SELECT d FROM doubles WHERE d<'inf'::DOUBLE ORDER BY d; + ++------+ +| d | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT d FROM doubles WHERE d<'-inf'::DOUBLE; + +++ +++ + +-- <= +SELECT d FROM doubles WHERE d<=1 ORDER BY d; + ++------+ +| d | ++------+ +| -inf | +| 1.0 | ++------+ + +SELECT d FROM doubles WHERE d<='inf'::DOUBLE ORDER BY d; + ++------+ +| d | ++------+ +| -inf | +| 1.0 | +| inf | ++------+ + +SELECT d FROM doubles WHERE d<='-inf'::DOUBLE ORDER BY d; + ++------+ +| d | ++------+ +| -inf | ++------+ + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/infinity.sql b/tests/cases/standalone/common/types/float/infinity.sql new file mode 100644 index 0000000000..a8b3c1e77c --- /dev/null +++ b/tests/cases/standalone/common/types/float/infinity.sql @@ -0,0 +1,129 @@ +-- description: Test usage of the INF value +-- FLOAT type + +-- inf as a constant +SELECT 'INF'::FLOAT, '-INF'::FLOAT; + +-- inf comparison +SELECT 'inf'::FLOAT = 'inf'::FLOAT; + +SELECT 'inf'::FLOAT <> 'inf'::FLOAT; + +SELECT 'inf'::FLOAT <> 3.0::FLOAT; + +-- storing inf in a table +CREATE TABLE floats(f FLOAT PRIMARY KEY, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('INF'::FLOAT, 1), (1::FLOAT, 2), ('-INF'::FLOAT, 3); + +SELECT * FROM floats; + +-- table filters on inf +-- = +SELECT f FROM floats WHERE f=1; + +SELECT f FROM floats WHERE f='inf'::FLOAT; + +SELECT f FROM floats WHERE f='-inf'::FLOAT; + +-- <> +SELECT f FROM floats WHERE f<>1 ORDER BY 1; + +SELECT f FROM floats WHERE f<>'inf'::FLOAT ORDER BY 1; + +SELECT f FROM floats WHERE f<>'-inf'::FLOAT ORDER BY 1; + +-- > +SELECT f FROM floats WHERE f>1 ORDER BY 1; + +SELECT f FROM floats WHERE f>'-inf'::FLOAT ORDER BY 1; + +SELECT f FROM floats WHERE f>'inf'::FLOAT; + +-- >= +SELECT f FROM floats WHERE f>=1 ORDER BY f; + +SELECT f FROM floats WHERE f>='-inf'::FLOAT ORDER BY f; + +SELECT f FROM floats WHERE f>='inf'::FLOAT ORDER BY f; + +-- < +SELECT f FROM floats WHERE f<1; + +SELECT f FROM floats WHERE f<'inf'::FLOAT ORDER BY f; + +SELECT f FROM floats WHERE f<'-inf'::FLOAT; + +-- <= +SELECT f FROM floats WHERE f<=1 ORDER BY f; + +SELECT f FROM floats WHERE f<='inf'::FLOAT ORDER BY f; + +SELECT f FROM floats WHERE f<='-inf'::FLOAT ORDER BY f; + +DROP TABLE floats; + + +-- DOUBLE type + +-- inf as a constant +SELECT 'INF'::DOUBLE, '-INF'::DOUBLE; + +-- inf comparison +SELECT 'inf'::DOUBLE = 'inf'::DOUBLE; + +SELECT 'inf'::DOUBLE <> 'inf'::DOUBLE; + +SELECT 'inf'::DOUBLE <> 3.0::DOUBLE; + +-- storing inf in a table +CREATE TABLE doubles(d DOUBLE PRIMARY KEY, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('INF'::DOUBLE, 1), (1::DOUBLE, 2), ('-INF'::DOUBLE, 3); + +SELECT * FROM doubles; + +-- table filters on inf +-- = +SELECT d FROM doubles WHERE d=1; + +SELECT d FROM doubles WHERE d='inf'::DOUBLE; + +SELECT d FROM doubles WHERE d='-inf'::DOUBLE; + +-- <> +SELECT d FROM doubles WHERE d<>1 ORDER BY 1; + +SELECT d FROM doubles WHERE d<>'inf'::DOUBLE ORDER BY 1; + +SELECT d FROM doubles WHERE d<>'-inf'::DOUBLE ORDER BY 1; + +-- > +SELECT d FROM doubles WHERE d>1 ORDER BY 1; + +SELECT d FROM doubles WHERE d>'-inf'::DOUBLE ORDER BY 1; + +SELECT d FROM doubles WHERE d>'inf'::DOUBLE; + +-- >= +SELECT d FROM doubles WHERE d>=1 ORDER BY d; + +SELECT d FROM doubles WHERE d>='-inf'::DOUBLE ORDER BY d; + +SELECT d FROM doubles WHERE d>='inf'::DOUBLE ORDER BY d; + +-- < +SELECT d FROM doubles WHERE d<1; + +SELECT d FROM doubles WHERE d<'inf'::DOUBLE ORDER BY d; + +SELECT d FROM doubles WHERE d<'-inf'::DOUBLE; + +-- <= +SELECT d FROM doubles WHERE d<=1 ORDER BY d; + +SELECT d FROM doubles WHERE d<='inf'::DOUBLE ORDER BY d; + +SELECT d FROM doubles WHERE d<='-inf'::DOUBLE ORDER BY d; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/float/nan.result b/tests/cases/standalone/common/types/float/nan.result new file mode 100644 index 0000000000..ab68884be7 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan.result @@ -0,0 +1,316 @@ +-- description: Test usage of the NAN value +-- FLOAT type +-- nan as a constant +SELECT 'NAN'::FLOAT; + ++-------------+ +| Utf8("NAN") | ++-------------+ +| NaN | ++-------------+ + +-- storing nan in a table +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('NAN'::FLOAT, 1), (1::FLOAT, 2); + +Affected Rows: 2 + +SELECT * FROM floats; + ++-----+-------------------------+ +| f | ts | ++-----+-------------------------+ +| NaN | 1970-01-01T00:00:00.001 | +| 1.0 | 1970-01-01T00:00:00.002 | ++-----+-------------------------+ + +-- nan comparison +-- Note, NaN is equals to itself in datafusion and greater than other float or double values. +SELECT 'nan'::FLOAT = 'nan'::FLOAT; + ++---------------------------+ +| Utf8("nan") = Utf8("nan") | ++---------------------------+ +| true | ++---------------------------+ + +SELECT 'nan'::FLOAT <> 'nan'::FLOAT; + ++----------------------------+ +| Utf8("nan") != Utf8("nan") | ++----------------------------+ +| false | ++----------------------------+ + +SELECT 'nan'::FLOAT <> 3.0::FLOAT; + ++---------------------------+ +| Utf8("nan") != Float64(3) | ++---------------------------+ +| true | ++---------------------------+ + +-- table filters on nan +-- = +SELECT f FROM floats WHERE f=1; + ++-----+ +| f | ++-----+ +| 1.0 | ++-----+ + +SELECT f FROM floats WHERE f='nan'::FLOAT; + ++-----+ +| f | ++-----+ +| NaN | ++-----+ + +-- <> +SELECT f FROM floats WHERE f<>1; + ++-----+ +| f | ++-----+ +| NaN | ++-----+ + +SELECT f FROM floats WHERE f<>'nan'::FLOAT; + ++-----+ +| f | ++-----+ +| 1.0 | ++-----+ + +-- > +SELECT f FROM floats WHERE f>0; + ++-----+ +| f | ++-----+ +| NaN | +| 1.0 | ++-----+ + +SELECT f FROM floats WHERE f>'nan'::FLOAT; + +++ +++ + +-- >= +SELECT f FROM floats WHERE f>=1; + ++-----+ +| f | ++-----+ +| NaN | +| 1.0 | ++-----+ + +SELECT f FROM floats WHERE f>='nan'::FLOAT; + ++-----+ +| f | ++-----+ +| NaN | ++-----+ + +-- < +SELECT f FROM floats WHERE f<1; + +++ +++ + +SELECT f FROM floats WHERE f<'nan'::FLOAT; + ++-----+ +| f | ++-----+ +| 1.0 | ++-----+ + +-- <= +SELECT f FROM floats WHERE f<=1; + ++-----+ +| f | ++-----+ +| 1.0 | ++-----+ + +SELECT f FROM floats WHERE f<='nan'::FLOAT; + ++-----+ +| f | ++-----+ +| NaN | +| 1.0 | ++-----+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- DOUBLE type +-- nan as a constant +SELECT 'NAN'::DOUBLE; + ++-------------+ +| Utf8("NAN") | ++-------------+ +| NaN | ++-------------+ + +-- storing nan in a table +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('NAN'::DOUBLE, 1), (1::DOUBLE, 2); + +Affected Rows: 2 + +SELECT * FROM doubles; + ++-----+-------------------------+ +| d | ts | ++-----+-------------------------+ +| NaN | 1970-01-01T00:00:00.001 | +| 1.0 | 1970-01-01T00:00:00.002 | ++-----+-------------------------+ + +-- nan comparison +SELECT 'nan'::DOUBLE = 'nan'::DOUBLE; + ++---------------------------+ +| Utf8("nan") = Utf8("nan") | ++---------------------------+ +| true | ++---------------------------+ + +SELECT 'nan'::DOUBLE <> 'nan'::DOUBLE; + ++----------------------------+ +| Utf8("nan") != Utf8("nan") | ++----------------------------+ +| false | ++----------------------------+ + +SELECT 'nan'::DOUBLE <> 3.0::DOUBLE; + ++---------------------------+ +| Utf8("nan") != Float64(3) | ++---------------------------+ +| true | ++---------------------------+ + +-- table filters on nan +-- = +SELECT d FROM doubles WHERE d=1; + ++-----+ +| d | ++-----+ +| 1.0 | ++-----+ + +SELECT d FROM doubles WHERE d='nan'::DOUBLE; + ++-----+ +| d | ++-----+ +| NaN | ++-----+ + +-- <> +SELECT d FROM doubles WHERE d<>1; + ++-----+ +| d | ++-----+ +| NaN | ++-----+ + +SELECT d FROM doubles WHERE d<>'nan'::DOUBLE; + ++-----+ +| d | ++-----+ +| 1.0 | ++-----+ + +-- > +SELECT d FROM doubles WHERE d>0; + ++-----+ +| d | ++-----+ +| NaN | +| 1.0 | ++-----+ + +SELECT d FROM doubles WHERE d>'nan'::DOUBLE; + +++ +++ + +-- >= +SELECT d FROM doubles WHERE d>=1; + ++-----+ +| d | ++-----+ +| NaN | +| 1.0 | ++-----+ + +SELECT d FROM doubles WHERE d>='nan'::DOUBLE; + ++-----+ +| d | ++-----+ +| NaN | ++-----+ + +-- < +SELECT d FROM doubles WHERE d<1; + +++ +++ + +SELECT d FROM doubles WHERE d<'nan'::DOUBLE; + ++-----+ +| d | ++-----+ +| 1.0 | ++-----+ + +-- <= +SELECT d FROM doubles WHERE d<=1; + ++-----+ +| d | ++-----+ +| 1.0 | ++-----+ + +SELECT d FROM doubles WHERE d<='nan'::DOUBLE; + ++-----+ +| d | ++-----+ +| NaN | +| 1.0 | ++-----+ + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan.sql b/tests/cases/standalone/common/types/float/nan.sql new file mode 100644 index 0000000000..02e461e3a9 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan.sql @@ -0,0 +1,124 @@ +-- description: Test usage of the NAN value + +-- FLOAT type + +-- nan as a constant + +SELECT 'NAN'::FLOAT; + +-- storing nan in a table + +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('NAN'::FLOAT, 1), (1::FLOAT, 2); + +SELECT * FROM floats; + +-- nan comparison +-- Note, NaN is equals to itself in datafusion and greater than other float or double values. +SELECT 'nan'::FLOAT = 'nan'::FLOAT; + +SELECT 'nan'::FLOAT <> 'nan'::FLOAT; + +SELECT 'nan'::FLOAT <> 3.0::FLOAT; + +-- table filters on nan +-- = + +SELECT f FROM floats WHERE f=1; + +SELECT f FROM floats WHERE f='nan'::FLOAT; + +-- <> + +SELECT f FROM floats WHERE f<>1; + +SELECT f FROM floats WHERE f<>'nan'::FLOAT; + +-- > + +SELECT f FROM floats WHERE f>0; + +SELECT f FROM floats WHERE f>'nan'::FLOAT; + +-- >= + +SELECT f FROM floats WHERE f>=1; + +SELECT f FROM floats WHERE f>='nan'::FLOAT; + +-- < + +SELECT f FROM floats WHERE f<1; + +SELECT f FROM floats WHERE f<'nan'::FLOAT; + +-- <= + +SELECT f FROM floats WHERE f<=1; + +SELECT f FROM floats WHERE f<='nan'::FLOAT; + +DROP TABLE floats; + + +-- DOUBLE type + +-- nan as a constant + +SELECT 'NAN'::DOUBLE; + +-- storing nan in a table + +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('NAN'::DOUBLE, 1), (1::DOUBLE, 2); + +SELECT * FROM doubles; + +-- nan comparison + +SELECT 'nan'::DOUBLE = 'nan'::DOUBLE; + +SELECT 'nan'::DOUBLE <> 'nan'::DOUBLE; + +SELECT 'nan'::DOUBLE <> 3.0::DOUBLE; + +-- table filters on nan +-- = + +SELECT d FROM doubles WHERE d=1; + +SELECT d FROM doubles WHERE d='nan'::DOUBLE; + +-- <> + +SELECT d FROM doubles WHERE d<>1; + +SELECT d FROM doubles WHERE d<>'nan'::DOUBLE; + +-- > + +SELECT d FROM doubles WHERE d>0; + +SELECT d FROM doubles WHERE d>'nan'::DOUBLE; + +-- >= + +SELECT d FROM doubles WHERE d>=1; + +SELECT d FROM doubles WHERE d>='nan'::DOUBLE; + +-- < + +SELECT d FROM doubles WHERE d<1; + +SELECT d FROM doubles WHERE d<'nan'::DOUBLE; + +-- <= + +SELECT d FROM doubles WHERE d<=1; + +SELECT d FROM doubles WHERE d<='nan'::DOUBLE; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/float/nan_aggregate.result b/tests/cases/standalone/common/types/float/nan_aggregate.result new file mode 100644 index 0000000000..f95cda7b02 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_aggregate.result @@ -0,0 +1,137 @@ +-- description: Test NaN and inf as aggregate groups +-- float +CREATE TABLE floats(f FLOAT, i INT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('inf'::FLOAT, 1, 2), ('inf'::FLOAT, 7, 3), ('-inf'::FLOAT, 3, 4), ('nan'::FLOAT, 7, 5), ('nan'::FLOAT, 19, 6), ('-inf'::FLOAT, 2, 7); + +Affected Rows: 6 + +SELECT f, SUM(i) FROM floats GROUP BY f ORDER BY f; + ++------+---------------+ +| f | SUM(floats.i) | ++------+---------------+ +| -inf | 5 | +| inf | 8 | +| NaN | 26 | ++------+---------------+ + +SELECT SUM(f) FROM floats WHERE f > 0 AND f != 'nan'::FLOAT; + ++---------------+ +| SUM(floats.f) | ++---------------+ +| inf | ++---------------+ + +SELECT SUM(f) FROM floats WHERE f < 0; + ++---------------+ +| SUM(floats.f) | ++---------------+ +| -inf | ++---------------+ + +SELECT SUM(f) FROM floats; + ++---------------+ +| SUM(floats.f) | ++---------------+ +| NaN | ++---------------+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- double +CREATE TABLE doubles(f DOUBLE, i INT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1, 2), ('inf'::DOUBLE, 7, 3), ('-inf'::DOUBLE, 3, 4), ('nan'::DOUBLE, 7, 5), ('nan'::DOUBLE, 19, 6), ('-inf'::DOUBLE, 2, 7); + +Affected Rows: 6 + +SELECT f, SUM(i) FROM doubles GROUP BY f ORDER BY f; + ++------+----------------+ +| f | SUM(doubles.i) | ++------+----------------+ +| -inf | 5 | +| inf | 8 | +| NaN | 26 | ++------+----------------+ + +SELECT SUM(f) FROM doubles WHERE f > 0 AND f != 'nan'::DOUBLE; + ++----------------+ +| SUM(doubles.f) | ++----------------+ +| inf | ++----------------+ + +SELECT SUM(f) FROM doubles WHERE f < 0; + ++----------------+ +| SUM(doubles.f) | ++----------------+ +| -inf | ++----------------+ + +SELECT SUM(f) FROM doubles; + ++----------------+ +| SUM(doubles.f) | ++----------------+ +| NaN | ++----------------+ + +DROP TABLE doubles; + +Affected Rows: 1 + +-- float double +CREATE TABLE floats_doubles (f FLOAT, d DOUBLE, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats_doubles VALUES (2e38, 1e308, 1), (2e38, 1e308, 2), (-1e38, 0, 3), (-1e38, 0, 4); + +Affected Rows: 4 + +SELECT * FROM floats_doubles; + ++---------+---------+-------------------------+ +| f | d | ts | ++---------+---------+-------------------------+ +| 2.0e38 | 1.0e308 | 1970-01-01T00:00:00.001 | +| 2.0e38 | 1.0e308 | 1970-01-01T00:00:00.002 | +| -1.0e38 | 0.0 | 1970-01-01T00:00:00.003 | +| -1.0e38 | 0.0 | 1970-01-01T00:00:00.004 | ++---------+---------+-------------------------+ + +-- not out of range -- +SELECT SUM(f) FROM floats_doubles WHERE f > 0; + ++-----------------------+ +| SUM(floats_doubles.f) | ++-----------------------+ +| 3.999999872114277e38 | ++-----------------------+ + +-- not out of range, but INF -- +SELECT SUM(d) FROM floats_doubles WHERE d > 0; + ++-----------------------+ +| SUM(floats_doubles.d) | ++-----------------------+ +| inf | ++-----------------------+ + +DROP TABLE floats_doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan_aggregate.sql b/tests/cases/standalone/common/types/float/nan_aggregate.sql new file mode 100644 index 0000000000..aae36c9da4 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_aggregate.sql @@ -0,0 +1,46 @@ +-- description: Test NaN and inf as aggregate groups + +-- float +CREATE TABLE floats(f FLOAT, i INT, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('inf'::FLOAT, 1, 2), ('inf'::FLOAT, 7, 3), ('-inf'::FLOAT, 3, 4), ('nan'::FLOAT, 7, 5), ('nan'::FLOAT, 19, 6), ('-inf'::FLOAT, 2, 7); + +SELECT f, SUM(i) FROM floats GROUP BY f ORDER BY f; + +SELECT SUM(f) FROM floats WHERE f > 0 AND f != 'nan'::FLOAT; + +SELECT SUM(f) FROM floats WHERE f < 0; + +SELECT SUM(f) FROM floats; + +DROP TABLE floats; + +-- double +CREATE TABLE doubles(f DOUBLE, i INT, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1, 2), ('inf'::DOUBLE, 7, 3), ('-inf'::DOUBLE, 3, 4), ('nan'::DOUBLE, 7, 5), ('nan'::DOUBLE, 19, 6), ('-inf'::DOUBLE, 2, 7); + +SELECT f, SUM(i) FROM doubles GROUP BY f ORDER BY f; + +SELECT SUM(f) FROM doubles WHERE f > 0 AND f != 'nan'::DOUBLE; + +SELECT SUM(f) FROM doubles WHERE f < 0; + +SELECT SUM(f) FROM doubles; + +DROP TABLE doubles; + +-- float double +CREATE TABLE floats_doubles (f FLOAT, d DOUBLE, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats_doubles VALUES (2e38, 1e308, 1), (2e38, 1e308, 2), (-1e38, 0, 3), (-1e38, 0, 4); + +SELECT * FROM floats_doubles; + +-- not out of range -- +SELECT SUM(f) FROM floats_doubles WHERE f > 0; + +-- not out of range, but INF -- +SELECT SUM(d) FROM floats_doubles WHERE d > 0; + +DROP TABLE floats_doubles; diff --git a/tests/cases/standalone/common/types/float/nan_aggregates.result b/tests/cases/standalone/common/types/float/nan_aggregates.result new file mode 100644 index 0000000000..69249efddb --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_aggregates.result @@ -0,0 +1,91 @@ +-- description: Test aggregates on NaN values +-- float -- +SELECT SUM('inf'::FLOAT), SUM('-inf'::FLOAT), SUM('nan'::FLOAT); + ++------------------+-------------------+------------------+ +| SUM(Utf8("inf")) | SUM(Utf8("-inf")) | SUM(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +SELECT MIN('inf'::FLOAT), MIN('-inf'::FLOAT), MIN('nan'::FLOAT); + ++------------------+-------------------+------------------+ +| MIN(Utf8("inf")) | MIN(Utf8("-inf")) | MIN(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +SELECT MAX('inf'::FLOAT), MAX('-inf'::FLOAT), MAX('nan'::FLOAT); + ++------------------+-------------------+------------------+ +| MAX(Utf8("inf")) | MAX(Utf8("-inf")) | MAX(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('inf'::FLOAT, 1), ('-inf'::FLOAT, 2), ('nan'::FLOAT, 3); + +Affected Rows: 3 + +SELECT MIN(f), MAX(f) FROM floats; + ++---------------+---------------+ +| MIN(floats.f) | MAX(floats.f) | ++---------------+---------------+ +| -inf | NaN | ++---------------+---------------+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- double -- +SELECT SUM('inf'::DOUBLE), SUM('-inf'::DOUBLE), SUM('nan'::DOUBLE); + ++------------------+-------------------+------------------+ +| SUM(Utf8("inf")) | SUM(Utf8("-inf")) | SUM(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +SELECT MIN('inf'::DOUBLE), MIN('-inf'::DOUBLE), MIN('nan'::DOUBLE); + ++------------------+-------------------+------------------+ +| MIN(Utf8("inf")) | MIN(Utf8("-inf")) | MIN(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +SELECT MAX('inf'::DOUBLE), MAX('-inf'::DOUBLE), MAX('nan'::DOUBLE); + ++------------------+-------------------+------------------+ +| MAX(Utf8("inf")) | MAX(Utf8("-inf")) | MAX(Utf8("nan")) | ++------------------+-------------------+------------------+ +| inf | -inf | NaN | ++------------------+-------------------+------------------+ + +CREATE TABLE doubles(f DOUBLE, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1), ('-inf'::DOUBLE, 2), ('nan'::DOUBLE, 3); + +Affected Rows: 3 + +SELECT MIN(f), MAX(f) FROM doubles; + ++----------------+----------------+ +| MIN(doubles.f) | MAX(doubles.f) | ++----------------+----------------+ +| -inf | NaN | ++----------------+----------------+ + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan_aggregates.sql b/tests/cases/standalone/common/types/float/nan_aggregates.sql new file mode 100644 index 0000000000..e507aa38a3 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_aggregates.sql @@ -0,0 +1,29 @@ +-- description: Test aggregates on NaN values + +-- float -- +SELECT SUM('inf'::FLOAT), SUM('-inf'::FLOAT), SUM('nan'::FLOAT); + +SELECT MIN('inf'::FLOAT), MIN('-inf'::FLOAT), MIN('nan'::FLOAT); + +SELECT MAX('inf'::FLOAT), MAX('-inf'::FLOAT), MAX('nan'::FLOAT); + +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); +INSERT INTO floats VALUES ('inf'::FLOAT, 1), ('-inf'::FLOAT, 2), ('nan'::FLOAT, 3); + +SELECT MIN(f), MAX(f) FROM floats; + +DROP TABLE floats; + +-- double -- +SELECT SUM('inf'::DOUBLE), SUM('-inf'::DOUBLE), SUM('nan'::DOUBLE); + +SELECT MIN('inf'::DOUBLE), MIN('-inf'::DOUBLE), MIN('nan'::DOUBLE); + +SELECT MAX('inf'::DOUBLE), MAX('-inf'::DOUBLE), MAX('nan'::DOUBLE); + +CREATE TABLE doubles(f DOUBLE, ts TIMESTAMP TIME INDEX); +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1), ('-inf'::DOUBLE, 2), ('nan'::DOUBLE, 3); + +SELECT MIN(f), MAX(f) FROM doubles; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/float/nan_arithmetic.result b/tests/cases/standalone/common/types/float/nan_arithmetic.result new file mode 100644 index 0000000000..165c286cae --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_arithmetic.result @@ -0,0 +1,368 @@ +-- FLOAT type +-- any arithmetic on a nan value will result in a nan value +SELECT 'nan'::FLOAT + 1; + ++------------------------+ +| Utf8("nan") + Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::FLOAT + 'inf'::FLOAT; + ++---------------------------+ +| Utf8("nan") + Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::FLOAT - 1; + ++------------------------+ +| Utf8("nan") - Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::FLOAT - 'inf'::FLOAT; + ++---------------------------+ +| Utf8("nan") - Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::FLOAT * 1; + ++------------------------+ +| Utf8("nan") * Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::FLOAT * 'inf'::FLOAT; + ++---------------------------+ +| Utf8("nan") * Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::FLOAT / 1; + ++------------------------+ +| Utf8("nan") / Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::FLOAT / 'inf'::FLOAT; + ++---------------------------+ +| Utf8("nan") / Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::FLOAT % 1; + ++------------------------+ +| Utf8("nan") % Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::FLOAT % 'inf'::FLOAT; + ++---------------------------+ +| Utf8("nan") % Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT -('nan'::FLOAT); + ++-----------------+ +| (- Utf8("nan")) | ++-----------------+ +| NaN | ++-----------------+ + +-- DOUBLE type +-- any arithmetic on a nan value will result in a nan value +SELECT 'nan'::DOUBLE + 1; + ++------------------------+ +| Utf8("nan") + Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::DOUBLE + 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("nan") + Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::DOUBLE - 1; + ++------------------------+ +| Utf8("nan") - Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::DOUBLE - 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("nan") - Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::DOUBLE * 1; + ++------------------------+ +| Utf8("nan") * Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::DOUBLE * 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("nan") * Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::DOUBLE / 1; + ++------------------------+ +| Utf8("nan") / Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::DOUBLE / 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("nan") / Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'nan'::DOUBLE % 1; + ++------------------------+ +| Utf8("nan") % Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 'nan'::DOUBLE % 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("nan") % Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT -('nan'::DOUBLE); + ++-----------------+ +| (- Utf8("nan")) | ++-----------------+ +| NaN | ++-----------------+ + +-- FLOAT type +-- any arithmetic on a nan value will result in a nan value +SELECT 'inf'::FLOAT + 1; + ++------------------------+ +| Utf8("inf") + Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf + inf = inf +SELECT 'inf'::FLOAT + 'inf'::FLOAT; + ++---------------------------+ +| Utf8("inf") + Utf8("inf") | ++---------------------------+ +| inf | ++---------------------------+ + +SELECT 'inf'::FLOAT - 1; + ++------------------------+ +| Utf8("inf") - Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf - inf = nan +SELECT 'inf'::FLOAT - 'inf'::FLOAT; + ++---------------------------+ +| Utf8("inf") - Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'inf'::FLOAT * 1; + ++------------------------+ +| Utf8("inf") * Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf * inf = inf +SELECT 'inf'::FLOAT * 'inf'::FLOAT; + ++---------------------------+ +| Utf8("inf") * Utf8("inf") | ++---------------------------+ +| inf | ++---------------------------+ + +-- inf * -inf = -inf +SELECT 'inf'::FLOAT * '-inf'::FLOAT; + ++----------------------------+ +| Utf8("inf") * Utf8("-inf") | ++----------------------------+ +| -inf | ++----------------------------+ + +SELECT 'inf'::FLOAT / 1; + ++------------------------+ +| Utf8("inf") / Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +SELECT 1 / 'inf'::FLOAT; + ++------------------------+ +| Int64(1) / Utf8("inf") | ++------------------------+ +| 0.0 | ++------------------------+ + +SELECT 'inf'::FLOAT % 1; + ++------------------------+ +| Utf8("inf") % Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 1 % 'inf'::FLOAT; + ++------------------------+ +| Int64(1) % Utf8("inf") | ++------------------------+ +| 1.0 | ++------------------------+ + +-- DOUBLE type +-- any arithmetic on a nan value will result in a nan value +SELECT 'inf'::DOUBLE + 1; + ++------------------------+ +| Utf8("inf") + Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf + inf = inf +SELECT 'inf'::DOUBLE + 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("inf") + Utf8("inf") | ++---------------------------+ +| inf | ++---------------------------+ + +SELECT 'inf'::DOUBLE - 1; + ++------------------------+ +| Utf8("inf") - Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf - inf = nan +SELECT 'inf'::DOUBLE - 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("inf") - Utf8("inf") | ++---------------------------+ +| NaN | ++---------------------------+ + +SELECT 'inf'::DOUBLE * 1; + ++------------------------+ +| Utf8("inf") * Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +-- inf * inf = inf +SELECT 'inf'::DOUBLE * 'inf'::DOUBLE; + ++---------------------------+ +| Utf8("inf") * Utf8("inf") | ++---------------------------+ +| inf | ++---------------------------+ + +-- inf * -inf = -inf +SELECT 'inf'::DOUBLE * '-inf'::DOUBLE; + ++----------------------------+ +| Utf8("inf") * Utf8("-inf") | ++----------------------------+ +| -inf | ++----------------------------+ + +SELECT 'inf'::DOUBLE / 1; + ++------------------------+ +| Utf8("inf") / Int64(1) | ++------------------------+ +| inf | ++------------------------+ + +SELECT 1 / 'inf'::DOUBLE; + ++------------------------+ +| Int64(1) / Utf8("inf") | ++------------------------+ +| 0.0 | ++------------------------+ + +SELECT 'inf'::DOUBLE % 1; + ++------------------------+ +| Utf8("inf") % Int64(1) | ++------------------------+ +| NaN | ++------------------------+ + +SELECT 1 % 'inf'::DOUBLE; + ++------------------------+ +| Int64(1) % Utf8("inf") | ++------------------------+ +| 1.0 | ++------------------------+ + diff --git a/tests/cases/standalone/common/types/float/nan_arithmetic.sql b/tests/cases/standalone/common/types/float/nan_arithmetic.sql new file mode 100644 index 0000000000..19dfabed5c --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_arithmetic.sql @@ -0,0 +1,108 @@ +-- FLOAT type +-- any arithmetic on a nan value will result in a nan value + +SELECT 'nan'::FLOAT + 1; + +SELECT 'nan'::FLOAT + 'inf'::FLOAT; + +SELECT 'nan'::FLOAT - 1; + +SELECT 'nan'::FLOAT - 'inf'::FLOAT; + +SELECT 'nan'::FLOAT * 1; + +SELECT 'nan'::FLOAT * 'inf'::FLOAT; + +SELECT 'nan'::FLOAT / 1; + +SELECT 'nan'::FLOAT / 'inf'::FLOAT; + +SELECT 'nan'::FLOAT % 1; + +SELECT 'nan'::FLOAT % 'inf'::FLOAT; + +SELECT -('nan'::FLOAT); + +-- DOUBLE type +-- any arithmetic on a nan value will result in a nan value + +SELECT 'nan'::DOUBLE + 1; + +SELECT 'nan'::DOUBLE + 'inf'::DOUBLE; + +SELECT 'nan'::DOUBLE - 1; + +SELECT 'nan'::DOUBLE - 'inf'::DOUBLE; + +SELECT 'nan'::DOUBLE * 1; + +SELECT 'nan'::DOUBLE * 'inf'::DOUBLE; + +SELECT 'nan'::DOUBLE / 1; + +SELECT 'nan'::DOUBLE / 'inf'::DOUBLE; + +SELECT 'nan'::DOUBLE % 1; + +SELECT 'nan'::DOUBLE % 'inf'::DOUBLE; + +SELECT -('nan'::DOUBLE); + +-- FLOAT type +-- any arithmetic on a nan value will result in a nan value + +SELECT 'inf'::FLOAT + 1; + +-- inf + inf = inf +SELECT 'inf'::FLOAT + 'inf'::FLOAT; + +SELECT 'inf'::FLOAT - 1; + +-- inf - inf = nan +SELECT 'inf'::FLOAT - 'inf'::FLOAT; + +SELECT 'inf'::FLOAT * 1; + +-- inf * inf = inf +SELECT 'inf'::FLOAT * 'inf'::FLOAT; + +-- inf * -inf = -inf +SELECT 'inf'::FLOAT * '-inf'::FLOAT; + +SELECT 'inf'::FLOAT / 1; + +SELECT 1 / 'inf'::FLOAT; + +SELECT 'inf'::FLOAT % 1; + +SELECT 1 % 'inf'::FLOAT; + + +-- DOUBLE type +-- any arithmetic on a nan value will result in a nan value + +SELECT 'inf'::DOUBLE + 1; + +-- inf + inf = inf +SELECT 'inf'::DOUBLE + 'inf'::DOUBLE; + +SELECT 'inf'::DOUBLE - 1; + +-- inf - inf = nan +SELECT 'inf'::DOUBLE - 'inf'::DOUBLE; + +SELECT 'inf'::DOUBLE * 1; + +-- inf * inf = inf +SELECT 'inf'::DOUBLE * 'inf'::DOUBLE; + +-- inf * -inf = -inf +SELECT 'inf'::DOUBLE * '-inf'::DOUBLE; + +SELECT 'inf'::DOUBLE / 1; + +SELECT 1 / 'inf'::DOUBLE; + +SELECT 'inf'::DOUBLE % 1; + +SELECT 1 % 'inf'::DOUBLE; diff --git a/tests/cases/standalone/common/types/float/nan_cast.result b/tests/cases/standalone/common/types/float/nan_cast.result new file mode 100644 index 0000000000..927aabf071 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_cast.result @@ -0,0 +1,273 @@ +-- description: Test casting of NaN and inf values +-- to integer/decimal casts +SELECT 'nan'::FLOAT; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT 'nan'::FLOAT::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value NaN to type Int32 + +SELECT 'nan'::FLOAT::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on NaN + +SELECT 'nan'::FLOAT::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on NaN + +SELECT 'nan'::FLOAT::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on NaN + +SELECT 'nan'::FLOAT::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on NaN + +SELECT 'inf'::FLOAT; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT 'inf'::FLOAT::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value inf to type Int32 + +SELECT 'inf'::FLOAT::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on inf + +SELECT 'inf'::FLOAT::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on inf + +SELECT 'inf'::FLOAT::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on inf + +SELECT 'inf'::FLOAT::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on inf + +SELECT '-inf'::FLOAT; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT '-inf'::FLOAT::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value -inf to type Int32 + +SELECT '-inf'::FLOAT::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on -inf + +SELECT '-inf'::FLOAT::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on -inf + +SELECT '-inf'::FLOAT::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on -inf + +SELECT '-inf'::FLOAT::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on -inf + +SELECT 'nan'::DOUBLE; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT 'nan'::DOUBLE::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value NaN to type Int32 + +SELECT 'nan'::DOUBLE::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on NaN + +SELECT 'nan'::DOUBLE::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on NaN + +SELECT 'nan'::DOUBLE::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on NaN + +SELECT 'nan'::DOUBLE::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on NaN + +SELECT 'inf'::DOUBLE; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT 'inf'::DOUBLE::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value inf to type Int32 + +SELECT 'inf'::DOUBLE::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on inf + +SELECT 'inf'::DOUBLE::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on inf + +SELECT 'inf'::DOUBLE::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on inf + +SELECT 'inf'::DOUBLE::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on inf + +SELECT '-inf'::DOUBLE; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + +-- cannot cast nan, inf or -inf to these types +SELECT '-inf'::DOUBLE::INT; + +Error: 3001(EngineExecuteQuery), Cast error: Can't cast value -inf to type Int32 + +SELECT '-inf'::DOUBLE::DECIMAL(4,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(4, 1). Overflowing on -inf + +SELECT '-inf'::DOUBLE::DECIMAL(9,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(9, 1). Overflowing on -inf + +SELECT '-inf'::DOUBLE::DECIMAL(18,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(18, 1). Overflowing on -inf + +SELECT '-inf'::DOUBLE::DECIMAL(38,1); + +Error: 3001(EngineExecuteQuery), Cast error: Cannot cast to Decimal128(38, 1). Overflowing on -inf + +-- we can cast nan, inf and -inf between floats and doubles, as well as to/from strings +SELECT 'nan'::FLOAT::VARCHAR; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +SELECT 'nan'::DOUBLE::VARCHAR; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +SELECT 'nan'::VARCHAR::FLOAT; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +SELECT 'nan'::VARCHAR::DOUBLE; + ++-------------+ +| Utf8("nan") | ++-------------+ +| NaN | ++-------------+ + +SELECT 'inf'::FLOAT::VARCHAR; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +SELECT 'inf'::DOUBLE::VARCHAR; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +SELECT 'inf'::VARCHAR::FLOAT; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +SELECT 'inf'::VARCHAR::DOUBLE; + ++-------------+ +| Utf8("inf") | ++-------------+ +| inf | ++-------------+ + +SELECT '-inf'::FLOAT::VARCHAR; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + +SELECT '-inf'::DOUBLE::VARCHAR; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + +SELECT '-inf'::VARCHAR::FLOAT; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + +SELECT '-inf'::VARCHAR::DOUBLE; + ++--------------+ +| Utf8("-inf") | ++--------------+ +| -inf | ++--------------+ + diff --git a/tests/cases/standalone/common/types/float/nan_cast.sql b/tests/cases/standalone/common/types/float/nan_cast.sql new file mode 100644 index 0000000000..1032865dbd --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_cast.sql @@ -0,0 +1,70 @@ +-- description: Test casting of NaN and inf values +-- to integer/decimal casts + +SELECT 'nan'::FLOAT; + +-- cannot cast nan, inf or -inf to these types +SELECT 'nan'::FLOAT::INT; +SELECT 'nan'::FLOAT::DECIMAL(4,1); +SELECT 'nan'::FLOAT::DECIMAL(9,1); +SELECT 'nan'::FLOAT::DECIMAL(18,1); +SELECT 'nan'::FLOAT::DECIMAL(38,1); + +SELECT 'inf'::FLOAT; + +-- cannot cast nan, inf or -inf to these types +SELECT 'inf'::FLOAT::INT; +SELECT 'inf'::FLOAT::DECIMAL(4,1); +SELECT 'inf'::FLOAT::DECIMAL(9,1); +SELECT 'inf'::FLOAT::DECIMAL(18,1); +SELECT 'inf'::FLOAT::DECIMAL(38,1); + +SELECT '-inf'::FLOAT; + +-- cannot cast nan, inf or -inf to these types +SELECT '-inf'::FLOAT::INT; +SELECT '-inf'::FLOAT::DECIMAL(4,1); +SELECT '-inf'::FLOAT::DECIMAL(9,1); +SELECT '-inf'::FLOAT::DECIMAL(18,1); +SELECT '-inf'::FLOAT::DECIMAL(38,1); + +SELECT 'nan'::DOUBLE; + +-- cannot cast nan, inf or -inf to these types +SELECT 'nan'::DOUBLE::INT; +SELECT 'nan'::DOUBLE::DECIMAL(4,1); +SELECT 'nan'::DOUBLE::DECIMAL(9,1); +SELECT 'nan'::DOUBLE::DECIMAL(18,1); +SELECT 'nan'::DOUBLE::DECIMAL(38,1); + +SELECT 'inf'::DOUBLE; + +-- cannot cast nan, inf or -inf to these types +SELECT 'inf'::DOUBLE::INT; +SELECT 'inf'::DOUBLE::DECIMAL(4,1); +SELECT 'inf'::DOUBLE::DECIMAL(9,1); +SELECT 'inf'::DOUBLE::DECIMAL(18,1); +SELECT 'inf'::DOUBLE::DECIMAL(38,1); + +SELECT '-inf'::DOUBLE; + +-- cannot cast nan, inf or -inf to these types +SELECT '-inf'::DOUBLE::INT; +SELECT '-inf'::DOUBLE::DECIMAL(4,1); +SELECT '-inf'::DOUBLE::DECIMAL(9,1); +SELECT '-inf'::DOUBLE::DECIMAL(18,1); +SELECT '-inf'::DOUBLE::DECIMAL(38,1); + +-- we can cast nan, inf and -inf between floats and doubles, as well as to/from strings +SELECT 'nan'::FLOAT::VARCHAR; +SELECT 'nan'::DOUBLE::VARCHAR; +SELECT 'nan'::VARCHAR::FLOAT; +SELECT 'nan'::VARCHAR::DOUBLE; +SELECT 'inf'::FLOAT::VARCHAR; +SELECT 'inf'::DOUBLE::VARCHAR; +SELECT 'inf'::VARCHAR::FLOAT; +SELECT 'inf'::VARCHAR::DOUBLE; +SELECT '-inf'::FLOAT::VARCHAR; +SELECT '-inf'::DOUBLE::VARCHAR; +SELECT '-inf'::VARCHAR::FLOAT; +SELECT '-inf'::VARCHAR::DOUBLE; diff --git a/tests/cases/standalone/common/types/float/nan_join.result b/tests/cases/standalone/common/types/float/nan_join.result new file mode 100644 index 0000000000..6a6d305e8d --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_join.result @@ -0,0 +1,68 @@ +-- description: Test NaN and inf joins +-- group: [float] +-- FLOAT type +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('inf'::FLOAT, 1), ('-inf'::FLOAT, 2), ('nan'::FLOAT, 3); + +Affected Rows: 3 + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) USING (f); + +Error: 3000(PlanQuery), Schema contains qualified field name floats.f and unqualified field name f which would be ambiguous + +SELECT * FROM floats JOIN (SELECT '-inf'::FLOAT) tbl(f) USING (f); + +Error: 3000(PlanQuery), Schema contains qualified field name floats.f and unqualified field name f which would be ambiguous + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) ON (floats.f >= tbl.f) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name floats.f and unqualified field name f which would be ambiguous + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) ON (floats.f <= tbl.f) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name floats.f and unqualified field name f which would be ambiguous + +SELECT * FROM floats JOIN (SELECT '-inf'::FLOAT, 'inf'::FLOAT) tbl(f,g) ON (floats.f >= tbl.f AND floats.f <= tbl.g) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name floats.f and unqualified field name f which would be ambiguous + +DROP TABLE floats; + +Affected Rows: 1 + +-- DOUBLE type +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1), ('-inf'::DOUBLE, 2), ('nan'::DOUBLE, 3); + +Affected Rows: 3 + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) USING (d); + +Error: 3000(PlanQuery), Schema contains qualified field name doubles.d and unqualified field name d which would be ambiguous + +SELECT * FROM doubles JOIN (SELECT '-inf'::DOUBLE) tbl(d) USING (d); + +Error: 3000(PlanQuery), Schema contains qualified field name doubles.d and unqualified field name d which would be ambiguous + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) ON (doubles.d >= tbl.d) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name doubles.d and unqualified field name d which would be ambiguous + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) ON (doubles.d <= tbl.d) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name doubles.d and unqualified field name d which would be ambiguous + +SELECT * FROM doubles JOIN (SELECT '-inf'::DOUBLE, 'inf'::DOUBLE) tbl(d,g) ON (doubles.d >= tbl.d AND doubles.d <= tbl.g) ORDER BY 1; + +Error: 3000(PlanQuery), Schema contains qualified field name doubles.d and unqualified field name d which would be ambiguous + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan_join.sql b/tests/cases/standalone/common/types/float/nan_join.sql new file mode 100644 index 0000000000..aba107e6e5 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_join.sql @@ -0,0 +1,39 @@ +-- description: Test NaN and inf joins +-- group: [float] + +-- FLOAT type + +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('inf'::FLOAT, 1), ('-inf'::FLOAT, 2), ('nan'::FLOAT, 3); + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) USING (f); + +SELECT * FROM floats JOIN (SELECT '-inf'::FLOAT) tbl(f) USING (f); + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) ON (floats.f >= tbl.f) ORDER BY 1; + +SELECT * FROM floats JOIN (SELECT 'inf'::FLOAT) tbl(f) ON (floats.f <= tbl.f) ORDER BY 1; + +SELECT * FROM floats JOIN (SELECT '-inf'::FLOAT, 'inf'::FLOAT) tbl(f,g) ON (floats.f >= tbl.f AND floats.f <= tbl.g) ORDER BY 1; + +DROP TABLE floats; + + +-- DOUBLE type + +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1), ('-inf'::DOUBLE, 2), ('nan'::DOUBLE, 3); + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) USING (d); + +SELECT * FROM doubles JOIN (SELECT '-inf'::DOUBLE) tbl(d) USING (d); + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) ON (doubles.d >= tbl.d) ORDER BY 1; + +SELECT * FROM doubles JOIN (SELECT 'inf'::DOUBLE) tbl(d) ON (doubles.d <= tbl.d) ORDER BY 1; + +SELECT * FROM doubles JOIN (SELECT '-inf'::DOUBLE, 'inf'::DOUBLE) tbl(d,g) ON (doubles.d >= tbl.d AND doubles.d <= tbl.g) ORDER BY 1; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/float/nan_ordering.result b/tests/cases/standalone/common/types/float/nan_ordering.result new file mode 100644 index 0000000000..f39b78d63c --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_ordering.result @@ -0,0 +1,199 @@ +-- description: Test ordering of NaN and infinity values +-- FLOAT type +-- storing nan in a table +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('NAN'::FLOAT, 1), (1::FLOAT, 2), ('infinity'::FLOAT, 3), ('-infinity'::FLOAT, 4), (-1::FLOAT, 5), (NULL, 6); + +Affected Rows: 6 + +-- standard ordering +SELECT f FROM floats ORDER BY f; + ++------+ +| f | ++------+ +| -inf | +| -1.0 | +| 1.0 | +| inf | +| NaN | +| | ++------+ + +SELECT f FROM floats ORDER BY f DESC; + ++------+ +| f | ++------+ +| | +| NaN | +| inf | +| 1.0 | +| -1.0 | +| -inf | ++------+ + +-- top-n +SELECT f FROM floats ORDER BY f DESC NULLS LAST LIMIT 2; + ++-----+ +| f | ++-----+ +| NaN | +| inf | ++-----+ + +SELECT f FROM floats ORDER BY f NULLS LAST LIMIT 2; + ++------+ +| f | ++------+ +| -inf | +| -1.0 | ++------+ + +SELECT f FROM floats ORDER BY f DESC NULLS LAST LIMIT 4; + ++------+ +| f | ++------+ +| NaN | +| inf | +| 1.0 | +| -1.0 | ++------+ + +SELECT f FROM floats ORDER BY f NULLS LAST LIMIT 4; + ++------+ +| f | ++------+ +| -inf | +| -1.0 | +| 1.0 | +| inf | ++------+ + +-- count with filters +SELECT COUNT(*) FROM floats WHERE f > 0; + ++-----------------+ +| COUNT(UInt8(1)) | ++-----------------+ +| 3 | ++-----------------+ + +SELECT COUNT(*) FROM floats WHERE f < 0; + ++-----------------+ +| COUNT(UInt8(1)) | ++-----------------+ +| 2 | ++-----------------+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- DOUBLE type +-- storing nan in a table +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('NAN'::DOUBLE, 1), (1::DOUBLE, 2), ('infinity'::DOUBLE, 3), ('-infinity'::DOUBLE, 4), (-1::DOUBLE, 5), (NULL, 6); + +Affected Rows: 6 + +-- standard ordering +SELECT d FROM doubles ORDER BY d; + ++------+ +| d | ++------+ +| -inf | +| -1.0 | +| 1.0 | +| inf | +| NaN | +| | ++------+ + +SELECT d FROM doubles ORDER BY d DESC; + ++------+ +| d | ++------+ +| | +| NaN | +| inf | +| 1.0 | +| -1.0 | +| -inf | ++------+ + +-- top-n +SELECT d FROM doubles ORDER BY d DESC NULLS LAST LIMIT 2; + ++-----+ +| d | ++-----+ +| NaN | +| inf | ++-----+ + +SELECT d FROM doubles ORDER BY d NULLS LAST LIMIT 2; + ++------+ +| d | ++------+ +| -inf | +| -1.0 | ++------+ + +SELECT d FROM doubles ORDER BY d DESC NULLS LAST LIMIT 4; + ++------+ +| d | ++------+ +| NaN | +| inf | +| 1.0 | +| -1.0 | ++------+ + +SELECT d FROM doubles ORDER BY d NULLS LAST LIMIT 4; + ++------+ +| d | ++------+ +| -inf | +| -1.0 | +| 1.0 | +| inf | ++------+ + +-- count with filters +SELECT COUNT(*) FROM doubles WHERE d > 0; + ++-----------------+ +| COUNT(UInt8(1)) | ++-----------------+ +| 3 | ++-----------------+ + +SELECT COUNT(*) FROM doubles WHERE d < 0; + ++-----------------+ +| COUNT(UInt8(1)) | ++-----------------+ +| 2 | ++-----------------+ + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan_ordering.sql b/tests/cases/standalone/common/types/float/nan_ordering.sql new file mode 100644 index 0000000000..3ebeeba223 --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_ordering.sql @@ -0,0 +1,59 @@ +-- description: Test ordering of NaN and infinity values + +-- FLOAT type + +-- storing nan in a table +CREATE TABLE floats(f FLOAT, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('NAN'::FLOAT, 1), (1::FLOAT, 2), ('infinity'::FLOAT, 3), ('-infinity'::FLOAT, 4), (-1::FLOAT, 5), (NULL, 6); + +-- standard ordering +SELECT f FROM floats ORDER BY f; + +SELECT f FROM floats ORDER BY f DESC; + +-- top-n +SELECT f FROM floats ORDER BY f DESC NULLS LAST LIMIT 2; + +SELECT f FROM floats ORDER BY f NULLS LAST LIMIT 2; + +SELECT f FROM floats ORDER BY f DESC NULLS LAST LIMIT 4; + +SELECT f FROM floats ORDER BY f NULLS LAST LIMIT 4; + +-- count with filters +SELECT COUNT(*) FROM floats WHERE f > 0; + +SELECT COUNT(*) FROM floats WHERE f < 0; + +DROP TABLE floats; + + +-- DOUBLE type + +-- storing nan in a table +CREATE TABLE doubles(d DOUBLE, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('NAN'::DOUBLE, 1), (1::DOUBLE, 2), ('infinity'::DOUBLE, 3), ('-infinity'::DOUBLE, 4), (-1::DOUBLE, 5), (NULL, 6); + + +-- standard ordering +SELECT d FROM doubles ORDER BY d; + +SELECT d FROM doubles ORDER BY d DESC; + +-- top-n +SELECT d FROM doubles ORDER BY d DESC NULLS LAST LIMIT 2; + +SELECT d FROM doubles ORDER BY d NULLS LAST LIMIT 2; + +SELECT d FROM doubles ORDER BY d DESC NULLS LAST LIMIT 4; + +SELECT d FROM doubles ORDER BY d NULLS LAST LIMIT 4; + +-- count with filters +SELECT COUNT(*) FROM doubles WHERE d > 0; + +SELECT COUNT(*) FROM doubles WHERE d < 0; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/float/nan_window.result b/tests/cases/standalone/common/types/float/nan_window.result new file mode 100644 index 0000000000..3a3e14b2ab --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_window.result @@ -0,0 +1,131 @@ +-- description: Test NaN and inf in windowing functions +-- grouping by inf and nan +CREATE TABLE floats(f FLOAT, i INT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO floats VALUES ('inf'::FLOAT, 1, 2), ('inf'::FLOAT, 7, 3), ('-inf'::FLOAT, 3, 4), ('nan'::FLOAT, 7, 5), ('nan'::FLOAT, 19, 6), ('-inf'::FLOAT, 2, 7); + +Affected Rows: 6 + +SELECT f, SUM(i) OVER (PARTITION BY f) FROM floats ORDER BY f; + ++------+------------------------------------------------------------------------------------------------+ +| f | SUM(floats.i) PARTITION BY [floats.f] ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING | ++------+------------------------------------------------------------------------------------------------+ +| -inf | 5 | +| -inf | 5 | +| inf | 8 | +| inf | 8 | +| NaN | 26 | +| NaN | 26 | ++------+------------------------------------------------------------------------------------------------+ + +SELECT f, i, SUM(i) OVER (ORDER BY f, i) FROM floats ORDER BY f, i; + ++------+----+-----------------------------------------------------------------------------------------------------------------------------+ +| f | i | SUM(floats.i) ORDER BY [floats.f ASC NULLS LAST, floats.i ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++------+----+-----------------------------------------------------------------------------------------------------------------------------+ +| -inf | 2 | 2 | +| -inf | 3 | 5 | +| inf | 1 | 6 | +| inf | 7 | 13 | +| NaN | 7 | 20 | +| NaN | 19 | 39 | ++------+----+-----------------------------------------------------------------------------------------------------------------------------+ + +SELECT f, i, SUM(i) OVER (PARTITION BY f ORDER BY f, i) FROM floats ORDER BY f, i; + ++------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| f | i | SUM(floats.i) PARTITION BY [floats.f] ORDER BY [floats.f ASC NULLS LAST, floats.i ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------+ +| -inf | 2 | 2 | +| -inf | 3 | 5 | +| inf | 1 | 1 | +| inf | 7 | 8 | +| NaN | 7 | 7 | +| NaN | 19 | 26 | ++------+----+-----------------------------------------------------------------------------------------------------------------------------------------------------+ + +SELECT i, f, SUM(i) OVER (ORDER BY i, f) FROM floats ORDER BY i, f; + ++----+------+-----------------------------------------------------------------------------------------------------------------------------+ +| i | f | SUM(floats.i) ORDER BY [floats.i ASC NULLS LAST, floats.f ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++----+------+-----------------------------------------------------------------------------------------------------------------------------+ +| 1 | inf | 1 | +| 2 | -inf | 3 | +| 3 | -inf | 6 | +| 7 | inf | 13 | +| 7 | NaN | 20 | +| 19 | NaN | 39 | ++----+------+-----------------------------------------------------------------------------------------------------------------------------+ + +DROP TABLE floats; + +Affected Rows: 1 + +-- grouping by inf and nan +CREATE TABLE doubles(f DOUBLE, i INT, ts TIMESTAMP TIME INDEX); + +Affected Rows: 0 + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1, 2), ('inf'::DOUBLE, 7, 3), ('-inf'::DOUBLE, 3, 4), ('nan'::DOUBLE, 7, 5), ('nan'::DOUBLE, 19, 6), ('-inf'::DOUBLE, 2, 7); + +Affected Rows: 6 + +SELECT f, SUM(i) OVER (PARTITION BY f) FROM doubles ORDER BY f; + ++------+--------------------------------------------------------------------------------------------------+ +| f | SUM(doubles.i) PARTITION BY [doubles.f] ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING | ++------+--------------------------------------------------------------------------------------------------+ +| -inf | 5 | +| -inf | 5 | +| inf | 8 | +| inf | 8 | +| NaN | 26 | +| NaN | 26 | ++------+--------------------------------------------------------------------------------------------------+ + +SELECT f, i, SUM(i) OVER (ORDER BY f, i) FROM doubles ORDER BY f, i; + ++------+----+--------------------------------------------------------------------------------------------------------------------------------+ +| f | i | SUM(doubles.i) ORDER BY [doubles.f ASC NULLS LAST, doubles.i ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++------+----+--------------------------------------------------------------------------------------------------------------------------------+ +| -inf | 2 | 2 | +| -inf | 3 | 5 | +| inf | 1 | 6 | +| inf | 7 | 13 | +| NaN | 7 | 20 | +| NaN | 19 | 39 | ++------+----+--------------------------------------------------------------------------------------------------------------------------------+ + +SELECT f, i, SUM(i) OVER (PARTITION BY f ORDER BY f, i) FROM doubles ORDER BY f, i; + ++------+----+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +| f | i | SUM(doubles.i) PARTITION BY [doubles.f] ORDER BY [doubles.f ASC NULLS LAST, doubles.i ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++------+----+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +| -inf | 2 | 2 | +| -inf | 3 | 5 | +| inf | 1 | 1 | +| inf | 7 | 8 | +| NaN | 7 | 7 | +| NaN | 19 | 26 | ++------+----+---------------------------------------------------------------------------------------------------------------------------------------------------------+ + +SELECT i, f, SUM(i) OVER (ORDER BY i, f) FROM doubles ORDER BY i, f; + ++----+------+--------------------------------------------------------------------------------------------------------------------------------+ +| i | f | SUM(doubles.i) ORDER BY [doubles.i ASC NULLS LAST, doubles.f ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | ++----+------+--------------------------------------------------------------------------------------------------------------------------------+ +| 1 | inf | 1 | +| 2 | -inf | 3 | +| 3 | -inf | 6 | +| 7 | inf | 13 | +| 7 | NaN | 20 | +| 19 | NaN | 39 | ++----+------+--------------------------------------------------------------------------------------------------------------------------------+ + +DROP TABLE doubles; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/float/nan_window.sql b/tests/cases/standalone/common/types/float/nan_window.sql new file mode 100644 index 0000000000..2c18ae83ee --- /dev/null +++ b/tests/cases/standalone/common/types/float/nan_window.sql @@ -0,0 +1,32 @@ +-- description: Test NaN and inf in windowing functions + +-- grouping by inf and nan +CREATE TABLE floats(f FLOAT, i INT, ts TIMESTAMP TIME INDEX); + +INSERT INTO floats VALUES ('inf'::FLOAT, 1, 2), ('inf'::FLOAT, 7, 3), ('-inf'::FLOAT, 3, 4), ('nan'::FLOAT, 7, 5), ('nan'::FLOAT, 19, 6), ('-inf'::FLOAT, 2, 7); + +SELECT f, SUM(i) OVER (PARTITION BY f) FROM floats ORDER BY f; + +SELECT f, i, SUM(i) OVER (ORDER BY f, i) FROM floats ORDER BY f, i; + +SELECT f, i, SUM(i) OVER (PARTITION BY f ORDER BY f, i) FROM floats ORDER BY f, i; + +SELECT i, f, SUM(i) OVER (ORDER BY i, f) FROM floats ORDER BY i, f; + +DROP TABLE floats; + +-- grouping by inf and nan +CREATE TABLE doubles(f DOUBLE, i INT, ts TIMESTAMP TIME INDEX); + +INSERT INTO doubles VALUES ('inf'::DOUBLE, 1, 2), ('inf'::DOUBLE, 7, 3), ('-inf'::DOUBLE, 3, 4), ('nan'::DOUBLE, 7, 5), ('nan'::DOUBLE, 19, 6), ('-inf'::DOUBLE, 2, 7); + + +SELECT f, SUM(i) OVER (PARTITION BY f) FROM doubles ORDER BY f; + +SELECT f, i, SUM(i) OVER (ORDER BY f, i) FROM doubles ORDER BY f, i; + +SELECT f, i, SUM(i) OVER (PARTITION BY f ORDER BY f, i) FROM doubles ORDER BY f, i; + +SELECT i, f, SUM(i) OVER (ORDER BY i, f) FROM doubles ORDER BY i, f; + +DROP TABLE doubles; diff --git a/tests/cases/standalone/common/types/string/bigstring.result b/tests/cases/standalone/common/types/string/bigstring.result new file mode 100644 index 0000000000..db405e9c2e --- /dev/null +++ b/tests/cases/standalone/common/types/string/bigstring.result @@ -0,0 +1,38 @@ +-- description: Insert big varchar strings +CREATE TABLE test (a VARCHAR, ts timestamp time index); + +Affected Rows: 0 + +-- insert a big varchar +INSERT INTO test VALUES ('aaaaaaaaaa', 1); + +Affected Rows: 1 + +-- sizes: 10, 100, 1000, 10000 +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 2 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 3 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 4 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +SELECT LENGTH(a) FROM test ORDER BY 1; + ++--------------------------+ +| character_length(test.a) | ++--------------------------+ +| 10 | +| 100 | +| 1000 | +| 10000 | ++--------------------------+ + +DROP TABLE test; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/string/bigstring.sql b/tests/cases/standalone/common/types/string/bigstring.sql new file mode 100644 index 0000000000..52ee0a716f --- /dev/null +++ b/tests/cases/standalone/common/types/string/bigstring.sql @@ -0,0 +1,17 @@ +-- description: Insert big varchar strings + +CREATE TABLE test (a VARCHAR, ts timestamp time index); + +-- insert a big varchar +INSERT INTO test VALUES ('aaaaaaaaaa', 1); + +-- sizes: 10, 100, 1000, 10000 +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 2 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 3 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, 4 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +SELECT LENGTH(a) FROM test ORDER BY 1; + +DROP TABLE test; diff --git a/tests/cases/standalone/common/types/string/scan_big_varchar.result b/tests/cases/standalone/common/types/string/scan_big_varchar.result new file mode 100644 index 0000000000..449e443839 --- /dev/null +++ b/tests/cases/standalone/common/types/string/scan_big_varchar.result @@ -0,0 +1,232 @@ +-- description: Test scanning many big varchar strings with limited memory +CREATE TABLE test (a VARCHAR, ts timestamp time index); + +Affected Rows: 0 + +-- create a big varchar (10K characters) +INSERT INTO test VALUES ('aaaaaaaaaa', 1); + +Affected Rows: 1 + +-- sizes: 10, 100, 1000, 10000 +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 3 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 5 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 7 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +-- now create a second table, we only insert the big varchar string in there +CREATE TABLE bigtable (a VARCHAR, ts timestamp time index); + +Affected Rows: 0 + +INSERT INTO bigtable SELECT a, ts FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +Affected Rows: 1 + +-- verify that the append worked +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 1 | 1 | 10000 | 10000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +-- we create a total of 16K entries in the big table +-- the total size of this table is 16K*10K = 160MB +-- we then scan the table at every step, as our buffer pool is limited to 100MB not all strings fit in memory +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 11 FROM bigtable; + +Affected Rows: 1 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 2 | 2 | 10000 | 20000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 23 FROM bigtable; + +Affected Rows: 2 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 4 | 4 | 10000 | 40000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 31 FROM bigtable; + +Affected Rows: 4 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 8 | 8 | 10000 | 80000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 37 FROM bigtable; + +Affected Rows: 8 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 16 | 16 | 10000 | 160000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 41 FROM bigtable; + +Affected Rows: 16 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 32 | 32 | 10000 | 320000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 47 FROM bigtable; + +Affected Rows: 32 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 64 | 64 | 10000 | 640000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 51 FROM bigtable; + +Affected Rows: 64 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 128 | 128 | 10000 | 1280000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 53 FROM bigtable; + +Affected Rows: 128 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 256 | 256 | 10000 | 2560000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 57 FROM bigtable; + +Affected Rows: 256 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 512 | 512 | 10000 | 5120000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 61 FROM bigtable; + +Affected Rows: 512 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 1024 | 1024 | 10000 | 10240000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 63 FROM bigtable; + +Affected Rows: 1024 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 2048 | 2048 | 10000 | 20480000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 67 FROM bigtable; + +Affected Rows: 2048 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 4096 | 4096 | 10000 | 40960000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 71 FROM bigtable; + +Affected Rows: 4096 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 8192 | 8192 | 10000 | 81920000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 73 FROM bigtable; + +Affected Rows: 8192 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 16384 | 16384 | 10000 | 163840000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 79 FROM bigtable; + +Affected Rows: 16384 + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| COUNT(UInt8(1)) | COUNT(bigtable.a) | MAX(character_length(bigtable.a)) | SUM(character_length(bigtable.a)) | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ +| 32768 | 32768 | 10000 | 327680000 | ++-----------------+-------------------+-----------------------------------+-----------------------------------+ + +DROP TABLE test; + +Affected Rows: 1 + +DROP TABLE bigtable; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/string/scan_big_varchar.sql b/tests/cases/standalone/common/types/string/scan_big_varchar.sql new file mode 100644 index 0000000000..ddd9edf917 --- /dev/null +++ b/tests/cases/standalone/common/types/string/scan_big_varchar.sql @@ -0,0 +1,90 @@ +-- description: Test scanning many big varchar strings with limited memory + +CREATE TABLE test (a VARCHAR, ts timestamp time index); + +-- create a big varchar (10K characters) +INSERT INTO test VALUES ('aaaaaaaaaa', 1); + +-- sizes: 10, 100, 1000, 10000 +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 3 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 5 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +INSERT INTO test SELECT a||a||a||a||a||a||a||a||a||a, to_unixtime(ts) * 7 FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +-- now create a second table, we only insert the big varchar string in there +CREATE TABLE bigtable (a VARCHAR, ts timestamp time index); + +INSERT INTO bigtable SELECT a, ts FROM test WHERE LENGTH(a)=(SELECT MAX(LENGTH(a)) FROM test); + +-- verify that the append worked +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +-- we create a total of 16K entries in the big table +-- the total size of this table is 16K*10K = 160MB +-- we then scan the table at every step, as our buffer pool is limited to 100MB not all strings fit in memory +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 11 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 23 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 31 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 37 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 41 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 47 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 51 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 53 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 57 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 61 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 63 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 67 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 71 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 73 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + +INSERT INTO bigtable SELECT a, to_unixtime(ts) * 79 FROM bigtable; + +SELECT COUNT(*), COUNT(a), MAX(LENGTH(a)), SUM(LENGTH(a)) FROM bigtable; + + +DROP TABLE test; + +DROP TABLE bigtable; diff --git a/tests/cases/standalone/common/types/string/unicode.result b/tests/cases/standalone/common/types/string/unicode.result new file mode 100644 index 0000000000..d9f1b70e56 --- /dev/null +++ b/tests/cases/standalone/common/types/string/unicode.result @@ -0,0 +1,68 @@ +-- description: Test unicode strings +-- insert unicode strings into the database +CREATE TABLE emojis(id INTEGER, s VARCHAR, ts timestamp time index); + +Affected Rows: 0 + +INSERT INTO emojis VALUES (1, '🦆', 1), (2, '🦆🍞🦆', 2); + +Affected Rows: 2 + +-- retrieve unicode strings again +SELECT * FROM emojis ORDER BY id; + ++----+--------+-------------------------+ +| id | s | ts | ++----+--------+-------------------------+ +| 1 | 🦆 | 1970-01-01T00:00:00.001 | +| 2 | 🦆🍞🦆 | 1970-01-01T00:00:00.002 | ++----+--------+-------------------------+ + +-- substr on unicode +SELECT substr(s, 1, 1), substr(s, 2, 1) FROM emojis ORDER BY id; + ++------------------------------------+------------------------------------+ +| substr(emojis.s,Int64(1),Int64(1)) | substr(emojis.s,Int64(2),Int64(1)) | ++------------------------------------+------------------------------------+ +| 🦆 | | +| 🦆 | 🍞 | ++------------------------------------+------------------------------------+ + +SELECT substr('u🦆', 1, 1); + ++---------------------------------------+ +| substr(Utf8("u🦆"),Int64(1),Int64(1)) | ++---------------------------------------+ +| u | ++---------------------------------------+ + +SELECT substr('A3🦤u🦆f', 4, 3); + ++--------------------------------------------+ +| substr(Utf8("A3🦤u🦆f"),Int64(4),Int64(3)) | ++--------------------------------------------+ +| u🦆f | ++--------------------------------------------+ + +SELECT substr('🦤🦆f', 1, 2); + ++-----------------------------------------+ +| substr(Utf8("🦤🦆f"),Int64(1),Int64(2)) | ++-----------------------------------------+ +| 🦤🦆 | ++-----------------------------------------+ + +-- length on emojis +SELECT length(s) FROM emojis ORDER BY id; + ++----------------------------+ +| character_length(emojis.s) | ++----------------------------+ +| 1 | +| 3 | ++----------------------------+ + +DROP TABLE emojis; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/string/unicode.sql b/tests/cases/standalone/common/types/string/unicode.sql new file mode 100644 index 0000000000..3dae3e6ab2 --- /dev/null +++ b/tests/cases/standalone/common/types/string/unicode.sql @@ -0,0 +1,23 @@ +-- description: Test unicode strings + +-- insert unicode strings into the database +CREATE TABLE emojis(id INTEGER, s VARCHAR, ts timestamp time index); + +INSERT INTO emojis VALUES (1, '🦆', 1), (2, '🦆🍞🦆', 2); + +-- retrieve unicode strings again +SELECT * FROM emojis ORDER BY id; + +-- substr on unicode +SELECT substr(s, 1, 1), substr(s, 2, 1) FROM emojis ORDER BY id; + +SELECT substr('u🦆', 1, 1); + +SELECT substr('A3🦤u🦆f', 4, 3); + +SELECT substr('🦤🦆f', 1, 2); + +-- length on emojis +SELECT length(s) FROM emojis ORDER BY id; + +DROP TABLE emojis; diff --git a/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.result b/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.result new file mode 100644 index 0000000000..945292234f --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.result @@ -0,0 +1,64 @@ +CREATE TABLE timestamp(t TIMESTAMP time index); + +Affected Rows: 0 + +INSERT INTO timestamp VALUES ('blabla'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse blabla to Timestamp value + +INSERT INTO timestamp VALUES ('1993-20-14 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1993-20-14 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1993-08-99 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1993-08-99 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1993-02-29 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1993-02-29 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-02-29 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-02-29 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1992-02-29 00:00:00'); + +Affected Rows: 1 + +INSERT INTO timestamp VALUES ('2000-02-29 00:00:00'); + +Affected Rows: 1 + +INSERT INTO timestamp VALUES ('02-02-1992 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 02-02-1992 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-1-1 59:59:23'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-1-1 59:59:23 to Timestamp value + +INSERT INTO timestamp VALUES ('1900a01a01 00:00:00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900a01a01 00:00:00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-1-1 00;00;00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-1-1 00;00;00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-1-1 00a00a00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-1-1 00a00a00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-1-1 00/00/00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-1-1 00/00/00 to Timestamp value + +INSERT INTO timestamp VALUES ('1900-1-1 00-00-00'); + +Error: 2000(InvalidSyntax), Failed to parse value: Failed to parse 1900-1-1 00-00-00 to Timestamp value + +DROP TABLE timestamp; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.sql b/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.sql new file mode 100644 index 0000000000..1afa7c7e8a --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/incorrect_timestamp.sql @@ -0,0 +1,31 @@ +CREATE TABLE timestamp(t TIMESTAMP time index); + +INSERT INTO timestamp VALUES ('blabla'); + +INSERT INTO timestamp VALUES ('1993-20-14 00:00:00'); + +INSERT INTO timestamp VALUES ('1993-08-99 00:00:00'); + +INSERT INTO timestamp VALUES ('1993-02-29 00:00:00'); + +INSERT INTO timestamp VALUES ('1900-02-29 00:00:00'); + +INSERT INTO timestamp VALUES ('1992-02-29 00:00:00'); + +INSERT INTO timestamp VALUES ('2000-02-29 00:00:00'); + +INSERT INTO timestamp VALUES ('02-02-1992 00:00:00'); + +INSERT INTO timestamp VALUES ('1900-1-1 59:59:23'); + +INSERT INTO timestamp VALUES ('1900a01a01 00:00:00'); + +INSERT INTO timestamp VALUES ('1900-1-1 00;00;00'); + +INSERT INTO timestamp VALUES ('1900-1-1 00a00a00'); + +INSERT INTO timestamp VALUES ('1900-1-1 00/00/00'); + +INSERT INTO timestamp VALUES ('1900-1-1 00-00-00'); + +DROP TABLE timestamp; diff --git a/tests/cases/standalone/common/types/timestamp/timestamp.result b/tests/cases/standalone/common/types/timestamp/timestamp.result new file mode 100644 index 0000000000..64029eafc9 --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp.result @@ -0,0 +1,177 @@ +CREATE TABLE IF NOT EXISTS timestamp (t TIMESTAMP, ts TIMESTAMP time index DEFAULT current_timestamp()); + +Affected Rows: 0 + +INSERT INTO timestamp VALUES ('2008-01-01 00:00:01', 1), (NULL, 2), ('2007-01-01 00:00:01', 3), ('2008-02-01 00:00:01', 4), ('2008-01-02 00:00:01', 5), ('2008-01-01 10:00:00', 6), ('2008-01-01 00:10:00', 7), ('2008-01-01 00:00:10', 8); + +Affected Rows: 8 + +SELECT timestamp '2017-07-23 13:10:11'; + ++-----------------------------+ +| Utf8("2017-07-23 13:10:11") | ++-----------------------------+ +| 2017-07-23T13:10:11 | ++-----------------------------+ + +SELECT timestamp '2017-07-23T13:10:11',timestamp '2017-07-23T13:10:11Z'; + ++-----------------------------+------------------------------+ +| Utf8("2017-07-23T13:10:11") | Utf8("2017-07-23T13:10:11Z") | ++-----------------------------+------------------------------+ +| 2017-07-23T13:10:11 | 2017-07-23T13:10:11 | ++-----------------------------+------------------------------+ + +SELECT timestamp ' 2017-07-23 13:10:11 '; + ++-----------------------------+ +| Utf8("2017-07-23 13:10:11") | ++-----------------------------+ +| 2017-07-23T13:10:11 | ++-----------------------------+ + +SELECT timestamp ' 2017-07-23 13:10:11 AA'; + +Error: 3001(EngineExecuteQuery), Parser error: Invalid timezone "AA": 'AA' is not a valid timezone + +SELECT timestamp 'AA2017-07-23 13:10:11'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from 'AA2017-07-23 13:10:11': error parsing date + +SELECT timestamp '2017-07-23A13:10:11'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '2017-07-23A13:10:11': invalid timestamp separator + +SELECT t FROM timestamp ORDER BY t; + ++---------------------+ +| t | ++---------------------+ +| 2007-01-01T00:00:01 | +| 2008-01-01T00:00:01 | +| 2008-01-01T00:00:10 | +| 2008-01-01T00:10:00 | +| 2008-01-01T10:00:00 | +| 2008-01-02T00:00:01 | +| 2008-02-01T00:00:01 | +| | ++---------------------+ + +SELECT MIN(t) FROM timestamp; + ++---------------------+ +| MIN(timestamp.t) | ++---------------------+ +| 2007-01-01T00:00:01 | ++---------------------+ + +SELECT MAX(t) FROM timestamp; + ++---------------------+ +| MAX(timestamp.t) | ++---------------------+ +| 2008-02-01T00:00:01 | ++---------------------+ + +SELECT SUM(t) FROM timestamp; + +Error: 3000(PlanQuery), Error during planning: The function Sum does not support inputs of type Timestamp(Millisecond, None). + +SELECT AVG(t) FROM timestamp; + +Error: 3000(PlanQuery), Error during planning: The function Avg does not support inputs of type Timestamp(Millisecond, None). + +SELECT t+t FROM timestamp; + +Error: 1003(Internal), Cast error: Cannot perform arithmetic operation between array of type Timestamp(Millisecond, None) and array of type Timestamp(Millisecond, None) + +SELECT t*t FROM timestamp; + +Error: 1003(Internal), Invalid argument error: column types must match schema types, expected Interval(DayTime) but found Timestamp(Millisecond, None) at column index 0 + +SELECT t/t FROM timestamp; + +Error: 1003(Internal), Invalid argument error: column types must match schema types, expected Interval(DayTime) but found Timestamp(Millisecond, None) at column index 0 + +SELECT t%t FROM timestamp; + +Error: 1003(Internal), Invalid argument error: column types must match schema types, expected Interval(DayTime) but found Timestamp(Millisecond, None) at column index 0 + +-- TODO(dennis): It can't run on distributed mode, uncomment it when the issue is fixed: https://github.com/GreptimeTeam/greptimedb/issues/2071 -- +-- SELECT t-t FROM timestamp; -- +SELECT EXTRACT(YEAR from TIMESTAMP '1992-01-01 01:01:01'); + ++-----------------------------------------------------+ +| date_part(Utf8("YEAR"),Utf8("1992-01-01 01:01:01")) | ++-----------------------------------------------------+ +| 1992.0 | ++-----------------------------------------------------+ + +SELECT EXTRACT(YEAR from TIMESTAMP '1992-01-01 01:01:01'::DATE); + ++-----------------------------------------------------+ +| date_part(Utf8("YEAR"),Utf8("1992-01-01 01:01:01")) | ++-----------------------------------------------------+ +| 1992.0 | ++-----------------------------------------------------+ + +SELECT (TIMESTAMP '1992-01-01 01:01:01')::DATE; + ++-----------------------------+ +| Utf8("1992-01-01 01:01:01") | ++-----------------------------+ +| 1992-01-01 | ++-----------------------------+ + +SELECT (TIMESTAMP '1992-01-01 01:01:01')::TIME; + ++-----------------------------+ +| Utf8("1992-01-01 01:01:01") | ++-----------------------------+ +| 01:01:01 | ++-----------------------------+ + +SELECT t::DATE FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1; + ++-------------+ +| timestamp.t | ++-------------+ +| 2007-01-01 | ++-------------+ + +SELECT t::TIME FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1; + ++-------------+ +| timestamp.t | ++-------------+ +| 00:00:01 | ++-------------+ + +SELECT (DATE '1992-01-01')::TIMESTAMP; + ++---------------------+ +| Utf8("1992-01-01") | ++---------------------+ +| 1992-01-01T00:00:00 | ++---------------------+ + +SELECT TIMESTAMP '2008-01-01 00:00:01.5'::VARCHAR; + ++-------------------------------+ +| Utf8("2008-01-01 00:00:01.5") | ++-------------------------------+ +| 2008-01-01T00:00:01.500 | ++-------------------------------+ + +SELECT TIMESTAMP '-8-01-01 00:00:01.5'::VARCHAR; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '-8-01-01 00:00:01.5': error parsing date + +SELECT TIMESTAMP '100000-01-01 00:00:01.5'::VARCHAR; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '100000-01-01 00:00:01.5': error parsing date + +DROP TABLE timestamp; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/timestamp/timestamp.sql b/tests/cases/standalone/common/types/timestamp/timestamp.sql new file mode 100644 index 0000000000..aa97e778bf --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp.sql @@ -0,0 +1,58 @@ +CREATE TABLE IF NOT EXISTS timestamp (t TIMESTAMP, ts TIMESTAMP time index DEFAULT current_timestamp()); + +INSERT INTO timestamp VALUES ('2008-01-01 00:00:01', 1), (NULL, 2), ('2007-01-01 00:00:01', 3), ('2008-02-01 00:00:01', 4), ('2008-01-02 00:00:01', 5), ('2008-01-01 10:00:00', 6), ('2008-01-01 00:10:00', 7), ('2008-01-01 00:00:10', 8); + +SELECT timestamp '2017-07-23 13:10:11'; + +SELECT timestamp '2017-07-23T13:10:11',timestamp '2017-07-23T13:10:11Z'; + +SELECT timestamp ' 2017-07-23 13:10:11 '; + +SELECT timestamp ' 2017-07-23 13:10:11 AA'; + +SELECT timestamp 'AA2017-07-23 13:10:11'; + +SELECT timestamp '2017-07-23A13:10:11'; + +SELECT t FROM timestamp ORDER BY t; + +SELECT MIN(t) FROM timestamp; + +SELECT MAX(t) FROM timestamp; + +SELECT SUM(t) FROM timestamp; + +SELECT AVG(t) FROM timestamp; + +SELECT t+t FROM timestamp; + +SELECT t*t FROM timestamp; + +SELECT t/t FROM timestamp; + +SELECT t%t FROM timestamp; + +-- TODO(dennis): It can't run on distributed mode, uncomment it when the issue is fixed: https://github.com/GreptimeTeam/greptimedb/issues/2071 -- +-- SELECT t-t FROM timestamp; -- + +SELECT EXTRACT(YEAR from TIMESTAMP '1992-01-01 01:01:01'); + +SELECT EXTRACT(YEAR from TIMESTAMP '1992-01-01 01:01:01'::DATE); + +SELECT (TIMESTAMP '1992-01-01 01:01:01')::DATE; + +SELECT (TIMESTAMP '1992-01-01 01:01:01')::TIME; + +SELECT t::DATE FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1; + +SELECT t::TIME FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1; + +SELECT (DATE '1992-01-01')::TIMESTAMP; + +SELECT TIMESTAMP '2008-01-01 00:00:01.5'::VARCHAR; + +SELECT TIMESTAMP '-8-01-01 00:00:01.5'::VARCHAR; + +SELECT TIMESTAMP '100000-01-01 00:00:01.5'::VARCHAR; + +DROP TABLE timestamp; diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_join.result b/tests/cases/standalone/common/types/timestamp/timestamp_join.result new file mode 100644 index 0000000000..6c0b466a17 --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_join.result @@ -0,0 +1,32 @@ +CREATE TABLE timestamp1(i TIMESTAMP time index); + +Affected Rows: 0 + +CREATE TABLE timestamp2(i TIMESTAMP time index); + +Affected Rows: 0 + +INSERT INTO timestamp1 VALUES ('1993-08-14 00:00:01'); + +Affected Rows: 1 + +INSERT INTO timestamp2 VALUES ('1993-08-14 00:00:01'); + +Affected Rows: 1 + +select count(*) from timestamp2 inner join timestamp1 on (timestamp1.i = timestamp2.i); + ++-----------------+ +| COUNT(UInt8(1)) | ++-----------------+ +| 1 | ++-----------------+ + +DROP TABLE timestamp1; + +Affected Rows: 1 + +DROP TABLE timestamp2; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_join.sql b/tests/cases/standalone/common/types/timestamp/timestamp_join.sql new file mode 100644 index 0000000000..661159ec2e --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_join.sql @@ -0,0 +1,13 @@ +CREATE TABLE timestamp1(i TIMESTAMP time index); + +CREATE TABLE timestamp2(i TIMESTAMP time index); + +INSERT INTO timestamp1 VALUES ('1993-08-14 00:00:01'); + +INSERT INTO timestamp2 VALUES ('1993-08-14 00:00:01'); + +select count(*) from timestamp2 inner join timestamp1 on (timestamp1.i = timestamp2.i); + +DROP TABLE timestamp1; + +DROP TABLE timestamp2; diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_limits.result b/tests/cases/standalone/common/types/timestamp/timestamp_limits.result new file mode 100644 index 0000000000..a3c8c619b4 --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_limits.result @@ -0,0 +1,81 @@ +-- https://github.com/duckdb/duckdb/blob/master/test/sql/types/timestamp/timestamp_limits.test -- +select timestamp '1970-01-01'; + ++---------------------+ +| Utf8("1970-01-01") | ++---------------------+ +| 1970-01-01T00:00:00 | ++---------------------+ + +select '290309-12-22 (BC) 00:00:00'::timestamp; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-21 (BC) 12:59:59.999999'::timestamp; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-21 (BC) 12:59:59.999999': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp + interval '1 day'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 microsecond'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 second'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 day'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 month'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 year'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00': error parsing date + +select timestamp '294247-01-10 04:00:54.775806'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775807'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775807': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 microsecond'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 second'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 hour'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 day'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 month'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 year'; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54.775806': error parsing date + +SELECT '290309-12-22 (BC) 00:00:00+07:00'::TIMESTAMP; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '290309-12-22 (BC) 00:00:00+07:00': error parsing date + +SELECT '294247-01-10 04:00:54-07:00'::TIMESTAMP; + +Error: 3001(EngineExecuteQuery), Parser error: Error parsing timestamp from '294247-01-10 04:00:54-07:00': error parsing date + diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_limits.sql b/tests/cases/standalone/common/types/timestamp/timestamp_limits.sql new file mode 100644 index 0000000000..c1bed8048b --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_limits.sql @@ -0,0 +1,49 @@ +-- https://github.com/duckdb/duckdb/blob/master/test/sql/types/timestamp/timestamp_limits.test -- + +select timestamp '1970-01-01'; + +select '290309-12-22 (BC) 00:00:00'::timestamp; + +select '290309-12-21 (BC) 12:59:59.999999'::timestamp; + +select '290309-12-22 (BC) 00:00:00'::timestamp + interval '1 day'; + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 microsecond'; + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 second'; + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 day'; + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 month'; + +select '290309-12-22 (BC) 00:00:00'::timestamp - interval '1 year'; + +select timestamp '294247-01-10 04:00:54.775806'; + +select timestamp '294247-01-10 04:00:54.775807'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 microsecond'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 second'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 hour'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 day'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 month'; + +select timestamp '294247-01-10 04:00:54.775806' + interval '1 year'; + +SELECT '290309-12-22 (BC) 00:00:00+07:00'::TIMESTAMP; + +SELECT '294247-01-10 04:00:54-07:00'::TIMESTAMP; + +--select epoch(timestamp '294247-01-10 04:00:54.775806'), epoch(timestamp '290309-12-22 (BC) 00:00:00'); + +--select year(timestamp '294247-01-10 04:00:54.775806'), year(timestamp '290309-12-22 (BC) 00:00:00'); + +--select decade(timestamp '294247-01-10 04:00:54.775806'), decade(timestamp '290309-12-22 (BC) 00:00:00'); + +--select monthname(timestamp '294247-01-10 04:00:54.775806'), monthname(timestamp '290309-12-22 (BC) 00:00:00'); + +--select age(timestamp '294247-01-10 04:00:54.775806', '290309-12-22 (BC) 00:00:00'::timestamp); diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_precision.result b/tests/cases/standalone/common/types/timestamp/timestamp_precision.result new file mode 100644 index 0000000000..441c9192bc --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_precision.result @@ -0,0 +1,61 @@ +-- description: Test timestamp precision +CREATE TABLE ts_precision( + sec TIMESTAMP, + msec TIMESTAMP(3), + micros TIMESTAMP(6), + nanos TIMESTAMP (9) TIME INDEX +); + +Affected Rows: 0 + +INSERT INTO ts_precision VALUES ('2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789'); + +Affected Rows: 1 + +-- FIXME: nano seconds do not render correctly +SELECT CAST(sec AS VARCHAR), CAST(msec AS VARCHAR), CAST(micros AS VARCHAR), CAST(nanos AS VARCHAR) FROM ts_precision; + ++-------------------------+-------------------------+----------------------------+-------------------------------+ +| ts_precision.sec | ts_precision.msec | ts_precision.micros | ts_precision.nanos | ++-------------------------+-------------------------+----------------------------+-------------------------------+ +| 2020-01-01T01:23:45.123 | 2020-01-01T01:23:45.123 | 2020-01-01T01:23:45.123456 | 2020-01-01T01:23:45.123456789 | ++-------------------------+-------------------------+----------------------------+-------------------------------+ + +SELECT EXTRACT(MICROSECONDS FROM sec), EXTRACT(MICROSECONDS FROM msec), EXTRACT(MICROSECONDS FROM micros), EXTRACT(MICROSECONDS FROM nanos) FROM ts_precision; + +Error: 1003(Internal), Execution error: Date part 'MICROSECONDS' not supported + +-- we only support precisions 0, 3, 6, and 9 +-- any other precision is rounded up (e.g. 1/2 -> 3, 4/5 -> 6, 7/8 -> 9) +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(0); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(0), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(3); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(3), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(6); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(6), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(9); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(9), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.12'::TIMESTAMP(3); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(3), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.12345'::TIMESTAMP(6); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(6), None) + +SELECT TIMESTAMP '2020-01-01 01:23:45.12345678'::TIMESTAMP(9); + +Error: 3000(PlanQuery), This feature is not implemented: Unsupported SQL type Timestamp(Some(9), None) + +DROP TABLE ts_precision; + +Affected Rows: 1 + diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_precision.sql b/tests/cases/standalone/common/types/timestamp/timestamp_precision.sql new file mode 100644 index 0000000000..0bbda85794 --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_precision.sql @@ -0,0 +1,33 @@ +-- description: Test timestamp precision + +CREATE TABLE ts_precision( + sec TIMESTAMP, + msec TIMESTAMP(3), + micros TIMESTAMP(6), + nanos TIMESTAMP (9) TIME INDEX +); + +INSERT INTO ts_precision VALUES ('2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789'); + +-- FIXME: nano seconds do not render correctly +SELECT CAST(sec AS VARCHAR), CAST(msec AS VARCHAR), CAST(micros AS VARCHAR), CAST(nanos AS VARCHAR) FROM ts_precision; + +SELECT EXTRACT(MICROSECONDS FROM sec), EXTRACT(MICROSECONDS FROM msec), EXTRACT(MICROSECONDS FROM micros), EXTRACT(MICROSECONDS FROM nanos) FROM ts_precision; + +-- we only support precisions 0, 3, 6, and 9 +-- any other precision is rounded up (e.g. 1/2 -> 3, 4/5 -> 6, 7/8 -> 9) +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(0); + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(3); + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(6); + +SELECT TIMESTAMP '2020-01-01 01:23:45.123456789'::TIMESTAMP(9); + +SELECT TIMESTAMP '2020-01-01 01:23:45.12'::TIMESTAMP(3); + +SELECT TIMESTAMP '2020-01-01 01:23:45.12345'::TIMESTAMP(6); + +SELECT TIMESTAMP '2020-01-01 01:23:45.12345678'::TIMESTAMP(9); + +DROP TABLE ts_precision; diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_tz.result b/tests/cases/standalone/common/types/timestamp/timestamp_tz.result new file mode 100644 index 0000000000..f863d1e02a --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_tz.result @@ -0,0 +1,32 @@ +select timestamptz '2021-11-15 02:30:00'; + ++-----------------------------+ +| Utf8("2021-11-15 02:30:00") | ++-----------------------------+ +| 2021-11-15T02:30:00Z | ++-----------------------------+ + +select '2021-11-15 02:30:00'::TIMESTAMP::TIMESTAMPTZ; + ++-----------------------------+ +| Utf8("2021-11-15 02:30:00") | ++-----------------------------+ +| 2021-11-15T02:30:00Z | ++-----------------------------+ + +SELECT '2021-04-29 10:50:09-05'::TIMESTAMPTZ::DATE; + ++--------------------------------+ +| Utf8("2021-04-29 10:50:09-05") | ++--------------------------------+ +| 2021-04-29 | ++--------------------------------+ + +SELECT '2021-04-29 10:50:09-05'::TIMESTAMPTZ::TIME; + ++--------------------------------+ +| Utf8("2021-04-29 10:50:09-05") | ++--------------------------------+ +| 15:50:09 | ++--------------------------------+ + diff --git a/tests/cases/standalone/common/types/timestamp/timestamp_tz.sql b/tests/cases/standalone/common/types/timestamp/timestamp_tz.sql new file mode 100644 index 0000000000..cfb757f02f --- /dev/null +++ b/tests/cases/standalone/common/types/timestamp/timestamp_tz.sql @@ -0,0 +1,7 @@ +select timestamptz '2021-11-15 02:30:00'; + +select '2021-11-15 02:30:00'::TIMESTAMP::TIMESTAMPTZ; + +SELECT '2021-04-29 10:50:09-05'::TIMESTAMPTZ::DATE; + +SELECT '2021-04-29 10:50:09-05'::TIMESTAMPTZ::TIME; diff --git a/tests/runner/src/env.rs b/tests/runner/src/env.rs index 94463078f2..10294d89d1 100644 --- a/tests/runner/src/env.rs +++ b/tests/runner/src/env.rs @@ -203,6 +203,7 @@ impl Env { let mut process = Command::new(program) .current_dir(util::get_binary_dir("debug")) + .env("TZ", "UTC") .args(args) .stdout(log_file) .spawn()