| 1 | #include "catch.hpp" |
| 2 | #include "test_helpers.hpp" |
| 3 | |
| 4 | using namespace duckdb; |
| 5 | using namespace std; |
| 6 | |
| 7 | TEST_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 | |
| 76 | TEST_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 | |
| 100 | TEST_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 | |