1 | #include "catch.hpp" |
2 | #include "test_helpers.hpp" |
3 | |
4 | using namespace duckdb; |
5 | using namespace std; |
6 | |
7 | TEST_CASE("Test ceil(ing)/floor function" , "[function]" ) { |
8 | unique_ptr<QueryResult> result; |
9 | DuckDB db(nullptr); |
10 | Connection con(db); |
11 | con.EnableQueryVerification(); |
12 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE numbers(n DOUBLE)" )); |
13 | REQUIRE_NO_FAIL(con.Query("INSERT INTO numbers VALUES (NULL),(-42.8),(-42.2),(0), (42.2), (42.8)" )); |
14 | |
15 | result = con.Query("SELECT cast(CEIL(n::tinyint) as bigint) FROM numbers ORDER BY n" ); |
16 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
17 | result = con.Query("SELECT cast(CEIL(n::smallint) as bigint) FROM numbers ORDER BY n" ); |
18 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
19 | result = con.Query("SELECT cast(CEIL(n::integer) as bigint) FROM numbers ORDER BY n" ); |
20 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
21 | result = con.Query("SELECT cast(CEIL(n::bigint) as bigint) FROM numbers ORDER BY n" ); |
22 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
23 | result = con.Query("SELECT cast(CEIL(n::float) as bigint) FROM numbers ORDER BY n" ); |
24 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 43, 43})); |
25 | result = con.Query("SELECT cast(CEIL(n::double) as bigint) FROM numbers ORDER BY n" ); |
26 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 43, 43})); |
27 | |
28 | result = con.Query("SELECT cast(CEILING(n::double) as bigint) FROM numbers ORDER BY n" ); |
29 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 43, 43})); |
30 | |
31 | result = con.Query("SELECT cast(FLOOR(n::tinyint) as bigint) FROM numbers ORDER BY n" ); |
32 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
33 | result = con.Query("SELECT cast(FLOOR(n::smallint) as bigint) FROM numbers ORDER BY n" ); |
34 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
35 | result = con.Query("SELECT cast(FLOOR(n::integer) as bigint) FROM numbers ORDER BY n" ); |
36 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
37 | result = con.Query("SELECT cast(FLOOR(n::bigint) as bigint) FROM numbers ORDER BY n" ); |
38 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -42, -42, 0, 42, 42})); |
39 | result = con.Query("SELECT cast(FLOOR(n::float) as bigint) FROM numbers ORDER BY n" ); |
40 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -43, -43, 0, 42, 42})); |
41 | result = con.Query("SELECT cast(FLOOR(n::double) as bigint) FROM numbers ORDER BY n" ); |
42 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), -43, -43, 0, 42, 42})); |
43 | } |
44 | |
45 | TEST_CASE("Rounding test" , "[function]" ) { |
46 | unique_ptr<QueryResult> result; |
47 | DuckDB db(nullptr); |
48 | Connection con(db); |
49 | con.EnableQueryVerification(); |
50 | |
51 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE roundme(a DOUBLE, b INTEGER)" )); |
52 | REQUIRE_NO_FAIL(con.Query("INSERT INTO roundme VALUES (42.123456, 3)" )); |
53 | |
54 | result = con.Query("select round(42.12345, 0)" ); |
55 | REQUIRE(CHECK_COLUMN(result, 0, {42.0})); |
56 | |
57 | result = con.Query("select round(42.12345, 2)" ); |
58 | REQUIRE(CHECK_COLUMN(result, 0, {42.12})); |
59 | |
60 | result = con.Query("select round(42, 0)" ); |
61 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
62 | |
63 | result = con.Query("select round(a, 1) from roundme" ); |
64 | REQUIRE(CHECK_COLUMN(result, 0, {42.1})); |
65 | |
66 | result = con.Query("select round(b, 1) from roundme" ); |
67 | REQUIRE(CHECK_COLUMN(result, 0, {3})); |
68 | |
69 | result = con.Query("select round(a, b) from roundme" ); |
70 | REQUIRE(CHECK_COLUMN(result, 0, {42.123})); |
71 | } |
72 | |
73 | TEST_CASE("Test random & setseed functions" , "[function]" ) { |
74 | unique_ptr<QueryResult> result, result1, result2; |
75 | DuckDB db(nullptr); |
76 | Connection con(db); |
77 | |
78 | // random() is evaluated twice here |
79 | result = con.Query("select case when random() between 0 and 0.99999 then 1 else 0 end" ); |
80 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
81 | |
82 | result1 = con.Query("select random()" ); |
83 | result2 = con.Query("select random()" ); |
84 | REQUIRE(!result1->Equals(*result2)); |
85 | |
86 | REQUIRE_NO_FAIL(con.Query("select setseed(0.1)" )); |
87 | result1 = con.Query("select random(), random(), random()" ); |
88 | REQUIRE(CHECK_COLUMN(result1, 0, {0.612055})); |
89 | REQUIRE(CHECK_COLUMN(result1, 1, {0.384141})); |
90 | REQUIRE(CHECK_COLUMN(result1, 2, {0.288025})); |
91 | REQUIRE_NO_FAIL(con.Query("select setseed(0.1)" )); |
92 | result2 = con.Query("select random(), random(), random()" ); |
93 | REQUIRE(result1->Equals(*result2)); |
94 | |
95 | REQUIRE_FAIL(con.Query("select setseed(1.1)" )); |
96 | REQUIRE_FAIL(con.Query("select setseed(-1.1)" )); |
97 | |
98 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE seeds(a DOUBLE)" )); |
99 | REQUIRE_NO_FAIL(con.Query("INSERT INTO seeds VALUES (-0.1), (0.0), (0.1)" )); |
100 | result2 = con.Query("select setseed(a), a from seeds;" ); |
101 | REQUIRE(CHECK_COLUMN(result2, 0, {Value(), Value(), Value()})); |
102 | REQUIRE(CHECK_COLUMN(result2, 1, {-0.1, 0.0, 0.1})); |
103 | // Make sure last seed (0.1) is in effect |
104 | result1 = con.Query("select random(), random(), random()" ); |
105 | REQUIRE_NO_FAIL(con.Query("select setseed(0.1)" )); |
106 | result2 = con.Query("select random(), random(), random()" ); |
107 | REQUIRE(result1->Equals(*result2)); |
108 | |
109 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE numbers(a INTEGER)" )); |
110 | REQUIRE_NO_FAIL(con.Query("INSERT INTO numbers VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)" )); |
111 | |
112 | result = con.Query("select case when min(random()) >= 0 then 1 else 0 end from numbers;" ); |
113 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
114 | result = con.Query("select case when max(random()) < 1 then 1 else 0 end from numbers;" ); |
115 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
116 | |
117 | REQUIRE_NO_FAIL(con.Query("select * from numbers order by random()" )); |
118 | REQUIRE_NO_FAIL(con.Query("select random() from numbers" )); |
119 | } |
120 | |
121 | // see https://www.postgresql.org/docs/10/functions-math.html |
122 | |
123 | TEST_CASE("Function test cases from PG docs" , "[function]" ) { |
124 | unique_ptr<QueryResult> result; |
125 | DuckDB db(nullptr); |
126 | Connection con(db); |
127 | con.EnableQueryVerification(); |
128 | |
129 | result = con.Query("select abs(-17.4)" ); |
130 | REQUIRE(CHECK_COLUMN(result, 0, {17.4})); |
131 | |
132 | result = con.Query("select cbrt(27.0)" ); |
133 | REQUIRE(CHECK_COLUMN(result, 0, {3.0})); |
134 | |
135 | result = con.Query("select ceil(-42.8)" ); |
136 | REQUIRE(CHECK_COLUMN(result, 0, {-42.0})); |
137 | |
138 | result = con.Query("select ceiling(-95.3)" ); |
139 | REQUIRE(CHECK_COLUMN(result, 0, {-95.0})); |
140 | |
141 | result = con.Query("select exp(1.0)" ); |
142 | REQUIRE(CHECK_COLUMN(result, 0, {2.71828182845905})); |
143 | |
144 | result = con.Query("select floor(-42.8)" ); |
145 | REQUIRE(CHECK_COLUMN(result, 0, {-43.0})); |
146 | |
147 | result = con.Query("select ln(2.0)" ); |
148 | REQUIRE(CHECK_COLUMN(result, 0, {0.693147180559945})); |
149 | |
150 | result = con.Query("select log(100.0)" ); |
151 | REQUIRE(CHECK_COLUMN(result, 0, {2.0})); |
152 | |
153 | result = con.Query("select log10(100.0)" ); |
154 | REQUIRE(CHECK_COLUMN(result, 0, {2.0})); |
155 | |
156 | result = con.Query("select log2(4.0)" ); |
157 | REQUIRE(CHECK_COLUMN(result, 0, {2.0})); |
158 | |
159 | result = con.Query("select pi()" ); |
160 | REQUIRE(CHECK_COLUMN(result, 0, {3.14159265358979})); |
161 | |
162 | result = con.Query("select sqrt(2.0)" ); |
163 | REQUIRE(CHECK_COLUMN(result, 0, {1.4142135623731})); |
164 | |
165 | result = con.Query("select radians(45.0)" ); |
166 | REQUIRE(CHECK_COLUMN(result, 0, {0.785398163397448})); |
167 | |
168 | result = con.Query("select degrees(0.5)" ); |
169 | REQUIRE(CHECK_COLUMN(result, 0, {28.6478897565412})); |
170 | |
171 | result = con.Query("select sign(4.1)" ); |
172 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
173 | |
174 | result = con.Query("select sign(-4.1)" ); |
175 | REQUIRE(CHECK_COLUMN(result, 0, {-1})); |
176 | |
177 | result = con.Query("select sign(0)" ); |
178 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
179 | |
180 | result = con.Query("select sign(3)" ); |
181 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
182 | } |
183 | |
184 | TEST_CASE("Mod test" , "[function]" ) { |
185 | unique_ptr<QueryResult> result; |
186 | DuckDB db(nullptr); |
187 | Connection con(db); |
188 | con.EnableQueryVerification(); |
189 | |
190 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE modme(a DOUBLE, b INTEGER)" )); |
191 | REQUIRE_NO_FAIL(con.Query("INSERT INTO modme VALUES (42.123456, 3)" )); |
192 | |
193 | // input is real, divisor is an integer |
194 | result = con.Query("select mod(a, 40) from modme" ); |
195 | REQUIRE(CHECK_COLUMN(result, 0, {2.123456})); |
196 | |
197 | // Mod with 0 should be null |
198 | result = con.Query("select mod(42, 0)" ); |
199 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
200 | |
201 | // input is real, divisor is a real |
202 | result = con.Query("select mod(a, 2) from modme" ); |
203 | REQUIRE(CHECK_COLUMN(result, 0, {.123456})); |
204 | |
205 | // input is an integer, divisor is a real |
206 | result = con.Query("select mod(b, 2.1) from modme" ); |
207 | REQUIRE(CHECK_COLUMN(result, 0, {0.9})); |
208 | } |
209 | TEST_CASE("Power test" , "[function]" ) { |
210 | unique_ptr<QueryResult> result; |
211 | DuckDB db(nullptr); |
212 | Connection con(db); |
213 | con.EnableQueryVerification(); |
214 | |
215 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE powerme(a DOUBLE, b INTEGER)" )); |
216 | REQUIRE_NO_FAIL(con.Query("INSERT INTO powerme VALUES (2.1, 3)" )); |
217 | |
218 | result = con.Query("select pow(a, 0) from powerme" ); |
219 | REQUIRE(CHECK_COLUMN(result, 0, {1.0})); |
220 | |
221 | result = con.Query("select pow(b, -2) from powerme" ); |
222 | REQUIRE(CHECK_COLUMN(result, 0, {.1111})); |
223 | |
224 | result = con.Query("select pow(a, b) from powerme" ); |
225 | REQUIRE(CHECK_COLUMN(result, 0, {9.261})); |
226 | |
227 | result = con.Query("select pow(b, a) from powerme" ); |
228 | REQUIRE(CHECK_COLUMN(result, 0, {10.045})); |
229 | |
230 | result = con.Query("select power(b, a) from powerme" ); |
231 | REQUIRE(CHECK_COLUMN(result, 0, {10.045})); |
232 | } |
233 | |
234 | TEST_CASE("BIT_COUNT test" , "[function]" ) { |
235 | unique_ptr<QueryResult> result; |
236 | DuckDB db(nullptr); |
237 | Connection con(db); |
238 | con.EnableQueryVerification(); |
239 | |
240 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE bits(t tinyint, s smallint, i integer, b bigint)" )); |
241 | REQUIRE_NO_FAIL(con.Query("INSERT INTO bits VALUES (NULL, NULL, NULL, NULL), " |
242 | "(31, 1023, 11834119, 50827156903621017), " |
243 | "(-59, -517, -575693, -9876543210)" )); |
244 | |
245 | result = con.Query("select bit_count(t), bit_count(s),bit_count(i), bit_count(b) from bits" ); |
246 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 5, 4})); |
247 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 10, 14})); |
248 | REQUIRE(CHECK_COLUMN(result, 2, {Value(), 11, 24})); |
249 | REQUIRE(CHECK_COLUMN(result, 3, {Value(), 27, 49})); |
250 | } |
251 | |
252 | TEST_CASE("Test invalid input for math functions" , "[function]" ) { |
253 | unique_ptr<QueryResult> result; |
254 | DuckDB db(nullptr); |
255 | Connection con(db); |
256 | con.EnableQueryVerification(); |
257 | |
258 | // any invalid input in math functions results in a NULL |
259 | // sqrt of negative number |
260 | result = con.Query("SELECT SQRT(-1), SQRT(0)" ); |
261 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
262 | REQUIRE(CHECK_COLUMN(result, 1, {0})); |
263 | |
264 | // log of value <= 0 |
265 | result = con.Query("SELECT LN(-1), LN(0), LOG10(-1), LOG10(0), LOG2(-1), LOG2(0)" ); |
266 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
267 | REQUIRE(CHECK_COLUMN(result, 1, {Value()})); |
268 | REQUIRE(CHECK_COLUMN(result, 2, {Value()})); |
269 | REQUIRE(CHECK_COLUMN(result, 3, {Value()})); |
270 | REQUIRE(CHECK_COLUMN(result, 4, {Value()})); |
271 | REQUIRE(CHECK_COLUMN(result, 5, {Value()})); |
272 | |
273 | // invalid input to POW function |
274 | result = con.Query("SELECT POW(1e300,100), POW(-1e300,100), POW(-1.0, 0.5)" ); |
275 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
276 | REQUIRE(CHECK_COLUMN(result, 1, {Value()})); |
277 | REQUIRE(CHECK_COLUMN(result, 2, {Value()})); |
278 | |
279 | // overflow in EXP function |
280 | result = con.Query("SELECT EXP(1e300), EXP(1e100)" ); |
281 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
282 | REQUIRE(CHECK_COLUMN(result, 1, {Value()})); |
283 | |
284 | // invalid input to trigonometric functions |
285 | result = con.Query("SELECT ACOS(3), ACOS(100), DEGREES(1e308)" ); |
286 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
287 | REQUIRE(CHECK_COLUMN(result, 1, {Value()})); |
288 | REQUIRE(CHECK_COLUMN(result, 2, {Value()})); |
289 | } |
290 | |