1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7TEST_CASE("Test handling of overflows in basic types", "[overflowhandling]") {
8 unique_ptr<QueryResult> result;
9 DuckDB db(nullptr);
10 Connection con(db);
11 con.EnableQueryVerification();
12
13 REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);"));
14
15 //! Casting NULL should still work though
16 REQUIRE_NO_FAIL(con.Query("SELECT ALL CAST ( - SUM ( DISTINCT - CAST ( "
17 "NULL AS INTEGER ) ) AS INTEGER ) FROM test"));
18
19 // insert too large value for domain should cause error
20 // FIXME new pg parser zeroes first param
21 REQUIRE_FAIL(con.Query("INSERT INTO test VALUES (-1099511627776, 3)"));
22
23 REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (12, 21), (14, 22)"));
24
25 //! Casting NULL should still work though
26 REQUIRE_NO_FAIL(con.Query("SELECT ALL CAST ( - SUM ( DISTINCT - CAST ( "
27 "NULL AS INTEGER ) ) AS INTEGER ) FROM test"));
28
29 // proper upcasting of integer columns in AVG
30 result = con.Query("SELECT b, AVG(a) FROM test GROUP BY b ORDER BY b;");
31 REQUIRE(CHECK_COLUMN(result, 0, {21, 22}));
32
33 // FIXME: statistics propagation for overflows needs to be reintroduced
34 return;
35 // cast to bigger type if it will overflow
36 result = con.Query("SELECT cast(200 AS TINYINT)");
37 REQUIRE(CHECK_COLUMN(result, 0, {200}));
38
39 // try to use the NULL value of a type
40 result = con.Query("SELECT cast(-127 AS TINYINT)");
41 REQUIRE(CHECK_COLUMN(result, 0, {-127}));
42
43 // promote on addition overflow
44 result = con.Query("SELECT cast(100 AS TINYINT) + cast(100 AS TINYINT)");
45 REQUIRE(CHECK_COLUMN(result, 0, {200}));
46
47 // also with tables
48 result = con.Query("CREATE TABLE test2 (a INTEGER, b TINYINT);");
49 result = con.Query("INSERT INTO test2 VALUES (200, 60), (12, 60), (14, 60)");
50
51 // cast to bigger type if it will overflow
52 result = con.Query("SELECT cast(a AS TINYINT) FROM test2");
53 REQUIRE(CHECK_COLUMN(result, 0, {200, 12, 14}));
54
55 // cast to bigger type if SUM overflows
56 result = con.Query("SELECT SUM(b) FROM test2");
57 REQUIRE(CHECK_COLUMN(result, 0, {180}));
58
59 // promote overflows in more complicated expression chains
60 // FIXME: need to fix statistics propagation
61 result = con.Query("SELECT a + b FROM (SELECT cast(100 AS TINYINT) AS a, cast(100 AS TINYINT) AS b) tbl1");
62 REQUIRE(CHECK_COLUMN(result, 0, {200}));
63}
64
65TEST_CASE("Test handling of overflows in float/double", "[overflowhandling]") {
66 unique_ptr<QueryResult> result;
67 DuckDB db(nullptr);
68 Connection con(db);
69 con.EnableQueryVerification();
70
71 // out of range constants are not accepted
72 REQUIRE_FAIL(con.Query("SELECT 1e1000"));
73 // overflow on cast from double to real results in an error
74 REQUIRE_FAIL(con.Query("SELECT 1e308::REAL"));
75 // test string casts
76 REQUIRE_FAIL(con.Query("SELECT '1e1000'::DOUBLE"));
77 REQUIRE_FAIL(con.Query("SELECT '1e100'::REAL"));
78
79 // overflow in SUM/AVG results in an error
80 REQUIRE_FAIL(con.Query("SELECT SUM(i) FROM (VALUES (1e308), (1e308)) tbl(i)"));
81 REQUIRE_FAIL(con.Query("SELECT AVG(i) FROM (VALUES (1e308), (1e308)) tbl(i)"));
82
83 // overflow in arithmetic as well
84 REQUIRE_FAIL(con.Query("SELECT 1e308+1e308"));
85 REQUIRE_FAIL(con.Query("SELECT 1e308*2"));
86 REQUIRE_FAIL(con.Query("SELECT -1e308-1e308"));
87 REQUIRE_FAIL(con.Query("SELECT 1e308/0.1"));
88
89 REQUIRE_FAIL(con.Query("SELECT 2e38::REAL+2e38::REAL"));
90 REQUIRE_FAIL(con.Query("SELECT 2e38::REAL*2"));
91 REQUIRE_FAIL(con.Query("SELECT -2e38::REAL-2e38::REAL"));
92 REQUIRE_FAIL(con.Query("SELECT 2e38::REAL/0.1::REAL"));
93}
94