1 | //===--------------------------------------------------------------------===// |
2 | // null_operators.cpp |
3 | // Description: This file contains the implementation of the |
4 | // IS NULL/NOT IS NULL operators |
5 | //===--------------------------------------------------------------------===// |
6 | |
7 | #include "duckdb/common/exception.hpp" |
8 | #include "duckdb/common/vector_operations/vector_operations.hpp" |
9 | |
10 | namespace duckdb { |
11 | |
12 | template <bool INVERSE> |
13 | void IsNullLoop(Vector &input, Vector &result, idx_t count) { |
14 | D_ASSERT(result.GetType() == LogicalType::BOOLEAN); |
15 | |
16 | if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { |
17 | result.SetVectorType(VectorType::CONSTANT_VECTOR); |
18 | auto result_data = ConstantVector::GetData<bool>(vector&: result); |
19 | *result_data = INVERSE ? !ConstantVector::IsNull(vector: input) : ConstantVector::IsNull(vector: input); |
20 | } else { |
21 | UnifiedVectorFormat data; |
22 | input.ToUnifiedFormat(count, data); |
23 | |
24 | result.SetVectorType(VectorType::FLAT_VECTOR); |
25 | auto result_data = FlatVector::GetData<bool>(vector&: result); |
26 | for (idx_t i = 0; i < count; i++) { |
27 | auto idx = data.sel->get_index(idx: i); |
28 | result_data[i] = INVERSE ? data.validity.RowIsValid(row_idx: idx) : !data.validity.RowIsValid(row_idx: idx); |
29 | } |
30 | } |
31 | } |
32 | |
33 | void VectorOperations::IsNotNull(Vector &input, Vector &result, idx_t count) { |
34 | IsNullLoop<true>(input, result, count); |
35 | } |
36 | |
37 | void VectorOperations::IsNull(Vector &input, Vector &result, idx_t count) { |
38 | IsNullLoop<false>(input, result, count); |
39 | } |
40 | |
41 | bool VectorOperations::HasNotNull(Vector &input, idx_t count) { |
42 | if (count == 0) { |
43 | return false; |
44 | } |
45 | if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { |
46 | return !ConstantVector::IsNull(vector: input); |
47 | } else { |
48 | UnifiedVectorFormat data; |
49 | input.ToUnifiedFormat(count, data); |
50 | |
51 | if (data.validity.AllValid()) { |
52 | return true; |
53 | } |
54 | for (idx_t i = 0; i < count; i++) { |
55 | auto idx = data.sel->get_index(idx: i); |
56 | if (data.validity.RowIsValid(row_idx: idx)) { |
57 | return true; |
58 | } |
59 | } |
60 | return false; |
61 | } |
62 | } |
63 | |
64 | bool VectorOperations::HasNull(Vector &input, idx_t count) { |
65 | if (count == 0) { |
66 | return false; |
67 | } |
68 | if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { |
69 | return ConstantVector::IsNull(vector: input); |
70 | } else { |
71 | UnifiedVectorFormat data; |
72 | input.ToUnifiedFormat(count, data); |
73 | |
74 | if (data.validity.AllValid()) { |
75 | return false; |
76 | } |
77 | for (idx_t i = 0; i < count; i++) { |
78 | auto idx = data.sel->get_index(idx: i); |
79 | if (!data.validity.RowIsValid(row_idx: idx)) { |
80 | return true; |
81 | } |
82 | } |
83 | return false; |
84 | } |
85 | } |
86 | |
87 | idx_t VectorOperations::CountNotNull(Vector &input, const idx_t count) { |
88 | idx_t valid = 0; |
89 | |
90 | UnifiedVectorFormat vdata; |
91 | input.ToUnifiedFormat(count, data&: vdata); |
92 | if (vdata.validity.AllValid()) { |
93 | return count; |
94 | } |
95 | switch (input.GetVectorType()) { |
96 | case VectorType::FLAT_VECTOR: |
97 | valid += vdata.validity.CountValid(count); |
98 | break; |
99 | case VectorType::CONSTANT_VECTOR: |
100 | valid += vdata.validity.CountValid(count: 1) * count; |
101 | break; |
102 | default: |
103 | for (idx_t i = 0; i < count; ++i) { |
104 | const auto row_idx = vdata.sel->get_index(idx: i); |
105 | valid += int(vdata.validity.RowIsValid(row_idx)); |
106 | } |
107 | break; |
108 | } |
109 | |
110 | return valid; |
111 | } |
112 | |
113 | } // namespace duckdb |
114 | |