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
10namespace duckdb {
11
12template <bool INVERSE>
13void 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
33void VectorOperations::IsNotNull(Vector &input, Vector &result, idx_t count) {
34 IsNullLoop<true>(input, result, count);
35}
36
37void VectorOperations::IsNull(Vector &input, Vector &result, idx_t count) {
38 IsNullLoop<false>(input, result, count);
39}
40
41bool 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
64bool 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
87idx_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