duckdb 0.8.2-dev2399.0 → 0.8.2-dev2669.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +1 -0
- package/package.json +1 -1
- package/src/duckdb/extension/icu/icu-datepart.cpp +3 -3
- package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +1 -1
- package/src/duckdb/src/catalog/default/default_functions.cpp +5 -0
- package/src/duckdb/src/common/enum_util.cpp +35 -1
- package/src/duckdb/src/common/http_state.cpp +78 -0
- package/src/duckdb/src/core_functions/function_list.cpp +2 -2
- package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +314 -82
- package/src/duckdb/src/execution/expression_executor/execute_parameter.cpp +2 -2
- package/src/duckdb/src/execution/index/art/art.cpp +43 -31
- package/src/duckdb/src/execution/index/art/leaf.cpp +47 -33
- package/src/duckdb/src/execution/index/art/node.cpp +31 -24
- package/src/duckdb/src/execution/index/art/prefix.cpp +100 -16
- package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +54 -31
- package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +32 -15
- package/src/duckdb/src/function/table/arrow/arrow_duck_schema.cpp +57 -0
- package/src/duckdb/src/function/table/arrow.cpp +95 -92
- package/src/duckdb/src/function/table/arrow_conversion.cpp +45 -68
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/case_insensitive_map.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enum_util.hpp +8 -0
- package/src/duckdb/src/include/duckdb/common/helper.hpp +8 -3
- package/src/duckdb/src/include/duckdb/common/http_state.hpp +61 -28
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +4 -1
- package/src/duckdb/src/include/duckdb/core_functions/scalar/list_functions.hpp +4 -4
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +7 -5
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +6 -6
- package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +6 -0
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +9 -11
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_create_index.hpp +8 -1
- package/src/duckdb/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +99 -0
- package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +6 -36
- package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +3 -1
- package/src/duckdb/src/include/duckdb/main/client_context.hpp +15 -14
- package/src/duckdb/src/include/duckdb/main/prepared_statement.hpp +73 -5
- package/src/duckdb/src/include/duckdb/main/prepared_statement_data.hpp +6 -6
- package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +20 -3
- package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +17 -1
- package/src/duckdb/src/include/duckdb/parser/statement/execute_statement.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +5 -3
- package/src/duckdb/src/include/duckdb/planner/bound_parameter_map.hpp +2 -1
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_data.hpp +20 -5
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_expression.hpp +3 -3
- package/src/duckdb/src/include/duckdb/planner/planner.hpp +4 -3
- package/src/duckdb/src/include/duckdb/storage/object_cache.hpp +1 -1
- package/src/duckdb/src/include/duckdb/verification/prepared_statement_verifier.hpp +1 -1
- package/src/duckdb/src/include/duckdb.h +16 -0
- package/src/duckdb/src/main/capi/pending-c.cpp +6 -0
- package/src/duckdb/src/main/capi/prepared-c.cpp +52 -4
- package/src/duckdb/src/main/client_context.cpp +27 -17
- package/src/duckdb/src/main/client_verify.cpp +17 -0
- package/src/duckdb/src/main/extension/extension_helper.cpp +2 -1
- package/src/duckdb/src/main/prepared_statement.cpp +38 -11
- package/src/duckdb/src/main/prepared_statement_data.cpp +23 -18
- package/src/duckdb/src/parser/expression/parameter_expression.cpp +7 -7
- package/src/duckdb/src/parser/statement/execute_statement.cpp +2 -2
- package/src/duckdb/src/parser/transform/expression/transform_array_access.cpp +13 -4
- package/src/duckdb/src/parser/transform/expression/transform_param_ref.cpp +45 -26
- package/src/duckdb/src/parser/transform/statement/transform_prepare.cpp +28 -6
- package/src/duckdb/src/parser/transformer.cpp +27 -9
- package/src/duckdb/src/planner/binder/expression/bind_parameter_expression.cpp +10 -10
- package/src/duckdb/src/planner/binder/statement/bind_execute.cpp +13 -7
- package/src/duckdb/src/planner/expression/bound_parameter_expression.cpp +13 -13
- package/src/duckdb/src/planner/planner.cpp +7 -6
- package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -1
- package/src/duckdb/src/storage/serialization/serialize_expression.cpp +3 -3
- package/src/duckdb/src/storage/serialization/serialize_parsed_expression.cpp +2 -2
- package/src/duckdb/src/verification/prepared_statement_verifier.cpp +16 -11
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +12855 -12282
- package/src/duckdb/ub_src_common.cpp +2 -0
- package/src/duckdb/ub_src_function_table_arrow.cpp +2 -0
@@ -1,14 +1,62 @@
|
|
1
1
|
#include "duckdb/core_functions/scalar/list_functions.hpp"
|
2
|
-
#include "duckdb/common/pair.hpp"
|
3
2
|
#include "duckdb/common/string_util.hpp"
|
3
|
+
#include "duckdb/common/swap.hpp"
|
4
4
|
#include "duckdb/common/types/data_chunk.hpp"
|
5
5
|
#include "duckdb/function/scalar/nested_functions.hpp"
|
6
6
|
#include "duckdb/function/scalar/string_functions.hpp"
|
7
|
-
#include "duckdb/parser/expression/bound_expression.hpp"
|
8
7
|
#include "duckdb/planner/expression/bound_function_expression.hpp"
|
8
|
+
#include "duckdb/planner/expression/bound_constant_expression.hpp"
|
9
9
|
|
10
10
|
namespace duckdb {
|
11
11
|
|
12
|
+
struct ListSliceBindData : public FunctionData {
|
13
|
+
ListSliceBindData(const LogicalType &return_type_p, bool begin_is_empty_p, bool end_is_empty_p)
|
14
|
+
: return_type(return_type_p), begin_is_empty(begin_is_empty_p), end_is_empty(end_is_empty_p) {
|
15
|
+
}
|
16
|
+
~ListSliceBindData() override;
|
17
|
+
|
18
|
+
LogicalType return_type;
|
19
|
+
|
20
|
+
bool begin_is_empty;
|
21
|
+
bool end_is_empty;
|
22
|
+
|
23
|
+
public:
|
24
|
+
bool Equals(const FunctionData &other_p) const override;
|
25
|
+
unique_ptr<FunctionData> Copy() const override;
|
26
|
+
};
|
27
|
+
|
28
|
+
ListSliceBindData::~ListSliceBindData() {
|
29
|
+
}
|
30
|
+
|
31
|
+
bool ListSliceBindData::Equals(const FunctionData &other_p) const {
|
32
|
+
auto &other = other_p.Cast<ListSliceBindData>();
|
33
|
+
return return_type == other.return_type && begin_is_empty == other.begin_is_empty &&
|
34
|
+
end_is_empty == other.end_is_empty;
|
35
|
+
}
|
36
|
+
|
37
|
+
unique_ptr<FunctionData> ListSliceBindData::Copy() const {
|
38
|
+
return make_uniq<ListSliceBindData>(return_type, begin_is_empty, end_is_empty);
|
39
|
+
}
|
40
|
+
|
41
|
+
template <typename INDEX_TYPE>
|
42
|
+
static int CalculateSliceLength(idx_t begin, idx_t end, INDEX_TYPE step, bool svalid) {
|
43
|
+
if (step < 0) {
|
44
|
+
step = abs(step);
|
45
|
+
}
|
46
|
+
if (step == 0 && svalid) {
|
47
|
+
throw InvalidInputException("Slice step cannot be zero");
|
48
|
+
}
|
49
|
+
if (step == 1) {
|
50
|
+
return end - begin;
|
51
|
+
} else if (static_cast<idx_t>(step) >= (end - begin)) {
|
52
|
+
return 1;
|
53
|
+
}
|
54
|
+
if ((end - begin) % step != 0) {
|
55
|
+
return (end - begin) / step + 1;
|
56
|
+
}
|
57
|
+
return (end - begin) / step;
|
58
|
+
}
|
59
|
+
|
12
60
|
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
13
61
|
INDEX_TYPE ValueLength(const INPUT_TYPE &value) {
|
14
62
|
return 0;
|
@@ -20,33 +68,44 @@ int64_t ValueLength(const list_entry_t &value) {
|
|
20
68
|
}
|
21
69
|
|
22
70
|
template <>
|
23
|
-
|
24
|
-
return LengthFun::Length<string_t,
|
71
|
+
int64_t ValueLength(const string_t &value) {
|
72
|
+
return LengthFun::Length<string_t, int64_t>(value);
|
25
73
|
}
|
26
74
|
|
27
75
|
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
28
|
-
|
29
|
-
const auto length = ValueLength<INPUT_TYPE, INDEX_TYPE>(value);
|
76
|
+
static void ClampIndex(INDEX_TYPE &index, const INPUT_TYPE &value, const INDEX_TYPE length, bool is_min) {
|
30
77
|
if (index < 0) {
|
31
|
-
|
32
|
-
return false;
|
33
|
-
}
|
78
|
+
index = (!is_min) ? index + 1 : index;
|
34
79
|
index = length + index;
|
80
|
+
return;
|
35
81
|
} else if (index > length) {
|
36
82
|
index = length;
|
37
83
|
}
|
38
|
-
return
|
84
|
+
return;
|
39
85
|
}
|
40
86
|
|
41
87
|
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
42
|
-
static bool ClampSlice(const INPUT_TYPE &value, INDEX_TYPE &begin, INDEX_TYPE &end
|
88
|
+
static bool ClampSlice(const INPUT_TYPE &value, INDEX_TYPE &begin, INDEX_TYPE &end) {
|
43
89
|
// Clamp offsets
|
44
|
-
begin =
|
45
|
-
|
46
|
-
|
47
|
-
if (
|
48
|
-
|
90
|
+
begin = (begin != 0 && begin != (INDEX_TYPE)NumericLimits<int64_t>::Minimum()) ? begin - 1 : begin;
|
91
|
+
|
92
|
+
bool is_min = false;
|
93
|
+
if (begin == (INDEX_TYPE)NumericLimits<int64_t>::Minimum()) {
|
94
|
+
begin++;
|
95
|
+
is_min = true;
|
96
|
+
}
|
97
|
+
|
98
|
+
const auto length = ValueLength<INPUT_TYPE, INDEX_TYPE>(value);
|
99
|
+
if (begin < 0 && -begin > length && end < 0 && -end > length) {
|
100
|
+
begin = 0;
|
101
|
+
end = 0;
|
102
|
+
return true;
|
49
103
|
}
|
104
|
+
if (begin < 0 && -begin > length) {
|
105
|
+
begin = 0;
|
106
|
+
}
|
107
|
+
ClampIndex(begin, value, length, is_min);
|
108
|
+
ClampIndex(end, value, length, false);
|
50
109
|
end = MaxValue<INDEX_TYPE>(begin, end);
|
51
110
|
|
52
111
|
return true;
|
@@ -65,108 +124,268 @@ list_entry_t SliceValue(Vector &result, list_entry_t input, int64_t begin, int64
|
|
65
124
|
}
|
66
125
|
|
67
126
|
template <>
|
68
|
-
string_t SliceValue(Vector &result, string_t input,
|
127
|
+
string_t SliceValue(Vector &result, string_t input, int64_t begin, int64_t end) {
|
69
128
|
// one-based - zero has strange semantics
|
70
129
|
return SubstringFun::SubstringUnicode(result, input, begin + 1, end - begin);
|
71
130
|
}
|
72
131
|
|
73
132
|
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
133
|
+
INPUT_TYPE SliceValueWithSteps(Vector &result, SelectionVector &sel, INPUT_TYPE input, INDEX_TYPE begin, INDEX_TYPE end,
|
134
|
+
INDEX_TYPE step, idx_t &sel_idx) {
|
135
|
+
return input;
|
136
|
+
}
|
137
|
+
|
138
|
+
template <>
|
139
|
+
list_entry_t SliceValueWithSteps(Vector &result, SelectionVector &sel, list_entry_t input, int64_t begin, int64_t end,
|
140
|
+
int64_t step, idx_t &sel_idx) {
|
141
|
+
if (end - begin == 0) {
|
142
|
+
input.length = 0;
|
143
|
+
input.offset = sel_idx;
|
144
|
+
return input;
|
145
|
+
}
|
146
|
+
input.length = CalculateSliceLength(begin, end, step, true);
|
147
|
+
idx_t child_idx = input.offset + begin;
|
148
|
+
if (step < 0) {
|
149
|
+
child_idx = input.offset + end - 1;
|
150
|
+
}
|
151
|
+
input.offset = sel_idx;
|
152
|
+
for (idx_t i = 0; i < input.length; i++) {
|
153
|
+
sel.set_index(sel_idx, child_idx);
|
154
|
+
child_idx += step;
|
155
|
+
sel_idx++;
|
156
|
+
}
|
157
|
+
return input;
|
158
|
+
}
|
159
|
+
|
160
|
+
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
161
|
+
static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &begin_vector, Vector &end_vector,
|
162
|
+
optional_ptr<Vector> step_vector, const idx_t count, SelectionVector &sel,
|
163
|
+
idx_t &sel_idx, optional_ptr<Vector> result_child_vector, bool begin_is_empty,
|
164
|
+
bool end_is_empty) {
|
165
|
+
auto result_data = ConstantVector::GetData<INPUT_TYPE>(result);
|
166
|
+
auto str_data = ConstantVector::GetData<INPUT_TYPE>(str_vector);
|
167
|
+
auto begin_data = ConstantVector::GetData<INDEX_TYPE>(begin_vector);
|
168
|
+
auto end_data = ConstantVector::GetData<INDEX_TYPE>(end_vector);
|
169
|
+
auto step_data = step_vector ? ConstantVector::GetData<INDEX_TYPE>(*step_vector) : nullptr;
|
170
|
+
|
171
|
+
auto str = str_data[0];
|
172
|
+
auto begin = begin_is_empty ? 0 : begin_data[0];
|
173
|
+
auto end = end_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(str) : end_data[0];
|
174
|
+
auto step = step_data ? step_data[0] : 1;
|
175
|
+
|
176
|
+
if (step < 0) {
|
177
|
+
swap(begin, end);
|
178
|
+
begin = end_is_empty ? 0 : begin;
|
179
|
+
end = begin_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(str) : end;
|
180
|
+
}
|
181
|
+
|
182
|
+
auto str_valid = !ConstantVector::IsNull(str_vector);
|
183
|
+
auto begin_valid = !ConstantVector::IsNull(begin_vector);
|
184
|
+
auto end_valid = !ConstantVector::IsNull(end_vector);
|
185
|
+
auto step_valid = step_vector && !ConstantVector::IsNull(*step_vector);
|
186
|
+
|
187
|
+
// Clamp offsets
|
188
|
+
bool clamp_result = false;
|
189
|
+
if (str_valid && begin_valid && end_valid && (step_valid || step == 1)) {
|
190
|
+
clamp_result = ClampSlice(str, begin, end);
|
191
|
+
}
|
192
|
+
|
193
|
+
auto sel_length = 0;
|
194
|
+
if (step_vector && step_valid && str_valid && begin_valid && end_valid && step != 1 && end - begin > 0) {
|
195
|
+
sel_length = CalculateSliceLength(begin, end, step, step_valid);
|
196
|
+
sel.Initialize(sel_length);
|
197
|
+
}
|
198
|
+
|
199
|
+
// Try to slice
|
200
|
+
if (!str_valid || !begin_valid || !end_valid || (step_vector && !step_valid) || !clamp_result) {
|
201
|
+
ConstantVector::SetNull(result, true);
|
202
|
+
} else if (step == 1) {
|
203
|
+
result_data[0] = SliceValue<INPUT_TYPE, INDEX_TYPE>(result, str, begin, end);
|
95
204
|
} else {
|
96
|
-
|
205
|
+
result_data[0] = SliceValueWithSteps<INPUT_TYPE, INDEX_TYPE>(result, sel, str, begin, end, step, sel_idx);
|
206
|
+
}
|
207
|
+
|
208
|
+
if (step_vector && step != 0 && end - begin > 0) {
|
209
|
+
result_child_vector->Slice(sel, sel_length);
|
210
|
+
}
|
211
|
+
}
|
97
212
|
|
98
|
-
|
99
|
-
|
100
|
-
|
213
|
+
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
214
|
+
static void ExecuteFlatSlice(Vector &result, Vector &list_vector, Vector &begin_vector, Vector &end_vector,
|
215
|
+
optional_ptr<Vector> step_vector, const idx_t count, SelectionVector &sel, idx_t &sel_idx,
|
216
|
+
optional_ptr<Vector> result_child_vector, bool begin_is_empty, bool end_is_empty) {
|
217
|
+
UnifiedVectorFormat list_data, begin_data, end_data, step_data;
|
218
|
+
idx_t sel_length = 0;
|
101
219
|
|
102
|
-
|
103
|
-
|
220
|
+
list_vector.ToUnifiedFormat(count, list_data);
|
221
|
+
begin_vector.ToUnifiedFormat(count, begin_data);
|
222
|
+
end_vector.ToUnifiedFormat(count, end_data);
|
223
|
+
if (step_vector) {
|
224
|
+
step_vector->ToUnifiedFormat(count, step_data);
|
225
|
+
sel.Initialize(ListVector::GetListSize(list_vector));
|
226
|
+
}
|
104
227
|
|
105
|
-
|
106
|
-
|
107
|
-
auto bidx = bdata.sel->get_index(i);
|
108
|
-
auto eidx = edata.sel->get_index(i);
|
228
|
+
auto result_data = FlatVector::GetData<INPUT_TYPE>(result);
|
229
|
+
auto &result_mask = FlatVector::Validity(result);
|
109
230
|
|
110
|
-
|
111
|
-
|
112
|
-
|
231
|
+
for (idx_t i = 0; i < count; ++i) {
|
232
|
+
auto list_idx = list_data.sel->get_index(i);
|
233
|
+
auto begin_idx = begin_data.sel->get_index(i);
|
234
|
+
auto end_idx = end_data.sel->get_index(i);
|
235
|
+
auto step_idx = step_vector ? step_data.sel->get_index(i) : 0;
|
113
236
|
|
114
|
-
|
115
|
-
|
116
|
-
|
237
|
+
auto sliced = reinterpret_cast<INPUT_TYPE *>(list_data.data)[list_idx];
|
238
|
+
auto begin = begin_is_empty ? 0 : reinterpret_cast<INDEX_TYPE *>(begin_data.data)[begin_idx];
|
239
|
+
auto end = end_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(sliced)
|
240
|
+
: reinterpret_cast<INDEX_TYPE *>(end_data.data)[end_idx];
|
241
|
+
auto step = step_vector ? reinterpret_cast<INDEX_TYPE *>(step_data.data)[step_idx] : 1;
|
117
242
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
243
|
+
if (step < 0) {
|
244
|
+
swap(begin, end);
|
245
|
+
begin = end_is_empty ? 0 : begin;
|
246
|
+
end = begin_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(sliced) : end;
|
247
|
+
}
|
248
|
+
auto list_valid = list_data.validity.RowIsValid(list_idx);
|
249
|
+
auto begin_valid = begin_data.validity.RowIsValid(begin_idx);
|
250
|
+
auto end_valid = end_data.validity.RowIsValid(end_idx);
|
251
|
+
auto step_valid = step_vector && step_data.validity.RowIsValid(step_idx);
|
252
|
+
|
253
|
+
bool clamp_result = false;
|
254
|
+
if (list_valid && begin_valid && end_valid && (step_valid || step == 1)) {
|
255
|
+
clamp_result = ClampSlice(sliced, begin, end);
|
256
|
+
}
|
257
|
+
|
258
|
+
auto length = 0;
|
259
|
+
if (step_vector && step_valid && list_valid && begin_valid && end_valid && end - begin > 0) {
|
260
|
+
length = CalculateSliceLength(begin, end, step, step_valid);
|
261
|
+
}
|
262
|
+
sel_length += length;
|
263
|
+
|
264
|
+
if (!list_valid || !begin_valid || !end_valid || (step_vector && !step_valid) || !clamp_result) {
|
265
|
+
result_mask.SetInvalid(i);
|
266
|
+
} else if (!step_vector) {
|
267
|
+
result_data[i] = SliceValue<INPUT_TYPE, INDEX_TYPE>(result, sliced, begin, end);
|
268
|
+
} else {
|
269
|
+
result_data[i] =
|
270
|
+
SliceValueWithSteps<INPUT_TYPE, INDEX_TYPE>(result, sel, sliced, begin, end, step, sel_idx);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
if (step_vector) {
|
274
|
+
SelectionVector new_sel(sel_length);
|
275
|
+
for (idx_t i = 0; i < sel_length; ++i) {
|
276
|
+
new_sel.set_index(i, sel.get_index(i));
|
124
277
|
}
|
278
|
+
result_child_vector->Slice(new_sel, sel_length);
|
125
279
|
}
|
280
|
+
}
|
281
|
+
|
282
|
+
template <typename INPUT_TYPE, typename INDEX_TYPE>
|
283
|
+
static void ExecuteSlice(Vector &result, Vector &list_or_str_vector, Vector &begin_vector, Vector &end_vector,
|
284
|
+
optional_ptr<Vector> step_vector, const idx_t count, bool begin_is_empty, bool end_is_empty) {
|
285
|
+
optional_ptr<Vector> result_child_vector;
|
286
|
+
if (step_vector) {
|
287
|
+
result_child_vector = &ListVector::GetEntry(result);
|
288
|
+
}
|
289
|
+
|
290
|
+
SelectionVector sel;
|
291
|
+
idx_t sel_idx = 0;
|
126
292
|
|
293
|
+
if (result.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
294
|
+
ExecuteConstantSlice<INPUT_TYPE, INDEX_TYPE>(result, list_or_str_vector, begin_vector, end_vector, step_vector,
|
295
|
+
count, sel, sel_idx, result_child_vector, begin_is_empty,
|
296
|
+
end_is_empty);
|
297
|
+
} else {
|
298
|
+
ExecuteFlatSlice<INPUT_TYPE, INDEX_TYPE>(result, list_or_str_vector, begin_vector, end_vector, step_vector,
|
299
|
+
count, sel, sel_idx, result_child_vector, begin_is_empty,
|
300
|
+
end_is_empty);
|
301
|
+
}
|
127
302
|
result.Verify(count);
|
128
303
|
}
|
129
304
|
|
130
305
|
static void ArraySliceFunction(DataChunk &args, ExpressionState &state, Vector &result) {
|
131
|
-
D_ASSERT(args.ColumnCount() == 3);
|
132
|
-
D_ASSERT(args.data.size() == 3);
|
306
|
+
D_ASSERT(args.ColumnCount() == 3 || args.ColumnCount() == 4);
|
307
|
+
D_ASSERT(args.data.size() == 3 || args.data.size() == 4);
|
133
308
|
auto count = args.size();
|
134
309
|
|
135
|
-
Vector &
|
136
|
-
|
137
|
-
|
310
|
+
Vector &list_or_str_vector = args.data[0];
|
311
|
+
if (list_or_str_vector.GetType().id() == LogicalTypeId::SQLNULL) {
|
312
|
+
auto &result_validity = FlatVector::Validity(result);
|
313
|
+
result_validity.SetInvalid(0);
|
314
|
+
return;
|
315
|
+
}
|
316
|
+
|
317
|
+
Vector &begin_vector = args.data[1];
|
318
|
+
Vector &end_vector = args.data[2];
|
319
|
+
|
320
|
+
optional_ptr<Vector> step_vector;
|
321
|
+
if (args.ColumnCount() == 4) {
|
322
|
+
step_vector = &args.data[3];
|
323
|
+
}
|
324
|
+
|
325
|
+
auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
|
326
|
+
auto &info = func_expr.bind_info->Cast<ListSliceBindData>();
|
327
|
+
auto begin_is_empty = info.begin_is_empty;
|
328
|
+
auto end_is_empty = info.end_is_empty;
|
138
329
|
|
139
330
|
result.SetVectorType(args.AllConstant() ? VectorType::CONSTANT_VECTOR : VectorType::FLAT_VECTOR);
|
140
331
|
switch (result.GetType().id()) {
|
141
|
-
case LogicalTypeId::LIST:
|
332
|
+
case LogicalTypeId::LIST: {
|
142
333
|
// Share the value dictionary as we are just going to slice it
|
143
|
-
if (
|
144
|
-
|
334
|
+
if (list_or_str_vector.GetVectorType() != VectorType::FLAT_VECTOR &&
|
335
|
+
list_or_str_vector.GetVectorType() != VectorType::CONSTANT_VECTOR) {
|
336
|
+
list_or_str_vector.Flatten(count);
|
145
337
|
}
|
146
|
-
ListVector::ReferenceEntry(result,
|
147
|
-
ExecuteSlice<list_entry_t, int64_t>(result,
|
338
|
+
ListVector::ReferenceEntry(result, list_or_str_vector);
|
339
|
+
ExecuteSlice<list_entry_t, int64_t>(result, list_or_str_vector, begin_vector, end_vector, step_vector, count,
|
340
|
+
begin_is_empty, end_is_empty);
|
148
341
|
break;
|
149
|
-
|
150
|
-
|
342
|
+
}
|
343
|
+
case LogicalTypeId::VARCHAR: {
|
344
|
+
ExecuteSlice<string_t, int64_t>(result, list_or_str_vector, begin_vector, end_vector, step_vector, count,
|
345
|
+
begin_is_empty, end_is_empty);
|
151
346
|
break;
|
347
|
+
}
|
152
348
|
default:
|
153
349
|
throw NotImplementedException("Specifier type not implemented");
|
154
350
|
}
|
155
351
|
}
|
156
352
|
|
353
|
+
static bool CheckIfParamIsEmpty(duckdb::unique_ptr<duckdb::Expression> ¶m) {
|
354
|
+
bool is_empty = false;
|
355
|
+
if (param->return_type.id() == LogicalTypeId::LIST) {
|
356
|
+
auto empty_list = make_uniq<BoundConstantExpression>(Value::LIST(LogicalType::INTEGER, vector<Value>()));
|
357
|
+
is_empty = param->Equals(*empty_list);
|
358
|
+
if (!is_empty) {
|
359
|
+
// if the param is not empty, the user has entered a list instead of a BIGINT
|
360
|
+
throw BinderException("The upper and lower bounds of the slice must be a BIGINT");
|
361
|
+
}
|
362
|
+
}
|
363
|
+
return is_empty;
|
364
|
+
}
|
365
|
+
|
157
366
|
static unique_ptr<FunctionData> ArraySliceBind(ClientContext &context, ScalarFunction &bound_function,
|
158
367
|
vector<unique_ptr<Expression>> &arguments) {
|
159
|
-
D_ASSERT(
|
368
|
+
D_ASSERT(arguments.size() == 3 || arguments.size() == 4);
|
369
|
+
D_ASSERT(bound_function.arguments.size() == 3 || bound_function.arguments.size() == 4);
|
370
|
+
|
160
371
|
switch (arguments[0]->return_type.id()) {
|
161
372
|
case LogicalTypeId::LIST:
|
162
373
|
// The result is the same type
|
163
374
|
bound_function.return_type = arguments[0]->return_type;
|
164
375
|
break;
|
165
376
|
case LogicalTypeId::VARCHAR:
|
166
|
-
// string slice returns a string
|
377
|
+
// string slice returns a string
|
378
|
+
if (bound_function.arguments.size() == 4) {
|
379
|
+
throw NotImplementedException(
|
380
|
+
"Slice with steps has not been implemented for string types, you can consider rewriting your query as "
|
381
|
+
"follows:\n SELECT array_to_string((str_split(string, '')[begin:end:step], '');");
|
382
|
+
}
|
167
383
|
bound_function.return_type = arguments[0]->return_type;
|
168
|
-
|
169
|
-
|
384
|
+
for (idx_t i = 1; i < 3; i++) {
|
385
|
+
if (arguments[i]->return_type.id() != LogicalTypeId::LIST) {
|
386
|
+
bound_function.arguments[i] = LogicalType::BIGINT;
|
387
|
+
}
|
388
|
+
}
|
170
389
|
break;
|
171
390
|
case LogicalTypeId::SQLNULL:
|
172
391
|
case LogicalTypeId::UNKNOWN:
|
@@ -177,16 +396,29 @@ static unique_ptr<FunctionData> ArraySliceBind(ClientContext &context, ScalarFun
|
|
177
396
|
throw BinderException("ARRAY_SLICE can only operate on LISTs and VARCHARs");
|
178
397
|
}
|
179
398
|
|
180
|
-
|
399
|
+
bool begin_is_empty = CheckIfParamIsEmpty(arguments[1]);
|
400
|
+
if (!begin_is_empty) {
|
401
|
+
bound_function.arguments[1] = LogicalType::BIGINT;
|
402
|
+
}
|
403
|
+
bool end_is_empty = CheckIfParamIsEmpty(arguments[2]);
|
404
|
+
if (!end_is_empty) {
|
405
|
+
bound_function.arguments[2] = LogicalType::BIGINT;
|
406
|
+
}
|
407
|
+
|
408
|
+
return make_uniq<ListSliceBindData>(bound_function.return_type, begin_is_empty, end_is_empty);
|
181
409
|
}
|
182
410
|
|
183
|
-
|
411
|
+
ScalarFunctionSet ListSliceFun::GetFunctions() {
|
184
412
|
// the arguments and return types are actually set in the binder function
|
185
|
-
ScalarFunction fun({LogicalType::ANY, LogicalType::
|
186
|
-
|
187
|
-
fun.varargs = LogicalType::ANY;
|
413
|
+
ScalarFunction fun({LogicalType::ANY, LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, ArraySliceFunction,
|
414
|
+
ArraySliceBind);
|
188
415
|
fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING;
|
189
|
-
|
416
|
+
|
417
|
+
ScalarFunctionSet set;
|
418
|
+
set.AddFunction(fun);
|
419
|
+
fun.arguments.push_back(LogicalType::BIGINT);
|
420
|
+
set.AddFunction(fun);
|
421
|
+
return set;
|
190
422
|
}
|
191
423
|
|
192
424
|
} // namespace duckdb
|
@@ -15,8 +15,8 @@ void ExpressionExecutor::Execute(const BoundParameterExpression &expr, Expressio
|
|
15
15
|
const SelectionVector *sel, idx_t count, Vector &result) {
|
16
16
|
D_ASSERT(expr.parameter_data);
|
17
17
|
D_ASSERT(expr.parameter_data->return_type == expr.return_type);
|
18
|
-
D_ASSERT(expr.parameter_data->
|
19
|
-
result.Reference(expr.parameter_data->
|
18
|
+
D_ASSERT(expr.parameter_data->GetValue().type() == expr.return_type);
|
19
|
+
result.Reference(expr.parameter_data->GetValue());
|
20
20
|
}
|
21
21
|
|
22
22
|
} // namespace duckdb
|
@@ -33,21 +33,27 @@ struct ARTIndexScanState : public IndexScanState {
|
|
33
33
|
|
34
34
|
ART::ART(const vector<column_t> &column_ids, TableIOManager &table_io_manager,
|
35
35
|
const vector<unique_ptr<Expression>> &unbound_expressions, const IndexConstraintType constraint_type,
|
36
|
-
AttachedDatabase &db, const
|
36
|
+
AttachedDatabase &db, const shared_ptr<vector<FixedSizeAllocator>> &allocators_ptr, const idx_t block_id,
|
37
|
+
const idx_t block_offset)
|
37
38
|
|
38
|
-
: Index(db, IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type)
|
39
|
+
: Index(db, IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type),
|
40
|
+
allocators(allocators_ptr), owns_data(false) {
|
39
41
|
|
40
42
|
if (!Radix::IsLittleEndian()) {
|
41
43
|
throw NotImplementedException("ART indexes are not supported on big endian architectures");
|
42
44
|
}
|
43
45
|
|
44
46
|
// initialize all allocators
|
45
|
-
allocators
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
if (!allocators) {
|
48
|
+
owns_data = true;
|
49
|
+
allocators = make_shared<vector<FixedSizeAllocator>>();
|
50
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Prefix), buffer_manager.GetBufferAllocator()));
|
51
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Leaf), buffer_manager.GetBufferAllocator()));
|
52
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Node4), buffer_manager.GetBufferAllocator()));
|
53
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Node16), buffer_manager.GetBufferAllocator()));
|
54
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Node48), buffer_manager.GetBufferAllocator()));
|
55
|
+
allocators->emplace_back(FixedSizeAllocator(sizeof(Node256), buffer_manager.GetBufferAllocator()));
|
56
|
+
}
|
51
57
|
|
52
58
|
// set the root node of the tree
|
53
59
|
tree = make_uniq<Node>();
|
@@ -986,26 +992,28 @@ BlockPointer ART::Serialize(MetaBlockWriter &writer) {
|
|
986
992
|
|
987
993
|
void ART::InitializeVacuum(ARTFlags &flags) {
|
988
994
|
|
989
|
-
flags.vacuum_flags.reserve(allocators
|
990
|
-
for (auto &allocator : allocators) {
|
991
|
-
flags.vacuum_flags.push_back(allocator
|
995
|
+
flags.vacuum_flags.reserve(allocators->size());
|
996
|
+
for (auto &allocator : *allocators) {
|
997
|
+
flags.vacuum_flags.push_back(allocator.InitializeVacuum());
|
992
998
|
}
|
993
999
|
}
|
994
1000
|
|
995
1001
|
void ART::FinalizeVacuum(const ARTFlags &flags) {
|
996
1002
|
|
997
|
-
for (idx_t i = 0; i < allocators
|
1003
|
+
for (idx_t i = 0; i < allocators->size(); i++) {
|
998
1004
|
if (flags.vacuum_flags[i]) {
|
999
|
-
allocators[i]
|
1005
|
+
(*allocators)[i].FinalizeVacuum();
|
1000
1006
|
}
|
1001
1007
|
}
|
1002
1008
|
}
|
1003
1009
|
|
1004
1010
|
void ART::Vacuum(IndexLock &state) {
|
1005
1011
|
|
1012
|
+
D_ASSERT(owns_data);
|
1013
|
+
|
1006
1014
|
if (!tree->IsSet()) {
|
1007
|
-
for (auto &allocator : allocators) {
|
1008
|
-
allocator
|
1015
|
+
for (auto &allocator : *allocators) {
|
1016
|
+
allocator.Reset();
|
1009
1017
|
}
|
1010
1018
|
return;
|
1011
1019
|
}
|
@@ -1032,8 +1040,8 @@ void ART::Vacuum(IndexLock &state) {
|
|
1032
1040
|
// finalize the vacuum operation
|
1033
1041
|
FinalizeVacuum(flags);
|
1034
1042
|
|
1035
|
-
for (auto &allocator : allocators) {
|
1036
|
-
allocator
|
1043
|
+
for (auto &allocator : *allocators) {
|
1044
|
+
allocator.Verify();
|
1037
1045
|
}
|
1038
1046
|
}
|
1039
1047
|
|
@@ -1043,9 +1051,11 @@ void ART::Vacuum(IndexLock &state) {
|
|
1043
1051
|
|
1044
1052
|
void ART::InitializeMerge(ARTFlags &flags) {
|
1045
1053
|
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1054
|
+
D_ASSERT(owns_data);
|
1055
|
+
|
1056
|
+
flags.merge_buffer_counts.reserve(allocators->size());
|
1057
|
+
for (auto &allocator : *allocators) {
|
1058
|
+
flags.merge_buffer_counts.emplace_back(allocator.buffers.size());
|
1049
1059
|
}
|
1050
1060
|
}
|
1051
1061
|
|
@@ -1056,16 +1066,18 @@ bool ART::MergeIndexes(IndexLock &state, Index &other_index) {
|
|
1056
1066
|
return true;
|
1057
1067
|
}
|
1058
1068
|
|
1059
|
-
if (
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1069
|
+
if (other_art.owns_data) {
|
1070
|
+
if (tree->IsSet()) {
|
1071
|
+
// fully deserialize other_index, and traverse it to increment its buffer IDs
|
1072
|
+
ARTFlags flags;
|
1073
|
+
InitializeMerge(flags);
|
1074
|
+
other_art.tree->InitializeMerge(other_art, flags);
|
1075
|
+
}
|
1065
1076
|
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1077
|
+
// merge the node storage
|
1078
|
+
for (idx_t i = 0; i < allocators->size(); i++) {
|
1079
|
+
(*allocators)[i].Merge((*other_art.allocators)[i]);
|
1080
|
+
}
|
1069
1081
|
}
|
1070
1082
|
|
1071
1083
|
// merge the ARTs
|
@@ -1073,8 +1085,8 @@ bool ART::MergeIndexes(IndexLock &state, Index &other_index) {
|
|
1073
1085
|
return false;
|
1074
1086
|
}
|
1075
1087
|
|
1076
|
-
for (auto &allocator : allocators) {
|
1077
|
-
allocator
|
1088
|
+
for (auto &allocator : *allocators) {
|
1089
|
+
allocator.Verify();
|
1078
1090
|
}
|
1079
1091
|
return true;
|
1080
1092
|
}
|