1#include "duckdb/function/aggregate/distributive_functions.hpp"
2#include "duckdb/common/exception.hpp"
3#include "duckdb/common/types/null_value.hpp"
4#include "duckdb/common/vector_operations/vector_operations.hpp"
5#include "duckdb/common/vector_operations/aggregate_executor.hpp"
6#include "duckdb/common/operator/numeric_binary_operators.hpp"
7
8using namespace std;
9
10namespace duckdb {
11
12template <class OP> static AggregateFunction GetBitfieldUnaryAggregate(SQLType type) {
13 switch (type.id) {
14 case SQLTypeId::TINYINT:
15 return AggregateFunction::UnaryAggregate<uint8_t, int8_t, int8_t, OP>(type, type);
16 case SQLTypeId::SMALLINT:
17 return AggregateFunction::UnaryAggregate<uint16_t, int16_t, int16_t, OP>(type, type);
18 case SQLTypeId::INTEGER:
19 return AggregateFunction::UnaryAggregate<uint32_t, int32_t, int32_t, OP>(type, type);
20 case SQLTypeId::BIGINT:
21 return AggregateFunction::UnaryAggregate<uint64_t, int64_t, int64_t, OP>(type, type);
22 default:
23 throw NotImplementedException("Unimplemented bitfield type for unary aggregate");
24 }
25}
26
27struct BitAndOperation {
28 template <class STATE> static void Initialize(STATE *state) {
29 // If there are no matching rows, BIT_AND() returns a neutral value (all bits set to 1)
30 // having the same length as the argument values.
31 *state = 0;
32 *state = ~*state;
33 }
34
35 template <class INPUT_TYPE, class STATE, class OP>
36 static void Operation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t idx) {
37 *state &= STATE(input[idx]);
38 }
39
40 template <class INPUT_TYPE, class STATE, class OP>
41 static void ConstantOperation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t count) {
42 // count is irrelevant
43 Operation<INPUT_TYPE, STATE, OP>(state, input, nullmask, 0);
44 }
45
46 template <class T, class STATE>
47 static void Finalize(Vector &result, STATE *state, T *target, nullmask_t &nullmask, idx_t idx) {
48 target[idx] = T(*state);
49 }
50
51 template <class STATE, class OP> static void Combine(STATE source, STATE *target) {
52 *target &= source;
53 }
54
55 static bool IgnoreNull() {
56 return true;
57 }
58};
59
60void BitAndFun::RegisterFunction(BuiltinFunctions &set) {
61 AggregateFunctionSet bit_and("bit_and");
62 for (auto type : SQLType::INTEGRAL) {
63 bit_and.AddFunction(GetBitfieldUnaryAggregate<BitAndOperation>(type));
64 }
65 set.AddFunction(bit_and);
66}
67
68struct BitOrOperation {
69 template <class STATE> static void Initialize(STATE *state) {
70 // If there are no matching rows, BIT_OR() returns a neutral value (all bits set to 0)
71 // having the same length as the argument values.
72 *state = 0;
73 }
74
75 template <class INPUT_TYPE, class STATE, class OP>
76 static void Operation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t idx) {
77 *state |= STATE(input[idx]);
78 }
79
80 template <class INPUT_TYPE, class STATE, class OP>
81 static void ConstantOperation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t count) {
82 // count is irrelevant
83 Operation<INPUT_TYPE, STATE, OP>(state, input, nullmask, 0);
84 }
85
86 template <class T, class STATE>
87 static void Finalize(Vector &result, STATE *state, T *target, nullmask_t &nullmask, idx_t idx) {
88 target[idx] = T(*state);
89 }
90
91 template <class STATE, class OP> static void Combine(STATE source, STATE *target) {
92 *target |= source;
93 }
94
95 static bool IgnoreNull() {
96 return true;
97 }
98};
99
100void BitOrFun::RegisterFunction(BuiltinFunctions &set) {
101 AggregateFunctionSet bit_or("bit_or");
102 for (auto type : SQLType::INTEGRAL) {
103 bit_or.AddFunction(GetBitfieldUnaryAggregate<BitOrOperation>(type));
104 }
105 set.AddFunction(bit_or);
106}
107
108struct BitXorOperation {
109 template <class STATE> static void Initialize(STATE *state) {
110 // If there are no matching rows, BIT_XOR() returns a neutral value (all bits set to 0)
111 // having the same length as the argument values.
112 *state = 0;
113 }
114
115 template <class INPUT_TYPE, class STATE, class OP>
116 static void Operation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t idx) {
117 *state ^= STATE(input[idx]);
118 }
119
120 template <class INPUT_TYPE, class STATE, class OP>
121 static void ConstantOperation(STATE *state, INPUT_TYPE *input, nullmask_t &nullmask, idx_t count) {
122 // count is irrelevant
123 Operation<INPUT_TYPE, STATE, OP>(state, input, nullmask, 0);
124 }
125
126 template <class T, class STATE>
127 static void Finalize(Vector &result, STATE *state, T *target, nullmask_t &nullmask, idx_t idx) {
128 target[idx] = T(*state);
129 }
130
131 template <class STATE, class OP> static void Combine(STATE source, STATE *target) {
132 *target ^= source;
133 }
134
135 static bool IgnoreNull() {
136 return true;
137 }
138};
139
140void BitXorFun::RegisterFunction(BuiltinFunctions &set) {
141 AggregateFunctionSet bit_xor("bit_xor");
142 for (auto type : SQLType::INTEGRAL) {
143 bit_xor.AddFunction(GetBitfieldUnaryAggregate<BitXorOperation>(type));
144 }
145 set.AddFunction(bit_xor);
146}
147
148} // namespace duckdb
149