Skip to content

Commit cdd22fc

Browse files
committed
vendor duckdb 1.2.0
1 parent 47f242f commit cdd22fc

File tree

218 files changed

+3129
-1641
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

218 files changed

+3129
-1641
lines changed

binding.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@
306306
"src/duckdb/extension/icu/./icu-makedate.cpp",
307307
"src/duckdb/extension/icu/./icu-list-range.cpp",
308308
"src/duckdb/extension/icu/./icu-timebucket.cpp",
309+
"src/duckdb/extension/icu/./icu-current.cpp",
309310
"src/duckdb/extension/icu/./icu-timezone.cpp",
310311
"src/duckdb/extension/icu/./icu-dateadd.cpp",
311312
"src/duckdb/extension/icu/./icu-datetrunc.cpp",

src/duckdb/extension/core_functions/function_list.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ static const StaticFunctionDefinition core_functions[] = {
266266
DUCKDB_SCALAR_FUNCTION(MapConcatFun),
267267
DUCKDB_SCALAR_FUNCTION(MapEntriesFun),
268268
DUCKDB_SCALAR_FUNCTION(MapExtractFun),
269+
DUCKDB_SCALAR_FUNCTION(MapExtractValueFun),
269270
DUCKDB_SCALAR_FUNCTION(MapFromEntriesFun),
270271
DUCKDB_SCALAR_FUNCTION(MapKeysFun),
271272
DUCKDB_SCALAR_FUNCTION(MapValuesFun),

src/duckdb/extension/core_functions/include/core_functions/scalar/map_functions.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ struct ElementAtFun {
5757
static constexpr const char *Name = "element_at";
5858
};
5959

60+
struct MapExtractValueFun {
61+
static constexpr const char *Name = "map_extract_value";
62+
static constexpr const char *Parameters = "map,key";
63+
static constexpr const char *Description = "Returns the value for a given key or NULL if the key is not contained in the map. The type of the key provided in the second parameter must match the type of the map’s keys else an error is returned";
64+
static constexpr const char *Example = "map_extract_value(map(['key'], ['val']), 'key')";
65+
66+
static ScalarFunction GetFunction();
67+
};
68+
6069
struct MapFromEntriesFun {
6170
static constexpr const char *Name = "map_from_entries";
6271
static constexpr const char *Parameters = "map";

src/duckdb/extension/core_functions/scalar/date/current.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "duckdb/main/client_context.hpp"
77
#include "duckdb/planner/expression/bound_function_expression.hpp"
88
#include "duckdb/transaction/meta_transaction.hpp"
9+
#include "duckdb/planner/expression/bound_cast_expression.hpp"
910

1011
namespace duckdb {
1112

src/duckdb/extension/core_functions/scalar/generic/can_implicitly_cast.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ static void CanCastImplicitlyFunction(DataChunk &args, ExpressionState &state, V
1818
}
1919

2020
unique_ptr<Expression> BindCanCastImplicitlyExpression(FunctionBindExpressionInput &input) {
21-
auto &source_type = input.function.children[0]->return_type;
22-
auto &target_type = input.function.children[1]->return_type;
21+
auto &source_type = input.children[0]->return_type;
22+
auto &target_type = input.children[1]->return_type;
2323
if (source_type.id() == LogicalTypeId::UNKNOWN || source_type.id() == LogicalTypeId::SQLNULL ||
2424
target_type.id() == LogicalTypeId::UNKNOWN || target_type.id() == LogicalTypeId::SQLNULL) {
2525
// parameter - unknown return type

src/duckdb/extension/core_functions/scalar/generic/typeof.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static void TypeOfFunction(DataChunk &args, ExpressionState &state, Vector &resu
1010
}
1111

1212
unique_ptr<Expression> BindTypeOfFunctionExpression(FunctionBindExpressionInput &input) {
13-
auto &return_type = input.function.children[0]->return_type;
13+
auto &return_type = input.children[0]->return_type;
1414
if (return_type.id() == LogicalTypeId::UNKNOWN || return_type.id() == LogicalTypeId::SQLNULL) {
1515
// parameter - unknown return type
1616
return nullptr;

src/duckdb/extension/core_functions/scalar/list/flatten.cpp

+91-61
Original file line numberDiff line numberDiff line change
@@ -7,102 +7,132 @@
77

88
namespace duckdb {
99

10-
void ListFlattenFunction(DataChunk &args, ExpressionState &state, Vector &result) {
11-
D_ASSERT(args.ColumnCount() == 1);
10+
static void ListFlattenFunction(DataChunk &args, ExpressionState &, Vector &result) {
1211

13-
Vector &input = args.data[0];
14-
if (input.GetType().id() == LogicalTypeId::SQLNULL) {
15-
result.Reference(input);
12+
const auto flat_list_data = FlatVector::GetData<list_entry_t>(result);
13+
auto &flat_list_mask = FlatVector::Validity(result);
14+
15+
UnifiedVectorFormat outer_format;
16+
UnifiedVectorFormat inner_format;
17+
UnifiedVectorFormat items_format;
18+
19+
// Setup outer vec;
20+
auto &outer_vec = args.data[0];
21+
const auto outer_count = args.size();
22+
outer_vec.ToUnifiedFormat(outer_count, outer_format);
23+
24+
// Special case: outer list is all-null
25+
if (outer_vec.GetType().id() == LogicalTypeId::SQLNULL) {
26+
result.Reference(outer_vec);
1627
return;
1728
}
1829

19-
idx_t count = args.size();
20-
21-
// Prepare the result vector
22-
result.SetVectorType(VectorType::FLAT_VECTOR);
23-
// This holds the new offsets and lengths
24-
auto result_entries = FlatVector::GetData<list_entry_t>(result);
25-
auto &result_validity = FlatVector::Validity(result);
26-
27-
// The outermost list in each row
28-
UnifiedVectorFormat row_data;
29-
input.ToUnifiedFormat(count, row_data);
30-
auto row_entries = UnifiedVectorFormat::GetData<list_entry_t>(row_data);
31-
32-
// The list elements in each row: [HERE, ...]
33-
auto &row_lists = ListVector::GetEntry(input);
34-
UnifiedVectorFormat row_lists_data;
35-
idx_t total_row_lists = ListVector::GetListSize(input);
36-
row_lists.ToUnifiedFormat(total_row_lists, row_lists_data);
37-
auto row_lists_entries = UnifiedVectorFormat::GetData<list_entry_t>(row_lists_data);
38-
39-
if (row_lists.GetType().id() == LogicalTypeId::SQLNULL) {
40-
for (idx_t row_cnt = 0; row_cnt < count; row_cnt++) {
41-
auto row_idx = row_data.sel->get_index(row_cnt);
42-
if (!row_data.validity.RowIsValid(row_idx)) {
43-
result_validity.SetInvalid(row_cnt);
30+
// Setup inner vec
31+
auto &inner_vec = ListVector::GetEntry(outer_vec);
32+
const auto inner_count = ListVector::GetListSize(outer_vec);
33+
inner_vec.ToUnifiedFormat(inner_count, inner_format);
34+
35+
// Special case: inner list is all-null
36+
if (inner_vec.GetType().id() == LogicalTypeId::SQLNULL) {
37+
for (idx_t outer_raw_idx = 0; outer_raw_idx < outer_count; outer_raw_idx++) {
38+
const auto outer_idx = outer_format.sel->get_index(outer_raw_idx);
39+
if (!outer_format.validity.RowIsValid(outer_idx)) {
40+
flat_list_mask.SetInvalid(outer_raw_idx);
4441
continue;
4542
}
46-
result_entries[row_cnt].offset = 0;
47-
result_entries[row_cnt].length = 0;
43+
flat_list_data[outer_raw_idx].offset = 0;
44+
flat_list_data[outer_raw_idx].length = 0;
4845
}
4946
if (args.AllConstant()) {
5047
result.SetVectorType(VectorType::CONSTANT_VECTOR);
5148
}
5249
return;
5350
}
5451

55-
// The actual elements inside each row list: [[HERE, ...], []]
56-
// This one becomes the child vector of the result.
57-
auto &elem_vector = ListVector::GetEntry(row_lists);
52+
// Setup items vec
53+
auto &items_vec = ListVector::GetEntry(inner_vec);
54+
const auto items_count = ListVector::GetListSize(inner_vec);
55+
items_vec.ToUnifiedFormat(items_count, items_format);
56+
57+
// First pass: Figure out the total amount of items.
58+
// This can be more than items_count if the inner list reference the same item(s) multiple times.
59+
60+
idx_t total_items = 0;
61+
62+
const auto outer_data = UnifiedVectorFormat::GetData<list_entry_t>(outer_format);
63+
const auto inner_data = UnifiedVectorFormat::GetData<list_entry_t>(inner_format);
64+
65+
for (idx_t outer_raw_idx = 0; outer_raw_idx < outer_count; outer_raw_idx++) {
66+
const auto outer_idx = outer_format.sel->get_index(outer_raw_idx);
67+
68+
if (!outer_format.validity.RowIsValid(outer_idx)) {
69+
continue;
70+
}
71+
72+
const auto &outer_entry = outer_data[outer_idx];
73+
74+
for (idx_t inner_raw_idx = outer_entry.offset; inner_raw_idx < outer_entry.offset + outer_entry.length;
75+
inner_raw_idx++) {
76+
const auto inner_idx = inner_format.sel->get_index(inner_raw_idx);
5877

59-
// We'll use this selection vector to slice the elem_vector.
60-
idx_t child_elem_cnt = ListVector::GetListSize(row_lists);
61-
SelectionVector sel(child_elem_cnt);
78+
if (!inner_format.validity.RowIsValid(inner_idx)) {
79+
continue;
80+
}
81+
82+
const auto &inner_entry = inner_data[inner_idx];
83+
84+
total_items += inner_entry.length;
85+
}
86+
}
87+
88+
// Now we know the total amount of items, we can create our selection vector.
89+
SelectionVector sel(total_items);
6290
idx_t sel_idx = 0;
6391

64-
// HERE, [[]], ...
65-
for (idx_t row_cnt = 0; row_cnt < count; row_cnt++) {
66-
auto row_idx = row_data.sel->get_index(row_cnt);
92+
// Second pass: Fill the selection vector (and the result list entries)
93+
94+
for (idx_t outer_raw_idx = 0; outer_raw_idx < outer_count; outer_raw_idx++) {
95+
const auto outer_idx = outer_format.sel->get_index(outer_raw_idx);
6796

68-
if (!row_data.validity.RowIsValid(row_idx)) {
69-
result_validity.SetInvalid(row_cnt);
97+
if (!outer_format.validity.RowIsValid(outer_idx)) {
98+
flat_list_mask.SetInvalid(outer_raw_idx);
7099
continue;
71100
}
72101

73-
idx_t list_offset = sel_idx;
74-
idx_t list_length = 0;
102+
const auto &outer_entry = outer_data[outer_idx];
103+
104+
list_entry_t list_entry = {sel_idx, 0};
75105

76-
// [HERE, [...], ...]
77-
auto row_entry = row_entries[row_idx];
78-
for (idx_t row_lists_cnt = 0; row_lists_cnt < row_entry.length; row_lists_cnt++) {
79-
auto row_lists_idx = row_lists_data.sel->get_index(row_entry.offset + row_lists_cnt);
106+
for (idx_t inner_raw_idx = outer_entry.offset; inner_raw_idx < outer_entry.offset + outer_entry.length;
107+
inner_raw_idx++) {
108+
const auto inner_idx = inner_format.sel->get_index(inner_raw_idx);
80109

81-
// Skip invalid lists
82-
if (!row_lists_data.validity.RowIsValid(row_lists_idx)) {
110+
if (!inner_format.validity.RowIsValid(inner_idx)) {
83111
continue;
84112
}
85113

86-
// [[HERE, ...], [.., ...]]
87-
auto list_entry = row_lists_entries[row_lists_idx];
88-
list_length += list_entry.length;
114+
const auto &inner_entry = inner_data[inner_idx];
115+
116+
list_entry.length += inner_entry.length;
117+
118+
for (idx_t elem_raw_idx = inner_entry.offset; elem_raw_idx < inner_entry.offset + inner_entry.length;
119+
elem_raw_idx++) {
120+
const auto elem_idx = items_format.sel->get_index(elem_raw_idx);
89121

90-
for (idx_t elem_cnt = 0; elem_cnt < list_entry.length; elem_cnt++) {
91-
// offset of the element in the elem_vector.
92-
idx_t offset = list_entry.offset + elem_cnt;
93-
sel.set_index(sel_idx, offset);
122+
sel.set_index(sel_idx, elem_idx);
94123
sel_idx++;
95124
}
96125
}
97126

98-
result_entries[row_cnt].offset = list_offset;
99-
result_entries[row_cnt].length = list_length;
127+
// Assign the result list entry
128+
flat_list_data[outer_raw_idx] = list_entry;
100129
}
101130

131+
// Now assing the result
102132
ListVector::SetListSize(result, sel_idx);
103133

104134
auto &result_child_vector = ListVector::GetEntry(result);
105-
result_child_vector.Slice(elem_vector, sel, sel_idx);
135+
result_child_vector.Slice(items_vec, sel, sel_idx);
106136
result_child_vector.Flatten(sel_idx);
107137

108138
if (args.AllConstant()) {

src/duckdb/extension/core_functions/scalar/map/map_extract.cpp

+89-8
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,36 @@
66

77
namespace duckdb {
88

9+
template <bool EXTRACT_VALUE>
910
static unique_ptr<FunctionData> MapExtractBind(ClientContext &, ScalarFunction &bound_function,
1011
vector<unique_ptr<Expression>> &arguments) {
1112
if (arguments.size() != 2) {
1213
throw BinderException("MAP_EXTRACT must have exactly two arguments");
1314
}
1415

15-
auto &map_type = arguments[0]->return_type;
16-
auto &input_type = arguments[1]->return_type;
16+
const auto &map_type = arguments[0]->return_type;
17+
const auto &input_type = arguments[1]->return_type;
1718

1819
if (map_type.id() == LogicalTypeId::SQLNULL) {
19-
bound_function.return_type = LogicalTypeId::SQLNULL;
20+
bound_function.return_type = EXTRACT_VALUE ? LogicalTypeId::SQLNULL : LogicalType::LIST(LogicalTypeId::SQLNULL);
2021
return make_uniq<VariableReturnBindData>(bound_function.return_type);
2122
}
2223

2324
if (map_type.id() != LogicalTypeId::MAP) {
24-
throw BinderException("MAP_EXTRACT can only operate on MAPs");
25+
throw BinderException("'%s' can only operate on MAPs", bound_function.name);
2526
}
2627
auto &value_type = MapType::ValueType(map_type);
2728

2829
//! Here we have to construct the List Type that will be returned
29-
bound_function.return_type = value_type;
30-
auto key_type = MapType::KeyType(map_type);
30+
bound_function.return_type = EXTRACT_VALUE ? value_type : LogicalType::LIST(value_type);
31+
const auto &key_type = MapType::KeyType(map_type);
3132
if (key_type.id() != LogicalTypeId::SQLNULL && input_type.id() != LogicalTypeId::SQLNULL) {
3233
bound_function.arguments[1] = MapType::KeyType(map_type);
3334
}
3435
return make_uniq<VariableReturnBindData>(bound_function.return_type);
3536
}
3637

37-
static void MapExtractFunc(DataChunk &args, ExpressionState &state, Vector &result) {
38+
static void MapExtractValueFunc(DataChunk &args, ExpressionState &state, Vector &result) {
3839
const auto count = args.size();
3940

4041
auto &map_vec = args.data[0];
@@ -94,8 +95,88 @@ static void MapExtractFunc(DataChunk &args, ExpressionState &state, Vector &resu
9495
result.Verify(count);
9596
}
9697

98+
static void MapExtractListFunc(DataChunk &args, ExpressionState &state, Vector &result) {
99+
const auto count = args.size();
100+
101+
auto &map_vec = args.data[0];
102+
auto &arg_vec = args.data[1];
103+
104+
const auto map_is_null = map_vec.GetType().id() == LogicalTypeId::SQLNULL;
105+
const auto arg_is_null = arg_vec.GetType().id() == LogicalTypeId::SQLNULL;
106+
107+
if (map_is_null || arg_is_null) {
108+
// Short-circuit if either the map or the arg is NULL
109+
ListVector::SetListSize(result, 0);
110+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
111+
ConstantVector::GetData<list_entry_t>(result)[0] = {0, 0};
112+
result.Verify(count);
113+
return;
114+
}
115+
116+
auto &key_vec = MapVector::GetKeys(map_vec);
117+
auto &val_vec = MapVector::GetValues(map_vec);
118+
119+
// Collect the matching positions
120+
Vector pos_vec(LogicalType::INTEGER, count);
121+
ListSearchOp<true>(map_vec, key_vec, arg_vec, pos_vec, args.size());
122+
123+
UnifiedVectorFormat val_format;
124+
UnifiedVectorFormat pos_format;
125+
UnifiedVectorFormat lst_format;
126+
127+
val_vec.ToUnifiedFormat(ListVector::GetListSize(map_vec), val_format);
128+
pos_vec.ToUnifiedFormat(count, pos_format);
129+
map_vec.ToUnifiedFormat(count, lst_format);
130+
131+
const auto pos_data = UnifiedVectorFormat::GetData<int32_t>(pos_format);
132+
const auto inc_list_data = ListVector::GetData(map_vec);
133+
const auto out_list_data = ListVector::GetData(result);
134+
135+
idx_t offset = 0;
136+
for (idx_t row_idx = 0; row_idx < count; row_idx++) {
137+
const auto lst_idx = lst_format.sel->get_index(row_idx);
138+
if (!lst_format.validity.RowIsValid(lst_idx)) {
139+
FlatVector::SetNull(result, row_idx, true);
140+
continue;
141+
}
142+
143+
auto &inc_list = inc_list_data[lst_idx];
144+
auto &out_list = out_list_data[row_idx];
145+
146+
const auto pos_idx = pos_format.sel->get_index(row_idx);
147+
if (!pos_format.validity.RowIsValid(pos_idx)) {
148+
// We didnt find the key in the map, so return emptyl ist
149+
out_list.offset = offset;
150+
out_list.length = 0;
151+
continue;
152+
}
153+
154+
// Compute the actual position of the value in the map value vector
155+
const auto pos = inc_list.offset + UnsafeNumericCast<idx_t>(pos_data[pos_idx] - 1);
156+
out_list.offset = offset;
157+
out_list.length = 1;
158+
ListVector::Append(result, val_vec, pos + 1, pos);
159+
offset++;
160+
}
161+
162+
if (args.size() == 1) {
163+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
164+
}
165+
166+
result.Verify(count);
167+
}
168+
169+
ScalarFunction MapExtractValueFun::GetFunction() {
170+
ScalarFunction fun({LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, MapExtractValueFunc,
171+
MapExtractBind<true>);
172+
fun.varargs = LogicalType::ANY;
173+
fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING;
174+
return fun;
175+
}
176+
97177
ScalarFunction MapExtractFun::GetFunction() {
98-
ScalarFunction fun({LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, MapExtractFunc, MapExtractBind);
178+
ScalarFunction fun({LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, MapExtractListFunc,
179+
MapExtractBind<false>);
99180
fun.varargs = LogicalType::ANY;
100181
fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING;
101182
return fun;

0 commit comments

Comments
 (0)