duckdb 0.8.2-dev4871.0 → 0.8.2-dev5080.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/package.json +1 -1
- package/src/duckdb/extension/icu/icu-strptime.cpp +1 -0
- package/src/duckdb/extension/json/json_functions/copy_json.cpp +1 -1
- package/src/duckdb/src/common/enum_util.cpp +5 -0
- package/src/duckdb/src/common/operator/cast_operators.cpp +18 -0
- package/src/duckdb/src/common/row_operations/row_matcher.cpp +5 -38
- package/src/duckdb/src/common/types/data_chunk.cpp +47 -10
- package/src/duckdb/src/common/types/vector.cpp +0 -1
- package/src/duckdb/src/common/types.cpp +10 -1
- package/src/duckdb/src/core_functions/scalar/date/strftime.cpp +2 -2
- package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +18 -8
- package/src/duckdb/src/core_functions/scalar/list/list_sort.cpp +10 -1
- package/src/duckdb/src/core_functions/scalar/map/map_concat.cpp +0 -2
- package/src/duckdb/src/core_functions/scalar/struct/struct_pack.cpp +12 -6
- package/src/duckdb/src/execution/nested_loop_join/nested_loop_join_inner.cpp +20 -27
- package/src/duckdb/src/execution/nested_loop_join/nested_loop_join_mark.cpp +21 -9
- package/src/duckdb/src/execution/operator/aggregate/physical_hash_aggregate.cpp +7 -7
- package/src/duckdb/src/execution/operator/csv_scanner/csv_reader_options.cpp +1 -1
- package/src/duckdb/src/execution/operator/csv_scanner/parallel_csv_reader.cpp +0 -2
- package/src/duckdb/src/execution/operator/csv_scanner/sniffer/type_detection.cpp +14 -2
- package/src/duckdb/src/execution/operator/persistent/physical_export.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +13 -8
- package/src/duckdb/src/function/cast/struct_cast.cpp +8 -0
- package/src/duckdb/src/function/cast/time_casts.cpp +12 -0
- package/src/duckdb/src/function/cast/union_casts.cpp +5 -0
- package/src/duckdb/src/function/function_binder.cpp +11 -2
- package/src/duckdb/src/function/pragma/pragma_functions.cpp +5 -0
- package/src/duckdb/src/function/pragma/pragma_queries.cpp +3 -0
- package/src/duckdb/src/function/scalar/strftime_format.cpp +29 -8
- package/src/duckdb/src/function/table/arrow.cpp +4 -0
- package/src/duckdb/src/function/table/copy_csv.cpp +2 -1
- package/src/duckdb/src/function/table/read_csv.cpp +4 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/multi_file_reader.hpp +5 -0
- package/src/duckdb/src/include/duckdb/common/operator/cast_operators.hpp +27 -0
- package/src/duckdb/src/include/duckdb/common/operator/comparison_operators.hpp +38 -2
- package/src/duckdb/src/include/duckdb/common/types.hpp +1 -0
- package/src/duckdb/src/include/duckdb/core_functions/scalar/bit_functions.hpp +4 -4
- package/src/duckdb/src/include/duckdb/core_functions/scalar/blob_functions.hpp +4 -4
- package/src/duckdb/src/include/duckdb/core_functions/scalar/date_functions.hpp +5 -5
- package/src/duckdb/src/include/duckdb/core_functions/scalar/enum_functions.hpp +7 -7
- package/src/duckdb/src/include/duckdb/core_functions/scalar/generic_functions.hpp +12 -12
- package/src/duckdb/src/include/duckdb/core_functions/scalar/list_functions.hpp +12 -12
- package/src/duckdb/src/include/duckdb/core_functions/scalar/map_functions.hpp +3 -3
- package/src/duckdb/src/include/duckdb/core_functions/scalar/math_functions.hpp +33 -33
- package/src/duckdb/src/include/duckdb/core_functions/scalar/operators_functions.hpp +2 -2
- package/src/duckdb/src/include/duckdb/core_functions/scalar/random_functions.hpp +3 -3
- package/src/duckdb/src/include/duckdb/core_functions/scalar/string_functions.hpp +12 -12
- package/src/duckdb/src/include/duckdb/core_functions/scalar/struct_functions.hpp +2 -2
- package/src/duckdb/src/include/duckdb/core_functions/scalar/union_functions.hpp +2 -2
- package/src/duckdb/src/include/duckdb/function/scalar/strftime_format.hpp +2 -1
- package/src/duckdb/src/include/duckdb/main/client_config.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/prepared_statement_data.hpp +1 -0
- package/src/duckdb/src/include/duckdb/planner/bound_parameter_map.hpp +28 -1
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_data.hpp +0 -18
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_expression.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/expression_binder/base_select_binder.hpp +1 -0
- package/src/duckdb/src/include/duckdb/planner/operator/logical_create_table.hpp +1 -2
- package/src/duckdb/src/include/duckdb/planner/operator/logical_delete.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/operator/logical_insert.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/operator/logical_update.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/planner.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +1 -1
- package/src/duckdb/src/main/capi/prepared-c.cpp +9 -3
- package/src/duckdb/src/planner/binder/expression/bind_comparison_expression.cpp +1 -0
- package/src/duckdb/src/planner/binder/expression/bind_parameter_expression.cpp +9 -19
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +28 -6
- package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +3 -0
- package/src/duckdb/src/planner/bound_parameter_map.cpp +67 -0
- package/src/duckdb/src/planner/expression_binder/base_select_binder.cpp +14 -6
- package/src/duckdb/src/planner/operator/logical_create_table.cpp +3 -3
- package/src/duckdb/src/planner/operator/logical_delete.cpp +3 -2
- package/src/duckdb/src/planner/operator/logical_insert.cpp +3 -2
- package/src/duckdb/src/planner/operator/logical_update.cpp +3 -2
- package/src/duckdb/src/planner/planner.cpp +2 -2
- package/src/duckdb/src/storage/data_table.cpp +8 -8
- package/src/duckdb/src/storage/local_storage.cpp +2 -3
- package/src/duckdb/src/storage/serialization/serialize_logical_operator.cpp +64 -80
- package/src/duckdb/src/storage/storage_manager.cpp +6 -2
- package/src/duckdb/src/storage/table/row_group.cpp +6 -0
- package/src/duckdb/src/storage/table/row_group_collection.cpp +4 -3
- package/src/duckdb/src/storage/table/struct_column_data.cpp +5 -0
- package/src/duckdb/src/transaction/duck_transaction.cpp +1 -0
- package/src/duckdb/ub_src_planner.cpp +2 -0
package/package.json
CHANGED
@@ -75,6 +75,7 @@ struct ICUStrptime : public ICUDateFunc {
|
|
75
75
|
calendar->set(UCAL_MINUTE, parsed.data[4]);
|
76
76
|
calendar->set(UCAL_SECOND, parsed.data[5]);
|
77
77
|
calendar->set(UCAL_MILLISECOND, parsed.data[6] / Interval::MICROS_PER_MSEC);
|
78
|
+
micros = parsed.data[6] % Interval::MICROS_PER_MSEC;
|
78
79
|
|
79
80
|
// This overrides the TZ setting, so only use it if an offset was parsed.
|
80
81
|
// Note that we don't bother/worry about the DST setting because the two just combine.
|
@@ -101,7 +101,7 @@ static BoundStatement CopyToJSONPlan(Binder &binder, CopyStatement &stmt) {
|
|
101
101
|
info.options["quote"] = {""};
|
102
102
|
info.options["escape"] = {""};
|
103
103
|
info.options["delimiter"] = {"\n"};
|
104
|
-
info.options["header"] = {0};
|
104
|
+
info.options["header"] = {{0}};
|
105
105
|
|
106
106
|
return binder.Bind(*stmt_copy);
|
107
107
|
}
|
@@ -5503,6 +5503,8 @@ const char* EnumUtil::ToChars<StrTimeSpecifier>(StrTimeSpecifier value) {
|
|
5503
5503
|
return "LOCALE_APPROPRIATE_DATE";
|
5504
5504
|
case StrTimeSpecifier::LOCALE_APPROPRIATE_TIME:
|
5505
5505
|
return "LOCALE_APPROPRIATE_TIME";
|
5506
|
+
case StrTimeSpecifier::NANOSECOND_PADDED:
|
5507
|
+
return "NANOSECOND_PADDED";
|
5506
5508
|
default:
|
5507
5509
|
throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value));
|
5508
5510
|
}
|
@@ -5606,6 +5608,9 @@ StrTimeSpecifier EnumUtil::FromString<StrTimeSpecifier>(const char *value) {
|
|
5606
5608
|
if (StringUtil::Equals(value, "LOCALE_APPROPRIATE_TIME")) {
|
5607
5609
|
return StrTimeSpecifier::LOCALE_APPROPRIATE_TIME;
|
5608
5610
|
}
|
5611
|
+
if (StringUtil::Equals(value, "NANOSECOND_PADDED")) {
|
5612
|
+
return StrTimeSpecifier::NANOSECOND_PADDED;
|
5613
|
+
}
|
5609
5614
|
throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value));
|
5610
5615
|
}
|
5611
5616
|
|
@@ -1373,6 +1373,12 @@ timestamp_t CastTimestampMsToUs::Operation(timestamp_t input) {
|
|
1373
1373
|
return Timestamp::FromEpochMs(input.value);
|
1374
1374
|
}
|
1375
1375
|
|
1376
|
+
template <>
|
1377
|
+
timestamp_t CastTimestampMsToNs::Operation(timestamp_t input) {
|
1378
|
+
auto us = CastTimestampMsToUs::Operation<timestamp_t, timestamp_t>(input);
|
1379
|
+
return CastTimestampUsToNs::Operation<timestamp_t, timestamp_t>(us);
|
1380
|
+
}
|
1381
|
+
|
1376
1382
|
template <>
|
1377
1383
|
timestamp_t CastTimestampNsToUs::Operation(timestamp_t input) {
|
1378
1384
|
return Timestamp::FromEpochNanoSeconds(input.value);
|
@@ -1383,6 +1389,18 @@ timestamp_t CastTimestampSecToUs::Operation(timestamp_t input) {
|
|
1383
1389
|
return Timestamp::FromEpochSeconds(input.value);
|
1384
1390
|
}
|
1385
1391
|
|
1392
|
+
template <>
|
1393
|
+
timestamp_t CastTimestampSecToMs::Operation(timestamp_t input) {
|
1394
|
+
auto us = CastTimestampSecToUs::Operation<timestamp_t, timestamp_t>(input);
|
1395
|
+
return CastTimestampUsToMs::Operation<timestamp_t, timestamp_t>(us);
|
1396
|
+
}
|
1397
|
+
|
1398
|
+
template <>
|
1399
|
+
timestamp_t CastTimestampSecToNs::Operation(timestamp_t input) {
|
1400
|
+
auto us = CastTimestampSecToUs::Operation<timestamp_t, timestamp_t>(input);
|
1401
|
+
return CastTimestampUsToNs::Operation<timestamp_t, timestamp_t>(us);
|
1402
|
+
}
|
1403
|
+
|
1386
1404
|
//===--------------------------------------------------------------------===//
|
1387
1405
|
// Cast To Timestamp
|
1388
1406
|
//===--------------------------------------------------------------------===//
|
@@ -8,44 +8,11 @@ namespace duckdb {
|
|
8
8
|
|
9
9
|
using ValidityBytes = TupleDataLayout::ValidityBytes;
|
10
10
|
|
11
|
-
template <class OP>
|
12
|
-
struct RowMatchOperator {
|
13
|
-
static constexpr const bool COMPARE_NULL = false;
|
14
|
-
|
15
|
-
template <class T>
|
16
|
-
static inline bool Operation(const T &left, const T &right, bool left_null, bool right_null) {
|
17
|
-
if (right_null || left_null) {
|
18
|
-
return false;
|
19
|
-
}
|
20
|
-
return OP::template Operation<T>(left, right);
|
21
|
-
}
|
22
|
-
};
|
23
|
-
|
24
|
-
template <>
|
25
|
-
struct RowMatchOperator<DistinctFrom> {
|
26
|
-
static constexpr const bool COMPARE_NULL = true;
|
27
|
-
|
28
|
-
template <class T>
|
29
|
-
static inline bool Operation(const T &left, const T &right, bool left_null, bool right_null) {
|
30
|
-
return DistinctFrom::template Operation<T>(left, right, left_null, right_null);
|
31
|
-
}
|
32
|
-
};
|
33
|
-
|
34
|
-
template <>
|
35
|
-
struct RowMatchOperator<NotDistinctFrom> {
|
36
|
-
static constexpr const bool COMPARE_NULL = true;
|
37
|
-
|
38
|
-
template <class T>
|
39
|
-
static inline bool Operation(const T &left, const T &right, bool left_null, bool right_null) {
|
40
|
-
return NotDistinctFrom::template Operation<T>(left, right, left_null, right_null);
|
41
|
-
}
|
42
|
-
};
|
43
|
-
|
44
11
|
template <bool NO_MATCH_SEL, class T, class OP>
|
45
12
|
static idx_t TemplatedMatch(Vector &, const TupleDataVectorFormat &lhs_format, SelectionVector &sel, const idx_t count,
|
46
13
|
const TupleDataLayout &rhs_layout, Vector &rhs_row_locations, const idx_t col_idx,
|
47
14
|
const vector<MatchFunction> &, SelectionVector *no_match_sel, idx_t &no_match_count) {
|
48
|
-
using
|
15
|
+
using COMPARISON_OP = ComparisonOperationWrapper<OP>;
|
49
16
|
|
50
17
|
// LHS
|
51
18
|
const auto &lhs_sel = *lhs_format.unified.sel;
|
@@ -70,8 +37,8 @@ static idx_t TemplatedMatch(Vector &, const TupleDataVectorFormat &lhs_format, S
|
|
70
37
|
const ValidityBytes rhs_mask(rhs_location);
|
71
38
|
const auto rhs_null = !rhs_mask.RowIsValid(rhs_mask.GetValidityEntryUnsafe(entry_idx), idx_in_entry);
|
72
39
|
|
73
|
-
if (
|
74
|
-
|
40
|
+
if (COMPARISON_OP::template Operation<T>(lhs_data[lhs_idx], Load<T>(rhs_location + rhs_offset_in_row), lhs_null,
|
41
|
+
rhs_null)) {
|
75
42
|
sel.set_index(match_count++, idx);
|
76
43
|
} else if (NO_MATCH_SEL) {
|
77
44
|
no_match_sel->set_index(no_match_count++, idx);
|
@@ -85,7 +52,7 @@ static idx_t StructMatchEquality(Vector &lhs_vector, const TupleDataVectorFormat
|
|
85
52
|
const idx_t count, const TupleDataLayout &rhs_layout, Vector &rhs_row_locations,
|
86
53
|
const idx_t col_idx, const vector<MatchFunction> &child_functions,
|
87
54
|
SelectionVector *no_match_sel, idx_t &no_match_count) {
|
88
|
-
using
|
55
|
+
using COMPARISON_OP = ComparisonOperationWrapper<OP>;
|
89
56
|
|
90
57
|
// LHS
|
91
58
|
const auto &lhs_sel = *lhs_format.unified.sel;
|
@@ -111,7 +78,7 @@ static idx_t StructMatchEquality(Vector &lhs_vector, const TupleDataVectorFormat
|
|
111
78
|
// For structs there is no value to compare, here we match NULLs and let recursion do the rest
|
112
79
|
// So we use the comparison only if rhs or LHS is NULL and COMPARE_NULL is true
|
113
80
|
if (!(lhs_null || rhs_null) ||
|
114
|
-
(
|
81
|
+
(COMPARISON_OP::COMPARE_NULL && COMPARISON_OP::template Operation<uint32_t>(0, 0, lhs_null, rhs_null))) {
|
115
82
|
sel.set_index(match_count++, idx);
|
116
83
|
} else if (NO_MATCH_SEL) {
|
117
84
|
no_match_sel->set_index(no_match_count++, idx);
|
@@ -13,6 +13,10 @@
|
|
13
13
|
#include "duckdb/common/vector_operations/vector_operations.hpp"
|
14
14
|
#include "duckdb/execution/execution_context.hpp"
|
15
15
|
|
16
|
+
#include "duckdb/common/serializer/memory_stream.hpp"
|
17
|
+
#include "duckdb/common/serializer/binary_serializer.hpp"
|
18
|
+
#include "duckdb/common/serializer/binary_deserializer.hpp"
|
19
|
+
|
16
20
|
namespace duckdb {
|
17
21
|
|
18
22
|
DataChunk::DataChunk() : count(0), capacity(STANDARD_VECTOR_SIZE) {
|
@@ -231,16 +235,20 @@ string DataChunk::ToString() const {
|
|
231
235
|
}
|
232
236
|
|
233
237
|
void DataChunk::Serialize(Serializer &serializer) const {
|
238
|
+
|
234
239
|
// write the count
|
235
240
|
auto row_count = size();
|
236
241
|
serializer.WriteProperty<sel_t>(100, "rows", row_count);
|
242
|
+
|
243
|
+
// we should never try to serialize empty data chunks
|
237
244
|
auto column_count = ColumnCount();
|
245
|
+
D_ASSERT(column_count);
|
238
246
|
|
239
|
-
//
|
247
|
+
// write the types
|
240
248
|
serializer.WriteList(101, "types", column_count,
|
241
249
|
[&](Serializer::List &list, idx_t i) { list.WriteElement(data[i].GetType()); });
|
242
250
|
|
243
|
-
//
|
251
|
+
// write the data
|
244
252
|
serializer.WriteList(102, "columns", column_count, [&](Serializer::List &list, idx_t i) {
|
245
253
|
list.WriteObject([&](Serializer &object) {
|
246
254
|
// Reference the vector to avoid potentially mutating it during serialization
|
@@ -252,21 +260,23 @@ void DataChunk::Serialize(Serializer &serializer) const {
|
|
252
260
|
}
|
253
261
|
|
254
262
|
void DataChunk::Deserialize(Deserializer &deserializer) {
|
255
|
-
|
263
|
+
|
264
|
+
// read and set the row count
|
256
265
|
auto row_count = deserializer.ReadProperty<sel_t>(100, "rows");
|
257
266
|
|
258
|
-
//
|
267
|
+
// read the types
|
259
268
|
vector<LogicalType> types;
|
260
269
|
deserializer.ReadList(101, "types", [&](Deserializer::List &list, idx_t i) {
|
261
270
|
auto type = list.ReadElement<LogicalType>();
|
262
271
|
types.push_back(type);
|
263
272
|
});
|
264
|
-
Initialize(Allocator::DefaultAllocator(), types);
|
265
273
|
|
266
|
-
//
|
274
|
+
// initialize the data chunk
|
275
|
+
D_ASSERT(!types.empty());
|
276
|
+
Initialize(Allocator::DefaultAllocator(), types);
|
267
277
|
SetCardinality(row_count);
|
268
278
|
|
269
|
-
//
|
279
|
+
// read the data
|
270
280
|
deserializer.ReadList(102, "columns", [&](Deserializer::List &list, idx_t i) {
|
271
281
|
list.ReadObject([&](Deserializer &object) { data[i].Deserialize(object, row_count); });
|
272
282
|
});
|
@@ -296,11 +306,11 @@ void DataChunk::Slice(DataChunk &other, const SelectionVector &sel, idx_t count_
|
|
296
306
|
}
|
297
307
|
|
298
308
|
unsafe_unique_array<UnifiedVectorFormat> DataChunk::ToUnifiedFormat() {
|
299
|
-
auto
|
309
|
+
auto unified_data = make_unsafe_uniq_array<UnifiedVectorFormat>(ColumnCount());
|
300
310
|
for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) {
|
301
|
-
data[col_idx].ToUnifiedFormat(size(),
|
311
|
+
data[col_idx].ToUnifiedFormat(size(), unified_data[col_idx]);
|
302
312
|
}
|
303
|
-
return
|
313
|
+
return unified_data;
|
304
314
|
}
|
305
315
|
|
306
316
|
void DataChunk::Hash(Vector &result) {
|
@@ -324,10 +334,37 @@ void DataChunk::Hash(vector<idx_t> &column_ids, Vector &result) {
|
|
324
334
|
void DataChunk::Verify() {
|
325
335
|
#ifdef DEBUG
|
326
336
|
D_ASSERT(size() <= capacity);
|
337
|
+
|
327
338
|
// verify that all vectors in this chunk have the chunk selection vector
|
328
339
|
for (idx_t i = 0; i < ColumnCount(); i++) {
|
329
340
|
data[i].Verify(size());
|
330
341
|
}
|
342
|
+
|
343
|
+
if (!ColumnCount()) {
|
344
|
+
// don't try to round-trip dummy data chunks with no data
|
345
|
+
// e.g., these exist in queries like 'SELECT distinct(col0, col1) FROM tbl', where we have groups, but no
|
346
|
+
// payload so the payload will be such an empty data chunk
|
347
|
+
return;
|
348
|
+
}
|
349
|
+
|
350
|
+
// verify that we can round-trip chunk serialization
|
351
|
+
MemoryStream mem_stream;
|
352
|
+
BinarySerializer serializer(mem_stream);
|
353
|
+
|
354
|
+
serializer.Begin();
|
355
|
+
Serialize(serializer);
|
356
|
+
serializer.End();
|
357
|
+
|
358
|
+
mem_stream.Rewind();
|
359
|
+
|
360
|
+
BinaryDeserializer deserializer(mem_stream);
|
361
|
+
DataChunk new_chunk;
|
362
|
+
|
363
|
+
deserializer.Begin();
|
364
|
+
new_chunk.Deserialize(deserializer);
|
365
|
+
deserializer.End();
|
366
|
+
|
367
|
+
D_ASSERT(size() == new_chunk.size());
|
331
368
|
#endif
|
332
369
|
}
|
333
370
|
|
@@ -434,7 +434,7 @@ LogicalType TransformStringToLogicalType(const string &str) {
|
|
434
434
|
|
435
435
|
LogicalType GetUserTypeRecursive(const LogicalType &type, ClientContext &context) {
|
436
436
|
if (type.id() == LogicalTypeId::USER && type.HasAlias()) {
|
437
|
-
return Catalog::
|
437
|
+
return Catalog::GetType(context, INVALID_CATALOG, INVALID_SCHEMA, type.GetAlias());
|
438
438
|
}
|
439
439
|
// Look for LogicalTypeId::USER in nested types
|
440
440
|
if (type.id() == LogicalTypeId::STRUCT) {
|
@@ -659,6 +659,10 @@ LogicalType LogicalType::MaxLogicalType(const LogicalType &left, const LogicalTy
|
|
659
659
|
return right;
|
660
660
|
} else if (right.id() == LogicalTypeId::UNKNOWN) {
|
661
661
|
return left;
|
662
|
+
} else if ((right.id() == LogicalTypeId::ENUM || left.id() == LogicalTypeId::ENUM) && right.id() != left.id()) {
|
663
|
+
// if one is an enum and the other is not, compare strings, not enums
|
664
|
+
// see https://github.com/duckdb/duckdb/issues/8561
|
665
|
+
return LogicalTypeId::VARCHAR;
|
662
666
|
} else if (left.id() < right.id()) {
|
663
667
|
return right;
|
664
668
|
}
|
@@ -911,6 +915,11 @@ const string &StructType::GetChildName(const LogicalType &type, idx_t index) {
|
|
911
915
|
idx_t StructType::GetChildCount(const LogicalType &type) {
|
912
916
|
return StructType::GetChildTypes(type).size();
|
913
917
|
}
|
918
|
+
bool StructType::IsUnnamed(const LogicalType &type) {
|
919
|
+
auto &child_types = StructType::GetChildTypes(type);
|
920
|
+
D_ASSERT(child_types.size() > 0);
|
921
|
+
return child_types[0].first.empty();
|
922
|
+
}
|
914
923
|
|
915
924
|
LogicalType LogicalType::STRUCT(child_list_t<LogicalType> children) {
|
916
925
|
auto info = make_shared<StructTypeInfo>(std::move(children));
|
@@ -183,7 +183,7 @@ struct StrpTimeFunction {
|
|
183
183
|
auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
|
184
184
|
auto &info = func_expr.bind_info->Cast<StrpTimeBindData>();
|
185
185
|
|
186
|
-
if (ConstantVector::IsNull(args.data[1])) {
|
186
|
+
if (args.data[1].GetVectorType() == VectorType::CONSTANT_VECTOR && ConstantVector::IsNull(args.data[1])) {
|
187
187
|
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
188
188
|
ConstantVector::SetNull(result, true);
|
189
189
|
return;
|
@@ -203,7 +203,7 @@ struct StrpTimeFunction {
|
|
203
203
|
auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
|
204
204
|
auto &info = func_expr.bind_info->Cast<StrpTimeBindData>();
|
205
205
|
|
206
|
-
if (ConstantVector::IsNull(args.data[1])) {
|
206
|
+
if (args.data[1].GetVectorType() == VectorType::CONSTANT_VECTOR && ConstantVector::IsNull(args.data[1])) {
|
207
207
|
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
208
208
|
ConstantVector::SetNull(result, true);
|
209
209
|
return;
|
@@ -191,9 +191,11 @@ static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &beg
|
|
191
191
|
}
|
192
192
|
|
193
193
|
auto sel_length = 0;
|
194
|
+
bool sel_valid = false;
|
194
195
|
if (step_vector && step_valid && str_valid && begin_valid && end_valid && step != 1 && end - begin > 0) {
|
195
196
|
sel_length = CalculateSliceLength(begin, end, step, step_valid);
|
196
197
|
sel.Initialize(sel_length);
|
198
|
+
sel_valid = true;
|
197
199
|
}
|
198
200
|
|
199
201
|
// Try to slice
|
@@ -205,8 +207,9 @@ static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &beg
|
|
205
207
|
result_data[0] = SliceValueWithSteps<INPUT_TYPE, INDEX_TYPE>(result, sel, str, begin, end, step, sel_idx);
|
206
208
|
}
|
207
209
|
|
208
|
-
if (
|
210
|
+
if (sel_valid) {
|
209
211
|
result_child_vector->Slice(sel, sel_length);
|
212
|
+
ListVector::SetListSize(result, sel_length);
|
210
213
|
}
|
211
214
|
}
|
212
215
|
|
@@ -234,6 +237,16 @@ static void ExecuteFlatSlice(Vector &result, Vector &list_vector, Vector &begin_
|
|
234
237
|
auto end_idx = end_data.sel->get_index(i);
|
235
238
|
auto step_idx = step_vector ? step_data.sel->get_index(i) : 0;
|
236
239
|
|
240
|
+
auto list_valid = list_data.validity.RowIsValid(list_idx);
|
241
|
+
auto begin_valid = begin_data.validity.RowIsValid(begin_idx);
|
242
|
+
auto end_valid = end_data.validity.RowIsValid(end_idx);
|
243
|
+
auto step_valid = step_vector && step_data.validity.RowIsValid(step_idx);
|
244
|
+
|
245
|
+
if (!list_valid || !begin_valid || !end_valid || (step_vector && !step_valid)) {
|
246
|
+
result_mask.SetInvalid(i);
|
247
|
+
continue;
|
248
|
+
}
|
249
|
+
|
237
250
|
auto sliced = reinterpret_cast<INPUT_TYPE *>(list_data.data)[list_idx];
|
238
251
|
auto begin = begin_is_empty ? 0 : reinterpret_cast<INDEX_TYPE *>(begin_data.data)[begin_idx];
|
239
252
|
auto end = end_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(sliced)
|
@@ -245,23 +258,19 @@ static void ExecuteFlatSlice(Vector &result, Vector &list_vector, Vector &begin_
|
|
245
258
|
begin = end_is_empty ? 0 : begin;
|
246
259
|
end = begin_is_empty ? ValueLength<INPUT_TYPE, INDEX_TYPE>(sliced) : end;
|
247
260
|
}
|
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
261
|
|
253
262
|
bool clamp_result = false;
|
254
|
-
if (
|
263
|
+
if (step_valid || step == 1) {
|
255
264
|
clamp_result = ClampSlice(sliced, begin, end);
|
256
265
|
}
|
257
266
|
|
258
267
|
auto length = 0;
|
259
|
-
if (
|
268
|
+
if (end - begin > 0) {
|
260
269
|
length = CalculateSliceLength(begin, end, step, step_valid);
|
261
270
|
}
|
262
271
|
sel_length += length;
|
263
272
|
|
264
|
-
if (!
|
273
|
+
if (!clamp_result) {
|
265
274
|
result_mask.SetInvalid(i);
|
266
275
|
} else if (!step_vector) {
|
267
276
|
result_data[i] = SliceValue<INPUT_TYPE, INDEX_TYPE>(result, sliced, begin, end);
|
@@ -276,6 +285,7 @@ static void ExecuteFlatSlice(Vector &result, Vector &list_vector, Vector &begin_
|
|
276
285
|
new_sel.set_index(i, sel.get_index(i));
|
277
286
|
}
|
278
287
|
result_child_vector->Slice(new_sel, sel_length);
|
288
|
+
ListVector::SetListSize(result, sel_length);
|
279
289
|
}
|
280
290
|
}
|
281
291
|
|
@@ -236,9 +236,18 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re
|
|
236
236
|
static unique_ptr<FunctionData> ListSortBind(ClientContext &context, ScalarFunction &bound_function,
|
237
237
|
vector<unique_ptr<Expression>> &arguments, OrderType &order,
|
238
238
|
OrderByNullType &null_order) {
|
239
|
+
|
240
|
+
LogicalType child_type;
|
241
|
+
if (arguments[0]->return_type == LogicalTypeId::UNKNOWN) {
|
242
|
+
bound_function.arguments[0] = LogicalTypeId::UNKNOWN;
|
243
|
+
bound_function.return_type = LogicalType::SQLNULL;
|
244
|
+
child_type = bound_function.return_type;
|
245
|
+
return make_uniq<ListSortBindData>(order, null_order, bound_function.return_type, child_type, context);
|
246
|
+
}
|
247
|
+
|
239
248
|
bound_function.arguments[0] = arguments[0]->return_type;
|
240
249
|
bound_function.return_type = arguments[0]->return_type;
|
241
|
-
|
250
|
+
child_type = ListType::GetChildType(arguments[0]->return_type);
|
242
251
|
|
243
252
|
return make_uniq<ListSortBindData>(order, null_order, bound_function.return_type, child_type, context);
|
244
253
|
}
|
@@ -97,7 +97,6 @@ static void MapConcatFunction(DataChunk &args, ExpressionState &state, Vector &r
|
|
97
97
|
auto &values = MapVector::GetValues(map);
|
98
98
|
values_list.push_back(values.GetValue(mapping.key_index));
|
99
99
|
}
|
100
|
-
idx_t entries_count = keys_list.size();
|
101
100
|
D_ASSERT(values_list.size() == keys_list.size());
|
102
101
|
result_entry.offset = ListVector::GetListSize(result);
|
103
102
|
result_entry.length = values_list.size();
|
@@ -105,7 +104,6 @@ static void MapConcatFunction(DataChunk &args, ExpressionState &state, Vector &r
|
|
105
104
|
for (auto &list_entry : list_entries) {
|
106
105
|
ListVector::PushBack(result, list_entry);
|
107
106
|
}
|
108
|
-
ListVector::SetListSize(result, ListVector::GetListSize(result) + entries_count);
|
109
107
|
}
|
110
108
|
|
111
109
|
if (args.AllConstant()) {
|
@@ -39,15 +39,21 @@ static unique_ptr<FunctionData> StructPackBind(ClientContext &context, ScalarFun
|
|
39
39
|
throw Exception("Can't pack nothing into a struct");
|
40
40
|
}
|
41
41
|
child_list_t<LogicalType> struct_children;
|
42
|
+
bool unnamed = false;
|
42
43
|
for (idx_t i = 0; i < arguments.size(); i++) {
|
43
44
|
auto &child = arguments[i];
|
44
|
-
if (child->alias.empty()
|
45
|
-
|
45
|
+
if (child->alias.empty()) {
|
46
|
+
if (bound_function.name == "struct_pack") {
|
47
|
+
throw BinderException("Need named argument for struct pack, e.g. STRUCT_PACK(a := b)");
|
48
|
+
} else {
|
49
|
+
D_ASSERT(bound_function.name == "row");
|
50
|
+
if (i > 1) {
|
51
|
+
D_ASSERT(unnamed);
|
52
|
+
}
|
53
|
+
unnamed = true;
|
54
|
+
}
|
46
55
|
}
|
47
|
-
if (child->alias.empty() &&
|
48
|
-
child->alias = "v" + std::to_string(i + 1);
|
49
|
-
}
|
50
|
-
if (name_collision_set.find(child->alias) != name_collision_set.end()) {
|
56
|
+
if (!child->alias.empty() && name_collision_set.find(child->alias) != name_collision_set.end()) {
|
51
57
|
throw BinderException("Duplicate struct entry name \"%s\"", child->alias);
|
52
58
|
}
|
53
59
|
name_collision_set.insert(child->alias);
|
@@ -3,21 +3,12 @@
|
|
3
3
|
|
4
4
|
namespace duckdb {
|
5
5
|
|
6
|
-
template <class OP>
|
7
|
-
struct ComparisonOperationWrapper {
|
8
|
-
template <class T>
|
9
|
-
static inline bool Operation(T left, T right, bool left_is_null, bool right_is_null) {
|
10
|
-
if (left_is_null || right_is_null) {
|
11
|
-
return false;
|
12
|
-
}
|
13
|
-
return OP::Operation(left, right);
|
14
|
-
}
|
15
|
-
};
|
16
|
-
|
17
6
|
struct InitialNestedLoopJoin {
|
18
7
|
template <class T, class OP>
|
19
8
|
static idx_t Operation(Vector &left, Vector &right, idx_t left_size, idx_t right_size, idx_t &lpos, idx_t &rpos,
|
20
9
|
SelectionVector &lvector, SelectionVector &rvector, idx_t current_match_count) {
|
10
|
+
using MATCH_OP = ComparisonOperationWrapper<OP>;
|
11
|
+
|
21
12
|
// initialize phase of nested loop join
|
22
13
|
// fill lvector and rvector with matches from the base vectors
|
23
14
|
UnifiedVectorFormat left_data, right_data;
|
@@ -37,7 +28,7 @@ struct InitialNestedLoopJoin {
|
|
37
28
|
}
|
38
29
|
idx_t left_position = left_data.sel->get_index(lpos);
|
39
30
|
bool left_is_valid = left_data.validity.RowIsValid(left_position);
|
40
|
-
if (
|
31
|
+
if (MATCH_OP::Operation(ldata[left_position], rdata[right_position], !left_is_valid, !right_is_valid)) {
|
41
32
|
// emit tuple
|
42
33
|
lvector.set_index(result_count, lpos);
|
43
34
|
rvector.set_index(result_count, rpos);
|
@@ -54,6 +45,8 @@ struct RefineNestedLoopJoin {
|
|
54
45
|
template <class T, class OP>
|
55
46
|
static idx_t Operation(Vector &left, Vector &right, idx_t left_size, idx_t right_size, idx_t &lpos, idx_t &rpos,
|
56
47
|
SelectionVector &lvector, SelectionVector &rvector, idx_t current_match_count) {
|
48
|
+
using MATCH_OP = ComparisonOperationWrapper<OP>;
|
49
|
+
|
57
50
|
UnifiedVectorFormat left_data, right_data;
|
58
51
|
left.ToUnifiedFormat(left_size, left_data);
|
59
52
|
right.ToUnifiedFormat(right_size, right_data);
|
@@ -72,7 +65,7 @@ struct RefineNestedLoopJoin {
|
|
72
65
|
auto right_idx = right_data.sel->get_index(ridx);
|
73
66
|
bool left_is_valid = left_data.validity.RowIsValid(left_idx);
|
74
67
|
bool right_is_valid = right_data.validity.RowIsValid(right_idx);
|
75
|
-
if (
|
68
|
+
if (MATCH_OP::Operation(ldata[left_idx], rdata[right_idx], !left_is_valid, !right_is_valid)) {
|
76
69
|
lvector.set_index(result_count, lidx);
|
77
70
|
rvector.set_index(result_count, ridx);
|
78
71
|
result_count++;
|
@@ -139,26 +132,26 @@ idx_t NestedLoopJoinComparisonSwitch(Vector &left, Vector &right, idx_t left_siz
|
|
139
132
|
D_ASSERT(left.GetType() == right.GetType());
|
140
133
|
switch (comparison_type) {
|
141
134
|
case ExpressionType::COMPARE_EQUAL:
|
142
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
143
|
-
|
135
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, Equals>(left, right, left_size, right_size, lpos, rpos, lvector,
|
136
|
+
rvector, current_match_count);
|
144
137
|
case ExpressionType::COMPARE_NOTEQUAL:
|
145
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
146
|
-
|
138
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, NotEquals>(left, right, left_size, right_size, lpos, rpos, lvector,
|
139
|
+
rvector, current_match_count);
|
147
140
|
case ExpressionType::COMPARE_LESSTHAN:
|
148
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
149
|
-
|
141
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, LessThan>(left, right, left_size, right_size, lpos, rpos, lvector,
|
142
|
+
rvector, current_match_count);
|
150
143
|
case ExpressionType::COMPARE_GREATERTHAN:
|
151
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
152
|
-
|
144
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, GreaterThan>(left, right, left_size, right_size, lpos, rpos, lvector,
|
145
|
+
rvector, current_match_count);
|
153
146
|
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
154
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
155
|
-
|
147
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, LessThanEquals>(left, right, left_size, right_size, lpos, rpos, lvector,
|
148
|
+
rvector, current_match_count);
|
156
149
|
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
157
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
158
|
-
|
150
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, GreaterThanEquals>(left, right, left_size, right_size, lpos, rpos,
|
151
|
+
lvector, rvector, current_match_count);
|
159
152
|
case ExpressionType::COMPARE_DISTINCT_FROM:
|
160
|
-
return NestedLoopJoinTypeSwitch<NLTYPE,
|
161
|
-
|
153
|
+
return NestedLoopJoinTypeSwitch<NLTYPE, DistinctFrom>(left, right, left_size, right_size, lpos, rpos, lvector,
|
154
|
+
rvector, current_match_count);
|
162
155
|
default:
|
163
156
|
throw NotImplementedException("Unimplemented comparison type for join!");
|
164
157
|
}
|
@@ -6,6 +6,8 @@ namespace duckdb {
|
|
6
6
|
|
7
7
|
template <class T, class OP>
|
8
8
|
static void TemplatedMarkJoin(Vector &left, Vector &right, idx_t lcount, idx_t rcount, bool found_match[]) {
|
9
|
+
using MATCH_OP = ComparisonOperationWrapper<OP>;
|
10
|
+
|
9
11
|
UnifiedVectorFormat left_data, right_data;
|
10
12
|
left.ToUnifiedFormat(lcount, left_data);
|
11
13
|
right.ToUnifiedFormat(rcount, right_data);
|
@@ -17,15 +19,17 @@ static void TemplatedMarkJoin(Vector &left, Vector &right, idx_t lcount, idx_t r
|
|
17
19
|
continue;
|
18
20
|
}
|
19
21
|
auto lidx = left_data.sel->get_index(i);
|
20
|
-
|
22
|
+
const auto left_null = !left_data.validity.RowIsValid(lidx);
|
23
|
+
if (!MATCH_OP::COMPARE_NULL && left_null) {
|
21
24
|
continue;
|
22
25
|
}
|
23
26
|
for (idx_t j = 0; j < rcount; j++) {
|
24
27
|
auto ridx = right_data.sel->get_index(j);
|
25
|
-
|
28
|
+
const auto right_null = !right_data.validity.RowIsValid(ridx);
|
29
|
+
if (!MATCH_OP::COMPARE_NULL && right_null) {
|
26
30
|
continue;
|
27
31
|
}
|
28
|
-
if (
|
32
|
+
if (MATCH_OP::template Operation<T>(ldata[lidx], rdata[ridx], left_null, right_null)) {
|
29
33
|
found_match[i] = true;
|
30
34
|
break;
|
31
35
|
}
|
@@ -62,6 +66,12 @@ static void MarkJoinNested(Vector &left, Vector &right, idx_t lcount, idx_t rcou
|
|
62
66
|
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
63
67
|
count = VectorOperations::GreaterThanEquals(left_reference, right, nullptr, rcount, nullptr, nullptr);
|
64
68
|
break;
|
69
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
70
|
+
count = VectorOperations::DistinctFrom(left_reference, right, nullptr, rcount, nullptr, nullptr);
|
71
|
+
break;
|
72
|
+
case ExpressionType::COMPARE_NOT_DISTINCT_FROM:
|
73
|
+
count = VectorOperations::NotDistinctFrom(left_reference, right, nullptr, rcount, nullptr, nullptr);
|
74
|
+
break;
|
65
75
|
default:
|
66
76
|
throw InternalException("Unsupported comparison type for MarkJoinNested");
|
67
77
|
}
|
@@ -116,17 +126,19 @@ static void MarkJoinComparisonSwitch(Vector &left, Vector &right, idx_t lcount,
|
|
116
126
|
D_ASSERT(left.GetType() == right.GetType());
|
117
127
|
switch (comparison_type) {
|
118
128
|
case ExpressionType::COMPARE_EQUAL:
|
119
|
-
return MarkJoinSwitch<
|
129
|
+
return MarkJoinSwitch<Equals>(left, right, lcount, rcount, found_match);
|
120
130
|
case ExpressionType::COMPARE_NOTEQUAL:
|
121
|
-
return MarkJoinSwitch<
|
131
|
+
return MarkJoinSwitch<NotEquals>(left, right, lcount, rcount, found_match);
|
122
132
|
case ExpressionType::COMPARE_LESSTHAN:
|
123
|
-
return MarkJoinSwitch<
|
133
|
+
return MarkJoinSwitch<LessThan>(left, right, lcount, rcount, found_match);
|
124
134
|
case ExpressionType::COMPARE_GREATERTHAN:
|
125
|
-
return MarkJoinSwitch<
|
135
|
+
return MarkJoinSwitch<GreaterThan>(left, right, lcount, rcount, found_match);
|
126
136
|
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
127
|
-
return MarkJoinSwitch<
|
137
|
+
return MarkJoinSwitch<LessThanEquals>(left, right, lcount, rcount, found_match);
|
128
138
|
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
129
|
-
return MarkJoinSwitch<
|
139
|
+
return MarkJoinSwitch<GreaterThanEquals>(left, right, lcount, rcount, found_match);
|
140
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
141
|
+
return MarkJoinSwitch<DistinctFrom>(left, right, lcount, rcount, found_match);
|
130
142
|
default:
|
131
143
|
throw NotImplementedException("Unimplemented comparison type for join!");
|
132
144
|
}
|