Skip to content

Commit 719da34

Browse files
Update vendored DuckDB sources to b8990f49dd
1 parent e6c5c2c commit 719da34

9 files changed

Lines changed: 306 additions & 8 deletions

File tree

src/duckdb/src/catalog/catalog_set.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "duckdb/common/exception.hpp"
88
#include "duckdb/common/serializer/memory_stream.hpp"
99
#include "duckdb/common/serializer/binary_serializer.hpp"
10+
#include "duckdb/catalog/catalog_entry/dependency/dependency_entry.hpp"
1011
#include "duckdb/common/string_util.hpp"
1112
#include "duckdb/parser/expression/constant_expression.hpp"
1213
#include "duckdb/parser/parsed_data/alter_table_info.hpp"

src/duckdb/src/function/function_list.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,13 @@ static const StaticFunctionDefinition function[] = {
159159
DUCKDB_SCALAR_FUNCTION(StrlenFun),
160160
DUCKDB_SCALAR_FUNCTION_SET(StrpTimeFun),
161161
DUCKDB_SCALAR_FUNCTION(StructConcatFun),
162+
DUCKDB_SCALAR_FUNCTION(StructContainsFun),
162163
DUCKDB_SCALAR_FUNCTION_SET(StructExtractFun),
163164
DUCKDB_SCALAR_FUNCTION(StructExtractAtFun),
165+
DUCKDB_SCALAR_FUNCTION_ALIAS(StructHasFun),
166+
DUCKDB_SCALAR_FUNCTION_ALIAS(StructIndexofFun),
164167
DUCKDB_SCALAR_FUNCTION(StructPackFun),
168+
DUCKDB_SCALAR_FUNCTION(StructPositionFun),
165169
DUCKDB_SCALAR_FUNCTION_SET_ALIAS(SubstrFun),
166170
DUCKDB_SCALAR_FUNCTION_SET(SubstringFun),
167171
DUCKDB_SCALAR_FUNCTION_SET(SubstringGraphemeFun),

src/duckdb/src/function/scalar/string/contains.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "duckdb/function/scalar/map_functions.hpp"
55
#include "duckdb/function/scalar/string_common.hpp"
66
#include "duckdb/function/scalar/string_functions.hpp"
7+
#include "duckdb/function/scalar/struct_functions.hpp"
78
#include "duckdb/planner/expression/bound_function_expression.hpp"
89

910
namespace duckdb {
@@ -124,10 +125,12 @@ ScalarFunctionSet ContainsFun::GetFunctions() {
124125
auto string_fun = GetStringContains();
125126
auto list_fun = ListContainsFun::GetFunction();
126127
auto map_fun = MapContainsFun::GetFunction();
128+
auto struct_fun = StructContainsFun::GetFunction();
127129
ScalarFunctionSet set("contains");
128130
set.AddFunction(string_fun);
129131
set.AddFunction(list_fun);
130132
set.AddFunction(map_fun);
133+
set.AddFunction(struct_fun);
131134
return set;
132135
}
133136

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
#include "duckdb/common/string_util.hpp"
2+
#include "duckdb/execution/expression_executor.hpp"
3+
#include "duckdb/function/scalar/struct_functions.hpp"
4+
#include "duckdb/function/scalar/list/contains_or_position.hpp"
5+
6+
namespace duckdb {
7+
8+
template <class T, class RETURN_TYPE, bool FIND_NULLS>
9+
static void TemplatedStructSearch(Vector &input_vector, vector<unique_ptr<Vector>> &members, Vector &target,
10+
const idx_t count, Vector &result) {
11+
// If the return type is not a bool, return the position
12+
const auto return_pos = std::is_same<RETURN_TYPE, int32_t>::value;
13+
14+
const auto &target_type = target.GetType();
15+
16+
UnifiedVectorFormat vector_format;
17+
input_vector.ToUnifiedFormat(count, vector_format);
18+
19+
UnifiedVectorFormat target_format;
20+
target.ToUnifiedFormat(count, target_format);
21+
const auto target_data = UnifiedVectorFormat::GetData<T>(target_format);
22+
23+
vector<const T *> member_datas;
24+
vector<UnifiedVectorFormat> member_vectors;
25+
idx_t total_matches = 0;
26+
for (const auto &member : members) {
27+
if (member->GetType().InternalType() == target_type.InternalType()) {
28+
UnifiedVectorFormat member_format;
29+
member->ToUnifiedFormat(count, member_format);
30+
member_datas.push_back(UnifiedVectorFormat::GetData<T>(member_format));
31+
member_vectors.push_back(std::move(member_format));
32+
total_matches++;
33+
} else {
34+
member_datas.push_back(nullptr);
35+
member_vectors.push_back(UnifiedVectorFormat());
36+
}
37+
}
38+
39+
if (total_matches == 0 && return_pos) {
40+
// if there are no members that match the target type, we cannot return a position
41+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
42+
ConstantVector::SetNull(result, true);
43+
return;
44+
}
45+
46+
result.SetVectorType(VectorType::FLAT_VECTOR);
47+
auto result_data = FlatVector::GetData<RETURN_TYPE>(result);
48+
auto &result_validity = FlatVector::Validity(result);
49+
50+
const auto member_count = members.size();
51+
for (idx_t row = 0; row < count; row++) {
52+
const auto &member_row_idx = vector_format.sel->get_index(row);
53+
54+
if (!vector_format.validity.RowIsValid(member_row_idx)) {
55+
result_validity.SetInvalid(row);
56+
continue;
57+
}
58+
59+
const auto &target_row_idx = target_format.sel->get_index(row);
60+
const bool target_valid = target_format.validity.RowIsValid(target_row_idx);
61+
62+
// We are finished if we are not looking for NULL, and the target is NULL.
63+
const auto finished = !FIND_NULLS && !target_valid;
64+
// We did not find the target (finished, or struct is empty).
65+
if (finished) {
66+
if (!target_valid || return_pos) {
67+
result_validity.SetInvalid(row);
68+
} else {
69+
result_data[row] = false;
70+
}
71+
continue;
72+
}
73+
74+
bool found = false;
75+
76+
for (idx_t member_idx = 0; member_idx < member_count; member_idx++) {
77+
auto &member_data = member_datas[member_idx];
78+
if (!member_data) {
79+
continue; // skip if member data is not compatible with the target type
80+
}
81+
const auto &member_vector = member_vectors[member_idx];
82+
const auto member_data_idx = member_vector.sel->get_index(row);
83+
const auto col_valid = member_vector.validity.RowIsValid(member_data_idx);
84+
85+
auto is_null = FIND_NULLS && !col_valid && !target_valid;
86+
auto both_valid_and_match = col_valid && target_valid &&
87+
Equals::Operation<T>(member_data[member_data_idx], target_data[target_row_idx]);
88+
89+
if (is_null || both_valid_and_match) {
90+
found = true;
91+
if (return_pos) {
92+
result_data[row] = UnsafeNumericCast<int32_t>(member_idx + 1);
93+
} else {
94+
result_data[row] = true;
95+
}
96+
}
97+
}
98+
99+
if (!found) {
100+
if (return_pos) {
101+
result_validity.SetInvalid(row);
102+
} else {
103+
result_data[row] = false;
104+
}
105+
}
106+
}
107+
}
108+
109+
template <class RETURN_TYPE, bool FIND_NULLS>
110+
static void StructNestedOp(Vector &input_vector, vector<unique_ptr<Vector>> &members, Vector &target, const idx_t count,
111+
Vector &result) {
112+
const OrderModifiers order_modifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST);
113+
114+
// Set up sort keys for nested types.
115+
const auto members_size = members.size();
116+
vector<unique_ptr<Vector>> member_sort_key_vectors;
117+
for (idx_t i = 0; i < members_size; i++) {
118+
Vector member_sort_key_vec(LogicalType::BLOB, count);
119+
CreateSortKeyHelpers::CreateSortKeyWithValidity(*members[i], member_sort_key_vec, order_modifiers, count);
120+
121+
auto member_sort_key_ptr = make_uniq<Vector>(member_sort_key_vec);
122+
member_sort_key_vectors.push_back(std::move(member_sort_key_ptr));
123+
}
124+
125+
Vector target_sort_key_vec(LogicalType::BLOB, count);
126+
CreateSortKeyHelpers::CreateSortKeyWithValidity(target, target_sort_key_vec, order_modifiers, count);
127+
128+
TemplatedStructSearch<string_t, RETURN_TYPE, FIND_NULLS>(input_vector, member_sort_key_vectors, target_sort_key_vec,
129+
count, result);
130+
}
131+
132+
template <class RETURN_TYPE, bool FIND_NULLS>
133+
static void StructSearchOp(Vector &input_vector, vector<unique_ptr<Vector>> &members, Vector &target, const idx_t count,
134+
Vector &result) {
135+
const auto &target_type = target.GetType().InternalType();
136+
switch (target_type) {
137+
case PhysicalType::BOOL:
138+
case PhysicalType::INT8:
139+
return TemplatedStructSearch<int8_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
140+
case PhysicalType::INT16:
141+
return TemplatedStructSearch<int16_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
142+
case PhysicalType::INT32:
143+
return TemplatedStructSearch<int32_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
144+
case PhysicalType::INT64:
145+
return TemplatedStructSearch<int64_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
146+
case PhysicalType::INT128:
147+
return TemplatedStructSearch<hugeint_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
148+
case PhysicalType::UINT8:
149+
return TemplatedStructSearch<uint8_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
150+
case PhysicalType::UINT16:
151+
return TemplatedStructSearch<uint16_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
152+
case PhysicalType::UINT32:
153+
return TemplatedStructSearch<uint32_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
154+
case PhysicalType::UINT64:
155+
return TemplatedStructSearch<uint64_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
156+
case PhysicalType::UINT128:
157+
return TemplatedStructSearch<uhugeint_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
158+
case PhysicalType::FLOAT:
159+
return TemplatedStructSearch<float, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
160+
case PhysicalType::DOUBLE:
161+
return TemplatedStructSearch<double, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
162+
case PhysicalType::VARCHAR:
163+
return TemplatedStructSearch<string_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
164+
case PhysicalType::INTERVAL:
165+
return TemplatedStructSearch<interval_t, RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
166+
case PhysicalType::STRUCT:
167+
case PhysicalType::LIST:
168+
case PhysicalType::ARRAY:
169+
return StructNestedOp<RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
170+
default:
171+
throw NotImplementedException("This function has not been implemented for logical type %s",
172+
TypeIdToString(target_type));
173+
}
174+
}
175+
176+
template <class RETURN_TYPE, bool FIND_NULLS = false>
177+
static void StructSearchFunction(DataChunk &args, ExpressionState &state, Vector &result) {
178+
if (result.GetType().id() == LogicalTypeId::SQLNULL) {
179+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
180+
ConstantVector::SetNull(result, true);
181+
return;
182+
}
183+
184+
const auto count = args.size();
185+
auto &input_vector = args.data[0];
186+
auto &members = StructVector::GetEntries(input_vector);
187+
auto &target = args.data[1];
188+
189+
StructSearchOp<RETURN_TYPE, FIND_NULLS>(input_vector, members, target, count, result);
190+
191+
if (args.AllConstant()) {
192+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
193+
}
194+
}
195+
196+
static unique_ptr<FunctionData> StructContainsBind(ClientContext &context, ScalarFunction &bound_function,
197+
vector<unique_ptr<Expression>> &arguments) {
198+
D_ASSERT(bound_function.arguments.size() == 2);
199+
auto &child_type = arguments[0]->return_type;
200+
if (child_type.id() == LogicalTypeId::UNKNOWN) {
201+
throw ParameterNotResolvedException();
202+
}
203+
204+
if (child_type.id() == LogicalTypeId::SQLNULL) {
205+
bound_function.arguments[0] = LogicalTypeId::UNKNOWN;
206+
bound_function.arguments[1] = LogicalTypeId::UNKNOWN;
207+
bound_function.return_type = LogicalType::SQLNULL;
208+
return nullptr;
209+
}
210+
211+
auto &struct_children = StructType::GetChildTypes(arguments[0]->return_type);
212+
if (struct_children.empty()) {
213+
throw InternalException("Can't check for containment in an empty struct");
214+
}
215+
if (!StructType::IsUnnamed(child_type)) {
216+
throw BinderException("%s can only be used on unnamed structs", bound_function.name);
217+
}
218+
bound_function.arguments[0] = child_type;
219+
220+
// the value type must match one of the struct's children
221+
LogicalType max_child_type = arguments[1]->return_type;
222+
vector<LogicalType> new_child_types;
223+
for (auto &child : struct_children) {
224+
if (!LogicalType::TryGetMaxLogicalType(context, child.second, max_child_type, max_child_type)) {
225+
new_child_types.push_back(child.second);
226+
continue;
227+
}
228+
229+
new_child_types.push_back(max_child_type);
230+
bound_function.arguments[1] = max_child_type;
231+
}
232+
233+
child_list_t<LogicalType> cast_children;
234+
for (idx_t i = 0; i < new_child_types.size(); i++) {
235+
cast_children.push_back(make_pair(struct_children[i].first, new_child_types[i]));
236+
}
237+
238+
bound_function.arguments[0] = LogicalType::STRUCT(cast_children);
239+
240+
return nullptr;
241+
}
242+
243+
ScalarFunction StructContainsFun::GetFunction() {
244+
return ScalarFunction("struct_contains", {LogicalTypeId::STRUCT, LogicalType::ANY}, LogicalType::BOOLEAN,
245+
StructSearchFunction<bool>, StructContainsBind);
246+
}
247+
248+
ScalarFunction StructPositionFun::GetFunction() {
249+
ScalarFunction fun("struct_contains", {LogicalTypeId::STRUCT, LogicalType::ANY}, LogicalType::INTEGER,
250+
StructSearchFunction<int32_t, true>, StructContainsBind);
251+
fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING;
252+
return fun;
253+
}
254+
255+
} // namespace duckdb

src/duckdb/src/function/table/version/pragma_version.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef DUCKDB_PATCH_VERSION
2-
#define DUCKDB_PATCH_VERSION "0-dev752"
2+
#define DUCKDB_PATCH_VERSION "0-dev761"
33
#endif
44
#ifndef DUCKDB_MINOR_VERSION
55
#define DUCKDB_MINOR_VERSION 4
@@ -8,10 +8,10 @@
88
#define DUCKDB_MAJOR_VERSION 1
99
#endif
1010
#ifndef DUCKDB_VERSION
11-
#define DUCKDB_VERSION "v1.4.0-dev752"
11+
#define DUCKDB_VERSION "v1.4.0-dev761"
1212
#endif
1313
#ifndef DUCKDB_SOURCE_ID
14-
#define DUCKDB_SOURCE_ID "23f4de5996"
14+
#define DUCKDB_SOURCE_ID "b8990f49dd"
1515
#endif
1616
#include "duckdb/function/table/system_functions.hpp"
1717
#include "duckdb/main/database.hpp"

src/duckdb/src/include/duckdb/function/scalar/list/contains_or_position.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace duckdb {
66

7-
template <class T, class RETURN_TYPE, bool FIND_NULLS = false>
7+
template <class T, class RETURN_TYPE, bool FIND_NULLS>
88
idx_t ListSearchSimpleOp(Vector &input_list, Vector &list_child, Vector &target, Vector &result, const idx_t count) {
99
// If the return type is not a bool, return the position
1010
const auto return_pos = std::is_same<RETURN_TYPE, int32_t>::value;
@@ -89,7 +89,7 @@ idx_t ListSearchSimpleOp(Vector &input_list, Vector &list_child, Vector &target,
8989
return total_matches;
9090
}
9191

92-
template <class RETURN_TYPE>
92+
template <class RETURN_TYPE, bool FIND_NULLS>
9393
idx_t ListSearchNestedOp(Vector &list_vec, Vector &source_vec, Vector &target_vec, Vector &result_vec,
9494
const idx_t target_count) {
9595
// Set up sort keys for nested types.
@@ -101,8 +101,8 @@ idx_t ListSearchNestedOp(Vector &list_vec, Vector &source_vec, Vector &target_ve
101101
CreateSortKeyHelpers::CreateSortKeyWithValidity(source_vec, source_sort_key_vec, order_modifiers, source_count);
102102
CreateSortKeyHelpers::CreateSortKeyWithValidity(target_vec, target_sort_key_vec, order_modifiers, target_count);
103103

104-
return ListSearchSimpleOp<string_t, RETURN_TYPE>(list_vec, source_sort_key_vec, target_sort_key_vec, result_vec,
105-
target_count);
104+
return ListSearchSimpleOp<string_t, RETURN_TYPE, FIND_NULLS>(list_vec, source_sort_key_vec, target_sort_key_vec,
105+
result_vec, target_count);
106106
}
107107

108108
//! "Search" each list in the list vector for the corresponding value in the target vector, returning either
@@ -152,7 +152,7 @@ idx_t ListSearchOp(Vector &list_v, Vector &source_v, Vector &target_v, Vector &r
152152
case PhysicalType::STRUCT:
153153
case PhysicalType::LIST:
154154
case PhysicalType::ARRAY:
155-
return ListSearchNestedOp<RETURN_TYPE>(list_v, source_v, target_v, result_v, target_count);
155+
return ListSearchNestedOp<RETURN_TYPE, FIND_NULLS>(list_v, source_v, target_v, result_v, target_count);
156156
default:
157157
throw NotImplementedException("This function has not been implemented for logical type %s",
158158
TypeIdToString(type));

src/duckdb/src/include/duckdb/function/scalar/struct_functions.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,36 @@ struct StructConcatFun {
7676
static ScalarFunction GetFunction();
7777
};
7878

79+
struct StructContainsFun {
80+
static constexpr const char *Name = "struct_contains";
81+
static constexpr const char *Parameters = "struct,'entry'";
82+
static constexpr const char *Description = "Check if an unnamed STRUCT contains the value.";
83+
static constexpr const char *Example = "struct_contains(ROW(3, 3, 0), 3)";
84+
static constexpr const char *Categories = "";
85+
86+
static ScalarFunction GetFunction();
87+
};
88+
89+
struct StructHasFun {
90+
using ALIAS = StructContainsFun;
91+
92+
static constexpr const char *Name = "struct_has";
93+
};
94+
95+
struct StructPositionFun {
96+
static constexpr const char *Name = "struct_position";
97+
static constexpr const char *Parameters = "struct,'entry'";
98+
static constexpr const char *Description = "Get the position of the entry in an unnamed STRUCT, starting at 1.";
99+
static constexpr const char *Example = "struct_position(ROW(3, 3, 0), 3)";
100+
static constexpr const char *Categories = "";
101+
102+
static ScalarFunction GetFunction();
103+
};
104+
105+
struct StructIndexofFun {
106+
using ALIAS = StructPositionFun;
107+
108+
static constexpr const char *Name = "struct_indexof";
109+
};
110+
79111
} // namespace duckdb

0 commit comments

Comments
 (0)