1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7TEST_CASE("Test scalar bitwise ops", "[bitop]") {
8 unique_ptr<QueryResult> result;
9 DuckDB db(nullptr);
10 Connection con(db);
11 con.EnableQueryVerification();
12
13 // left shift
14 result = con.Query("SELECT 1 << 2, NULL << 2, 2 << NULL");
15 REQUIRE(CHECK_COLUMN(result, 0, {4}));
16 REQUIRE(CHECK_COLUMN(result, 1, {Value()}));
17 REQUIRE(CHECK_COLUMN(result, 2, {Value()}));
18
19 // right shift
20 result = con.Query("SELECT 16 >> 2, 1 >> 2, NULL >> 2, 2 >> NULL");
21 REQUIRE(CHECK_COLUMN(result, 0, {4}));
22 REQUIRE(CHECK_COLUMN(result, 1, {0}));
23 REQUIRE(CHECK_COLUMN(result, 2, {Value()}));
24 REQUIRE(CHECK_COLUMN(result, 3, {Value()}));
25
26 // bitwise and
27 result = con.Query("SELECT 1 & 1, 1 & 0, 0 & 0, NULL & 1, 1 & NULL");
28 REQUIRE(CHECK_COLUMN(result, 0, {1}));
29 REQUIRE(CHECK_COLUMN(result, 1, {0}));
30 REQUIRE(CHECK_COLUMN(result, 2, {0}));
31 REQUIRE(CHECK_COLUMN(result, 3, {Value()}));
32 REQUIRE(CHECK_COLUMN(result, 4, {Value()}));
33
34 // bitwise or
35 result = con.Query("SELECT 1 | 1, 1 | 0, 0 | 0, NULL | 1, 1 | NULL");
36 REQUIRE(CHECK_COLUMN(result, 0, {1}));
37 REQUIRE(CHECK_COLUMN(result, 1, {1}));
38 REQUIRE(CHECK_COLUMN(result, 2, {0}));
39 REQUIRE(CHECK_COLUMN(result, 3, {Value()}));
40 REQUIRE(CHECK_COLUMN(result, 4, {Value()}));
41
42 // bitwise xor
43 result = con.Query("SELECT 1 # 1, 1 # 0, 0 # 0, NULL # 1, 1 # NULL");
44 REQUIRE(CHECK_COLUMN(result, 0, {0}));
45 REQUIRE(CHECK_COLUMN(result, 1, {1}));
46 REQUIRE(CHECK_COLUMN(result, 2, {0}));
47 REQUIRE(CHECK_COLUMN(result, 3, {Value()}));
48 REQUIRE(CHECK_COLUMN(result, 4, {Value()}));
49
50 // out of range shifts return 0
51 result = con.Query("SELECT 1::TINYINT << -1::TINYINT, 1::TINYINT >> -1::TINYINT, 1::TINYINT << 12::TINYINT, "
52 "1::TINYINT >> 12::TINYINT");
53 REQUIRE(CHECK_COLUMN(result, 0, {0}));
54 REQUIRE(CHECK_COLUMN(result, 1, {0}));
55 REQUIRE(CHECK_COLUMN(result, 2, {0}));
56 REQUIRE(CHECK_COLUMN(result, 3, {0}));
57 result = con.Query("SELECT 1::SMALLINT << -1::SMALLINT, 1::SMALLINT >> -1::SMALLINT, 1::SMALLINT << 20::SMALLINT, "
58 "1::SMALLINT >> 20::SMALLINT");
59 REQUIRE(CHECK_COLUMN(result, 0, {0}));
60 REQUIRE(CHECK_COLUMN(result, 1, {0}));
61 REQUIRE(CHECK_COLUMN(result, 2, {0}));
62 REQUIRE(CHECK_COLUMN(result, 3, {0}));
63 result = con.Query("SELECT 1::INT << -1::INT, 1::INT >> -1::INT, 1::INT << 40::INT, 1::INT >> 40::INT");
64 REQUIRE(CHECK_COLUMN(result, 0, {0}));
65 REQUIRE(CHECK_COLUMN(result, 1, {0}));
66 REQUIRE(CHECK_COLUMN(result, 2, {0}));
67 REQUIRE(CHECK_COLUMN(result, 3, {0}));
68 result = con.Query("SELECT 1::BIGINT << -1::BIGINT, 1::BIGINT >> -1::BIGINT, 1::BIGINT << 1000::BIGINT, 1::BIGINT "
69 ">> 1000::BIGINT");
70 REQUIRE(CHECK_COLUMN(result, 0, {0}));
71 REQUIRE(CHECK_COLUMN(result, 1, {0}));
72 REQUIRE(CHECK_COLUMN(result, 2, {0}));
73 REQUIRE(CHECK_COLUMN(result, 3, {0}));
74}
75
76TEST_CASE("Test bitwise ops with tables and different types", "[bitop]") {
77 unique_ptr<QueryResult> result;
78 DuckDB db(nullptr);
79 Connection con(db);
80 con.EnableQueryVerification();
81
82 vector<string> types = {"TINYINT", "SMALLINT", "INTEGER", "BIGINT"};
83 for (auto &type : types) {
84 REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION"));
85 REQUIRE_NO_FAIL(con.Query("CREATE TABLE bitwise_test(i " + type + ", j " + type + ")"));
86 REQUIRE_NO_FAIL(con.Query(
87 "INSERT INTO bitwise_test VALUES (1, 1), (1, 0), (0, 1), (0, 0), (1, NULL), (NULL, 1), (NULL, NULL)"));
88
89 result = con.Query("SELECT i << j, i >> j, i & j, i | j, i # j FROM bitwise_test");
90 REQUIRE(CHECK_COLUMN(result, 0, {2, 1, 0, 0, Value(), Value(), Value()}));
91 REQUIRE(CHECK_COLUMN(result, 1, {0, 1, 0, 0, Value(), Value(), Value()}));
92 REQUIRE(CHECK_COLUMN(result, 2, {1, 0, 0, 0, Value(), Value(), Value()}));
93 REQUIRE(CHECK_COLUMN(result, 3, {1, 1, 1, 0, Value(), Value(), Value()}));
94 REQUIRE(CHECK_COLUMN(result, 4, {0, 1, 1, 0, Value(), Value(), Value()}));
95
96 REQUIRE_NO_FAIL(con.Query("ROLLBACK"));
97 }
98}
99
100TEST_CASE("Test invalid ops for bitwise operations", "[bitop]") {
101 unique_ptr<QueryResult> result;
102 DuckDB db(nullptr);
103 Connection con(db);
104 con.EnableQueryVerification();
105
106 REQUIRE_FAIL(con.Query("SELECT 'hello' << 3"));
107 REQUIRE_FAIL(con.Query("SELECT 3 << 'hello'"));
108 REQUIRE_FAIL(con.Query("SELECT 2.0 << 1"));
109}
110