duckdb 1.1.0 → 1.1.1-dev3.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 +2 -1
- package/package.json +1 -1
- package/src/duckdb/extension/icu/third_party/icu/stubdata/stubdata.cpp +1 -1
- package/src/duckdb/extension/json/include/json_common.hpp +14 -4
- package/src/duckdb/extension/json/include/json_executors.hpp +11 -3
- package/src/duckdb/extension/json/json_extension.cpp +1 -1
- package/src/duckdb/extension/json/json_functions/json_extract.cpp +11 -3
- package/src/duckdb/extension/json/json_functions/json_value.cpp +4 -3
- package/src/duckdb/extension/json/json_functions.cpp +16 -7
- package/src/duckdb/extension/parquet/column_reader.cpp +3 -0
- package/src/duckdb/extension/parquet/column_writer.cpp +54 -43
- package/src/duckdb/extension/parquet/geo_parquet.cpp +19 -0
- package/src/duckdb/extension/parquet/include/geo_parquet.hpp +10 -6
- package/src/duckdb/extension/parquet/include/templated_column_reader.hpp +3 -3
- package/src/duckdb/extension/parquet/parquet_writer.cpp +2 -1
- package/src/duckdb/src/common/arrow/arrow_converter.cpp +1 -1
- package/src/duckdb/src/common/arrow/arrow_merge_event.cpp +1 -0
- package/src/duckdb/src/common/arrow/arrow_util.cpp +60 -0
- package/src/duckdb/src/common/arrow/arrow_wrapper.cpp +1 -53
- package/src/duckdb/src/common/cgroups.cpp +15 -24
- package/src/duckdb/src/common/constants.cpp +8 -0
- package/src/duckdb/src/common/enum_util.cpp +331 -326
- package/src/duckdb/src/common/http_util.cpp +5 -1
- package/src/duckdb/src/common/operator/cast_operators.cpp +6 -60
- package/src/duckdb/src/common/types/bit.cpp +1 -1
- package/src/duckdb/src/common/types/column/column_data_allocator.cpp +18 -1
- package/src/duckdb/src/common/types/row/tuple_data_allocator.cpp +2 -1
- package/src/duckdb/src/common/types/row/tuple_data_segment.cpp +5 -0
- package/src/duckdb/src/core_functions/aggregate/distributive/arg_min_max.cpp +1 -1
- package/src/duckdb/src/core_functions/aggregate/distributive/minmax.cpp +2 -1
- package/src/duckdb/src/execution/index/art/iterator.cpp +17 -15
- package/src/duckdb/src/execution/index/art/prefix.cpp +9 -34
- package/src/duckdb/src/execution/index/fixed_size_buffer.cpp +4 -3
- package/src/duckdb/src/execution/operator/aggregate/physical_ungrouped_aggregate.cpp +1 -0
- package/src/duckdb/src/execution/operator/csv_scanner/buffer_manager/csv_buffer.cpp +2 -1
- package/src/duckdb/src/execution/operator/csv_scanner/scanner/base_scanner.cpp +2 -2
- package/src/duckdb/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp +23 -1
- package/src/duckdb/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp +33 -4
- package/src/duckdb/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp +23 -13
- package/src/duckdb/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp +23 -19
- package/src/duckdb/src/execution/operator/csv_scanner/sniffer/header_detection.cpp +12 -11
- package/src/duckdb/src/execution/operator/csv_scanner/sniffer/type_detection.cpp +20 -14
- package/src/duckdb/src/execution/operator/csv_scanner/state_machine/csv_state_machine_cache.cpp +4 -4
- package/src/duckdb/src/execution/operator/csv_scanner/util/csv_error.cpp +3 -1
- package/src/duckdb/src/execution/operator/join/physical_piecewise_merge_join.cpp +6 -1
- package/src/duckdb/src/function/cast/decimal_cast.cpp +33 -3
- package/src/duckdb/src/function/table/arrow/arrow_duck_schema.cpp +9 -0
- package/src/duckdb/src/function/table/arrow.cpp +34 -22
- package/src/duckdb/src/function/table/sniff_csv.cpp +4 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +3 -3
- package/src/duckdb/src/include/duckdb/common/arrow/arrow_util.hpp +31 -0
- package/src/duckdb/src/include/duckdb/common/arrow/arrow_wrapper.hpp +2 -16
- package/src/duckdb/src/include/duckdb/common/operator/cast_operators.hpp +60 -0
- package/src/duckdb/src/include/duckdb/common/types/column/column_data_allocator.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/types/hugeint.hpp +0 -1
- package/src/duckdb/src/include/duckdb/common/types/row/row_data_collection.hpp +2 -1
- package/src/duckdb/src/include/duckdb/core_functions/aggregate/minmax_n_helpers.hpp +9 -5
- package/src/duckdb/src/include/duckdb/execution/executor.hpp +1 -0
- package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp +5 -2
- package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp +5 -1
- package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/csv_sniffer.hpp +5 -5
- package/src/duckdb/src/include/duckdb/execution/operator/helper/physical_result_collector.hpp +1 -0
- package/src/duckdb/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +11 -0
- package/src/duckdb/src/include/duckdb/main/config.hpp +2 -2
- package/src/duckdb/src/include/duckdb/main/extension.hpp +1 -0
- package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +14 -5
- package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +1 -1
- package/src/duckdb/src/include/duckdb/main/settings.hpp +4 -2
- package/src/duckdb/src/include/duckdb/parser/keyword_helper.hpp +3 -0
- package/src/duckdb/src/include/duckdb/parser/parser.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/simplified_token.hpp +7 -1
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +2 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder/select_binder.hpp +2 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +3 -1
- package/src/duckdb/src/include/duckdb/storage/block_manager.hpp +3 -1
- package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +7 -4
- package/src/duckdb/src/include/duckdb/storage/buffer/buffer_handle.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/buffer/buffer_pool.hpp +2 -1
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +4 -4
- package/src/duckdb/src/include/duckdb/storage/standard_buffer_manager.hpp +3 -4
- package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +4 -2
- package/src/duckdb/src/include/duckdb/storage/table/standard_column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/transaction/duck_transaction.hpp +1 -0
- package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +1 -0
- package/src/duckdb/src/include/duckdb/transaction/transaction_manager.hpp +1 -1
- package/src/duckdb/src/include/duckdb.h +8 -8
- package/src/duckdb/src/main/appender.cpp +1 -1
- package/src/duckdb/src/main/capi/duckdb_value-c.cpp +3 -3
- package/src/duckdb/src/main/capi/helper-c.cpp +4 -0
- package/src/duckdb/src/main/config.cpp +24 -11
- package/src/duckdb/src/main/database.cpp +6 -5
- package/src/duckdb/src/main/extension/extension_install.cpp +13 -8
- package/src/duckdb/src/main/extension/extension_load.cpp +10 -4
- package/src/duckdb/src/main/extension.cpp +1 -1
- package/src/duckdb/src/optimizer/filter_pushdown.cpp +10 -1
- package/src/duckdb/src/optimizer/join_filter_pushdown_optimizer.cpp +9 -5
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +14 -8
- package/src/duckdb/src/optimizer/join_order/query_graph_manager.cpp +2 -0
- package/src/duckdb/src/optimizer/join_order/relation_manager.cpp +15 -0
- package/src/duckdb/src/optimizer/optimizer.cpp +4 -1
- package/src/duckdb/src/optimizer/pushdown/pushdown_cross_product.cpp +1 -11
- package/src/duckdb/src/optimizer/pushdown/pushdown_inner_join.cpp +1 -7
- package/src/duckdb/src/optimizer/pushdown/pushdown_left_join.cpp +1 -1
- package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +3 -0
- package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +1 -0
- package/src/duckdb/src/parser/keyword_helper.cpp +4 -0
- package/src/duckdb/src/parser/parser.cpp +20 -18
- package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +8 -3
- package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +3 -0
- package/src/duckdb/src/planner/binder/expression/bind_lambda.cpp +7 -1
- package/src/duckdb/src/planner/binder/expression/bind_unnest_expression.cpp +13 -0
- package/src/duckdb/src/planner/binder/statement/bind_copy_database.cpp +7 -11
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +27 -10
- package/src/duckdb/src/planner/binder/statement/bind_export.cpp +24 -9
- package/src/duckdb/src/planner/binder/tableref/plan_joinref.cpp +1 -3
- package/src/duckdb/src/planner/binder.cpp +5 -6
- package/src/duckdb/src/planner/expression/bound_cast_expression.cpp +1 -0
- package/src/duckdb/src/planner/expression_binder/select_binder.cpp +9 -0
- package/src/duckdb/src/planner/operator/logical_copy_to_file.cpp +2 -2
- package/src/duckdb/src/planner/operator/logical_positional_join.cpp +1 -0
- package/src/duckdb/src/storage/buffer/block_handle.cpp +18 -21
- package/src/duckdb/src/storage/buffer/block_manager.cpp +12 -4
- package/src/duckdb/src/storage/buffer/buffer_handle.cpp +2 -2
- package/src/duckdb/src/storage/buffer/buffer_pool.cpp +12 -2
- package/src/duckdb/src/storage/buffer_manager.cpp +3 -2
- package/src/duckdb/src/storage/compression/rle.cpp +5 -2
- package/src/duckdb/src/storage/compression/string_uncompressed.cpp +2 -1
- package/src/duckdb/src/storage/metadata/metadata_manager.cpp +8 -7
- package/src/duckdb/src/storage/standard_buffer_manager.cpp +19 -20
- package/src/duckdb/src/storage/statistics/column_statistics.cpp +1 -2
- package/src/duckdb/src/storage/table/column_data.cpp +5 -2
- package/src/duckdb/src/storage/table/column_segment.cpp +2 -2
- package/src/duckdb/src/storage/table/row_group_collection.cpp +18 -14
- package/src/duckdb/src/storage/table/standard_column_data.cpp +3 -3
- package/src/duckdb/src/storage/wal_replay.cpp +2 -3
- package/src/duckdb/third_party/libpg_query/include/common/keywords.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/include/parser/parser.hpp +1 -2
- package/src/duckdb/third_party/libpg_query/include/pg_simplified_token.hpp +6 -4
- package/src/duckdb/third_party/libpg_query/include/postgres_parser.hpp +1 -1
- package/src/duckdb/third_party/libpg_query/postgres_parser.cpp +1 -1
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +801 -799
- package/src/duckdb/third_party/libpg_query/src_backend_parser_parser.cpp +6 -2
- package/src/duckdb/third_party/libpg_query/src_common_keywords.cpp +0 -1
- package/src/duckdb/ub_src_common_arrow.cpp +2 -0
- package/vendor.py +1 -2
@@ -12,6 +12,7 @@
|
|
12
12
|
#include "duckdb/storage/table/table_index_list.hpp"
|
13
13
|
#include "duckdb/storage/table/table_statistics.hpp"
|
14
14
|
#include "duckdb/storage/optimistic_data_writer.hpp"
|
15
|
+
#include "duckdb/common/error_data.hpp"
|
15
16
|
#include "duckdb/common/reference_map.hpp"
|
16
17
|
|
17
18
|
namespace duckdb {
|
@@ -133,6 +133,8 @@ typedef enum DUCKDB_TYPE {
|
|
133
133
|
DUCKDB_TYPE_ANY = 34,
|
134
134
|
// duckdb_varint
|
135
135
|
DUCKDB_TYPE_VARINT = 35,
|
136
|
+
// SQLNULL type
|
137
|
+
DUCKDB_TYPE_SQLNULL = 36,
|
136
138
|
} duckdb_type;
|
137
139
|
//! An enum over the returned state of different functions.
|
138
140
|
typedef enum duckdb_state { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state;
|
@@ -866,8 +868,8 @@ Returns the number of rows present in the result object.
|
|
866
868
|
* @return The number of rows present in the result object.
|
867
869
|
*/
|
868
870
|
DUCKDB_API idx_t duckdb_row_count(duckdb_result *result);
|
869
|
-
#endif
|
870
871
|
|
872
|
+
#endif
|
871
873
|
/*!
|
872
874
|
Returns the number of rows changed by the query stored in the result. This is relevant only for INSERT/UPDATE/DELETE
|
873
875
|
queries. For other queries the rows_changed will be 0.
|
@@ -898,9 +900,7 @@ printf("Data for row %d: %d\n", row, data[row]);
|
|
898
900
|
* @return The column data of the specified column.
|
899
901
|
*/
|
900
902
|
DUCKDB_API void *duckdb_column_data(duckdb_result *result, idx_t col);
|
901
|
-
#endif
|
902
903
|
|
903
|
-
#ifndef DUCKDB_API_NO_DEPRECATED
|
904
904
|
/*!
|
905
905
|
**DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead.
|
906
906
|
|
@@ -923,8 +923,8 @@ if (nullmask[row]) {
|
|
923
923
|
* @return The nullmask of the specified column.
|
924
924
|
*/
|
925
925
|
DUCKDB_API bool *duckdb_nullmask_data(duckdb_result *result, idx_t col);
|
926
|
-
#endif
|
927
926
|
|
927
|
+
#endif
|
928
928
|
/*!
|
929
929
|
Returns the error message contained within the result. The error is only set if `duckdb_query` returns `DuckDBError`.
|
930
930
|
|
@@ -990,6 +990,7 @@ Returns the number of data chunks present in the result.
|
|
990
990
|
*/
|
991
991
|
DUCKDB_API idx_t duckdb_result_chunk_count(duckdb_result result);
|
992
992
|
|
993
|
+
#endif
|
993
994
|
/*!
|
994
995
|
Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on error
|
995
996
|
|
@@ -998,7 +999,6 @@ Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on er
|
|
998
999
|
*/
|
999
1000
|
DUCKDB_API duckdb_result_type duckdb_result_return_type(duckdb_result result);
|
1000
1001
|
|
1001
|
-
#endif
|
1002
1002
|
//===--------------------------------------------------------------------===//
|
1003
1003
|
// Safe Fetch Functions
|
1004
1004
|
//===--------------------------------------------------------------------===//
|
@@ -1663,8 +1663,8 @@ Note that the result must be freed with `duckdb_destroy_result`.
|
|
1663
1663
|
*/
|
1664
1664
|
DUCKDB_API duckdb_state duckdb_execute_prepared_streaming(duckdb_prepared_statement prepared_statement,
|
1665
1665
|
duckdb_result *out_result);
|
1666
|
-
#endif
|
1667
1666
|
|
1667
|
+
#endif
|
1668
1668
|
//===--------------------------------------------------------------------===//
|
1669
1669
|
// Extract Statements
|
1670
1670
|
//===--------------------------------------------------------------------===//
|
@@ -1754,8 +1754,8 @@ Note that after calling `duckdb_pending_prepared_streaming`, the pending result
|
|
1754
1754
|
*/
|
1755
1755
|
DUCKDB_API duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement,
|
1756
1756
|
duckdb_pending_result *out_result);
|
1757
|
-
#endif
|
1758
1757
|
|
1758
|
+
#endif
|
1759
1759
|
/*!
|
1760
1760
|
Closes the pending result and de-allocates all memory allocated for the result.
|
1761
1761
|
|
@@ -4038,8 +4038,8 @@ It is not known beforehand how many chunks will be returned by this result.
|
|
4038
4038
|
* @return The resulting data chunk. Returns `NULL` if the result has an error.
|
4039
4039
|
*/
|
4040
4040
|
DUCKDB_API duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result);
|
4041
|
-
#endif
|
4042
4041
|
|
4042
|
+
#endif
|
4043
4043
|
/*!
|
4044
4044
|
Fetches a data chunk from a duckdb_result. This function should be called repeatedly until the result is exhausted.
|
4045
4045
|
|
@@ -114,7 +114,7 @@ void BaseAppender::BeginRow() {
|
|
114
114
|
void BaseAppender::EndRow() {
|
115
115
|
// check that all rows have been appended to
|
116
116
|
if (column != chunk.ColumnCount()) {
|
117
|
-
throw InvalidInputException("Call to EndRow before all
|
117
|
+
throw InvalidInputException("Call to EndRow before all columns have been appended to!");
|
118
118
|
}
|
119
119
|
column = 0;
|
120
120
|
chunk.SetCardinality(chunk.size() + 1);
|
@@ -282,7 +282,7 @@ idx_t duckdb_get_map_size(duckdb_value value) {
|
|
282
282
|
}
|
283
283
|
|
284
284
|
auto val = UnwrapValue(value);
|
285
|
-
if (val.type() != LogicalTypeId::MAP) {
|
285
|
+
if (val.type().id() != LogicalTypeId::MAP) {
|
286
286
|
return 0;
|
287
287
|
}
|
288
288
|
|
@@ -296,7 +296,7 @@ duckdb_value duckdb_get_map_key(duckdb_value value, idx_t index) {
|
|
296
296
|
}
|
297
297
|
|
298
298
|
auto val = UnwrapValue(value);
|
299
|
-
if (val.type() != LogicalTypeId::MAP) {
|
299
|
+
if (val.type().id() != LogicalTypeId::MAP) {
|
300
300
|
return nullptr;
|
301
301
|
}
|
302
302
|
|
@@ -316,7 +316,7 @@ duckdb_value duckdb_get_map_value(duckdb_value value, idx_t index) {
|
|
316
316
|
}
|
317
317
|
|
318
318
|
auto val = UnwrapValue(value);
|
319
|
-
if (val.type() != LogicalTypeId::MAP) {
|
319
|
+
if (val.type().id() != LogicalTypeId::MAP) {
|
320
320
|
return nullptr;
|
321
321
|
}
|
322
322
|
|
@@ -74,6 +74,8 @@ LogicalTypeId ConvertCTypeToCPP(duckdb_type c_type) {
|
|
74
74
|
return LogicalTypeId::TIMESTAMP_TZ;
|
75
75
|
case DUCKDB_TYPE_ANY:
|
76
76
|
return LogicalTypeId::ANY;
|
77
|
+
case DUCKDB_TYPE_SQLNULL:
|
78
|
+
return LogicalTypeId::SQLNULL;
|
77
79
|
default: // LCOV_EXCL_START
|
78
80
|
D_ASSERT(0);
|
79
81
|
return LogicalTypeId::INVALID;
|
@@ -154,6 +156,8 @@ duckdb_type ConvertCPPTypeToC(const LogicalType &sql_type) {
|
|
154
156
|
return DUCKDB_TYPE_ARRAY;
|
155
157
|
case LogicalTypeId::ANY:
|
156
158
|
return DUCKDB_TYPE_ANY;
|
159
|
+
case LogicalTypeId::SQLNULL:
|
160
|
+
return DUCKDB_TYPE_SQLNULL;
|
157
161
|
default: // LCOV_EXCL_START
|
158
162
|
D_ASSERT(0);
|
159
163
|
return DUCKDB_TYPE_INVALID;
|
@@ -363,16 +363,22 @@ idx_t DBConfig::GetSystemMaxThreads(FileSystem &fs) {
|
|
363
363
|
}
|
364
364
|
|
365
365
|
idx_t DBConfig::GetSystemAvailableMemory(FileSystem &fs) {
|
366
|
+
#ifdef __linux__
|
366
367
|
// Check SLURM environment variables first
|
367
368
|
const char *slurm_mem_per_node = getenv("SLURM_MEM_PER_NODE");
|
368
369
|
const char *slurm_mem_per_cpu = getenv("SLURM_MEM_PER_CPU");
|
369
370
|
|
370
371
|
if (slurm_mem_per_node) {
|
371
|
-
|
372
|
+
auto limit = ParseMemoryLimitSlurm(slurm_mem_per_node);
|
373
|
+
if (limit.IsValid()) {
|
374
|
+
return limit.GetIndex();
|
375
|
+
}
|
372
376
|
} else if (slurm_mem_per_cpu) {
|
373
|
-
|
374
|
-
|
375
|
-
|
377
|
+
auto mem_per_cpu = ParseMemoryLimitSlurm(slurm_mem_per_cpu);
|
378
|
+
if (mem_per_cpu.IsValid()) {
|
379
|
+
idx_t num_threads = GetSystemMaxThreads(fs);
|
380
|
+
return mem_per_cpu.GetIndex() * num_threads;
|
381
|
+
}
|
376
382
|
}
|
377
383
|
|
378
384
|
// Check cgroup memory limit
|
@@ -380,8 +386,9 @@ idx_t DBConfig::GetSystemAvailableMemory(FileSystem &fs) {
|
|
380
386
|
if (cgroup_memory_limit.IsValid()) {
|
381
387
|
return cgroup_memory_limit.GetIndex();
|
382
388
|
}
|
389
|
+
#endif
|
383
390
|
|
384
|
-
//
|
391
|
+
// System memory detection
|
385
392
|
auto memory = FileSystem::GetAvailableMemory();
|
386
393
|
if (!memory.IsValid()) {
|
387
394
|
return DBConfigOptions().maximum_memory;
|
@@ -451,9 +458,9 @@ idx_t DBConfig::ParseMemoryLimit(const string &arg) {
|
|
451
458
|
return LossyNumericCast<idx_t>(static_cast<double>(multiplier) * limit);
|
452
459
|
}
|
453
460
|
|
454
|
-
|
461
|
+
optional_idx DBConfig::ParseMemoryLimitSlurm(const string &arg) {
|
455
462
|
if (arg.empty()) {
|
456
|
-
return
|
463
|
+
return optional_idx();
|
457
464
|
}
|
458
465
|
|
459
466
|
string number_str = arg;
|
@@ -475,13 +482,19 @@ idx_t DBConfig::ParseMemoryLimitSlurm(const string &arg) {
|
|
475
482
|
}
|
476
483
|
|
477
484
|
// Parse the number
|
478
|
-
double limit
|
485
|
+
double limit;
|
486
|
+
if (!TryCast::Operation<string_t, double>(string_t(number_str), limit)) {
|
487
|
+
return optional_idx();
|
488
|
+
}
|
479
489
|
|
480
490
|
if (limit < 0) {
|
481
|
-
return NumericLimits<
|
491
|
+
return static_cast<idx_t>(NumericLimits<int64_t>::Maximum());
|
482
492
|
}
|
483
|
-
|
484
|
-
|
493
|
+
idx_t actual_limit = LossyNumericCast<idx_t>(static_cast<double>(multiplier) * limit);
|
494
|
+
if (actual_limit == NumericLimits<idx_t>::Maximum()) {
|
495
|
+
return static_cast<idx_t>(NumericLimits<int64_t>::Maximum());
|
496
|
+
}
|
497
|
+
return actual_limit;
|
485
498
|
}
|
486
499
|
|
487
500
|
// Right now we only really care about access mode when comparing DBConfigs
|
@@ -2,29 +2,29 @@
|
|
2
2
|
|
3
3
|
#include "duckdb/catalog/catalog.hpp"
|
4
4
|
#include "duckdb/common/virtual_file_system.hpp"
|
5
|
+
#include "duckdb/execution/index/index_type_set.hpp"
|
5
6
|
#include "duckdb/execution/operator/helper/physical_set.hpp"
|
6
7
|
#include "duckdb/function/cast/cast_function_set.hpp"
|
7
8
|
#include "duckdb/function/compression_function.hpp"
|
8
9
|
#include "duckdb/main/attached_database.hpp"
|
9
10
|
#include "duckdb/main/client_context.hpp"
|
10
11
|
#include "duckdb/main/connection_manager.hpp"
|
12
|
+
#include "duckdb/main/database_file_opener.hpp"
|
11
13
|
#include "duckdb/main/database_manager.hpp"
|
12
14
|
#include "duckdb/main/database_path_and_type.hpp"
|
15
|
+
#include "duckdb/main/db_instance_cache.hpp"
|
13
16
|
#include "duckdb/main/error_manager.hpp"
|
14
17
|
#include "duckdb/main/extension_helper.hpp"
|
15
18
|
#include "duckdb/main/secret/secret_manager.hpp"
|
16
19
|
#include "duckdb/parallel/task_scheduler.hpp"
|
17
20
|
#include "duckdb/parser/parsed_data/attach_info.hpp"
|
21
|
+
#include "duckdb/planner/collation_binding.hpp"
|
18
22
|
#include "duckdb/planner/extension_callback.hpp"
|
19
23
|
#include "duckdb/storage/object_cache.hpp"
|
20
24
|
#include "duckdb/storage/standard_buffer_manager.hpp"
|
21
25
|
#include "duckdb/storage/storage_extension.hpp"
|
22
26
|
#include "duckdb/storage/storage_manager.hpp"
|
23
27
|
#include "duckdb/transaction/transaction_manager.hpp"
|
24
|
-
#include "duckdb/execution/index/index_type_set.hpp"
|
25
|
-
#include "duckdb/main/database_file_opener.hpp"
|
26
|
-
#include "duckdb/planner/collation_binding.hpp"
|
27
|
-
#include "duckdb/main/db_instance_cache.hpp"
|
28
28
|
|
29
29
|
#ifndef DUCKDB_NO_THREADS
|
30
30
|
#include "duckdb/common/thread.hpp"
|
@@ -436,7 +436,8 @@ void DatabaseInstance::Configure(DBConfig &new_config, const char *database_path
|
|
436
436
|
config.buffer_pool = std::move(new_config.buffer_pool);
|
437
437
|
} else {
|
438
438
|
config.buffer_pool = make_shared_ptr<BufferPool>(config.options.maximum_memory,
|
439
|
-
config.options.buffer_manager_track_eviction_timestamps
|
439
|
+
config.options.buffer_manager_track_eviction_timestamps,
|
440
|
+
config.options.allocator_bulk_deallocation_flush_threshold);
|
440
441
|
}
|
441
442
|
}
|
442
443
|
|
@@ -268,15 +268,20 @@ static unique_ptr<ExtensionInstallInfo> DirectInstallExtension(DatabaseInstance
|
|
268
268
|
const string &local_extension_path,
|
269
269
|
ExtensionInstallOptions &options,
|
270
270
|
optional_ptr<ClientContext> context) {
|
271
|
-
string
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
if (
|
277
|
-
|
278
|
-
|
271
|
+
string extension;
|
272
|
+
string file;
|
273
|
+
if (fs.IsRemoteFile(path, extension)) {
|
274
|
+
file = path;
|
275
|
+
// Try autoloading httpfs for loading extensions over https
|
276
|
+
if (context) {
|
277
|
+
auto &db = DatabaseInstance::GetDatabase(*context);
|
278
|
+
if (extension == "httpfs" && !db.ExtensionIsLoaded("httpfs") &&
|
279
|
+
db.config.options.autoload_known_extensions) {
|
280
|
+
ExtensionHelper::AutoLoadExtension(*context, "httpfs");
|
281
|
+
}
|
279
282
|
}
|
283
|
+
} else {
|
284
|
+
file = fs.ConvertSeparators(path);
|
280
285
|
}
|
281
286
|
|
282
287
|
// Check if file exists
|
@@ -173,7 +173,7 @@ static string FilterZeroAtEnd(string s) {
|
|
173
173
|
return s;
|
174
174
|
}
|
175
175
|
|
176
|
-
ParsedExtensionMetaData ExtensionHelper::ParseExtensionMetaData(const char *metadata) {
|
176
|
+
ParsedExtensionMetaData ExtensionHelper::ParseExtensionMetaData(const char *metadata) noexcept {
|
177
177
|
ParsedExtensionMetaData result;
|
178
178
|
|
179
179
|
vector<string> metadata_field;
|
@@ -194,12 +194,18 @@ ParsedExtensionMetaData ExtensionHelper::ParseExtensionMetaData(const char *meta
|
|
194
194
|
|
195
195
|
result.extension_version = FilterZeroAtEnd(metadata_field[3]);
|
196
196
|
|
197
|
-
|
197
|
+
auto extension_abi_metadata = FilterZeroAtEnd(metadata_field[4]);
|
198
198
|
|
199
|
-
if (
|
199
|
+
if (extension_abi_metadata == "C_STRUCT") {
|
200
|
+
result.abi_type = ExtensionABIType::C_STRUCT;
|
200
201
|
result.duckdb_capi_version = FilterZeroAtEnd(metadata_field[2]);
|
201
|
-
} else if (
|
202
|
+
} else if (extension_abi_metadata == "CPP" || extension_abi_metadata.empty()) {
|
203
|
+
result.abi_type = ExtensionABIType::CPP;
|
202
204
|
result.duckdb_version = FilterZeroAtEnd(metadata_field[2]);
|
205
|
+
} else {
|
206
|
+
result.abi_type = ExtensionABIType::UNKNOWN;
|
207
|
+
result.duckdb_version = "unknown";
|
208
|
+
result.extension_abi_metadata = extension_abi_metadata;
|
203
209
|
}
|
204
210
|
|
205
211
|
result.signature = string(metadata, ParsedExtensionMetaData::FOOTER_SIZE - ParsedExtensionMetaData::SIGNATURE_SIZE);
|
@@ -62,7 +62,7 @@ string ParsedExtensionMetaData::GetInvalidMetadataError() {
|
|
62
62
|
DUCKDB_EXTENSION_API_VERSION_MINOR, DUCKDB_EXTENSION_API_VERSION_PATCH);
|
63
63
|
}
|
64
64
|
} else {
|
65
|
-
throw InternalException("Unknown ABI type for extension: " +
|
65
|
+
throw InternalException("Unknown ABI type for extension: " + extension_abi_metadata);
|
66
66
|
}
|
67
67
|
|
68
68
|
if (engine_platform != platform) {
|
@@ -93,9 +93,14 @@ unique_ptr<LogicalOperator> FilterPushdown::Rewrite(unique_ptr<LogicalOperator>
|
|
93
93
|
// we can just push directly through these operations without any rewriting
|
94
94
|
op->children[0] = Rewrite(std::move(op->children[0]));
|
95
95
|
return op;
|
96
|
-
case LogicalOperatorType::LOGICAL_MATERIALIZED_CTE:
|
96
|
+
case LogicalOperatorType::LOGICAL_MATERIALIZED_CTE: {
|
97
|
+
// we can't push filters into the materialized CTE (LHS), but we do want to recurse into it
|
98
|
+
FilterPushdown pushdown(optimizer, convert_mark_joins);
|
99
|
+
op->children[0] = pushdown.Rewrite(std::move(op->children[0]));
|
100
|
+
// we can push filters into the rest of the query plan (RHS)
|
97
101
|
op->children[1] = Rewrite(std::move(op->children[1]));
|
98
102
|
return op;
|
103
|
+
}
|
99
104
|
case LogicalOperatorType::LOGICAL_GET:
|
100
105
|
return PushdownGet(std::move(op));
|
101
106
|
case LogicalOperatorType::LOGICAL_LIMIT:
|
@@ -127,6 +132,10 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownJoin(unique_ptr<LogicalOpera
|
|
127
132
|
|
128
133
|
switch (join.join_type) {
|
129
134
|
case JoinType::INNER:
|
135
|
+
// AsOf joins can't push anything into the RHS, so treat it as a left join
|
136
|
+
if (op->type == LogicalOperatorType::LOGICAL_ASOF_JOIN) {
|
137
|
+
return PushdownLeftJoin(std::move(op), left_bindings, right_bindings);
|
138
|
+
}
|
130
139
|
return PushdownInnerJoin(std::move(op), left_bindings, right_bindings);
|
131
140
|
case JoinType::LEFT:
|
132
141
|
return PushdownLeftJoin(std::move(op), left_bindings, right_bindings);
|
@@ -118,11 +118,6 @@ void JoinFilterPushdownOptimizer::GenerateJoinFilters(LogicalComparisonJoin &joi
|
|
118
118
|
}
|
119
119
|
}
|
120
120
|
// pushdown can be performed
|
121
|
-
// set up the dynamic filters (if we don't have any yet)
|
122
|
-
if (!get.dynamic_filters) {
|
123
|
-
get.dynamic_filters = make_shared_ptr<DynamicTableFilterSet>();
|
124
|
-
}
|
125
|
-
pushdown_info->dynamic_filters = get.dynamic_filters;
|
126
121
|
|
127
122
|
// set up the min/max aggregates for each of the filters
|
128
123
|
vector<AggregateFunction> aggr_functions;
|
@@ -135,9 +130,18 @@ void JoinFilterPushdownOptimizer::GenerateJoinFilters(LogicalComparisonJoin &joi
|
|
135
130
|
aggr_children.push_back(join.conditions[filter.join_condition].right->Copy());
|
136
131
|
auto aggr_expr = function_binder.BindAggregateFunction(aggr, std::move(aggr_children), nullptr,
|
137
132
|
AggregateType::NON_DISTINCT);
|
133
|
+
if (aggr_expr->children.size() != 1) {
|
134
|
+
// min/max with collation - not supported
|
135
|
+
return;
|
136
|
+
}
|
138
137
|
pushdown_info->min_max_aggregates.push_back(std::move(aggr_expr));
|
139
138
|
}
|
140
139
|
}
|
140
|
+
// set up the dynamic filters (if we don't have any yet)
|
141
|
+
if (!get.dynamic_filters) {
|
142
|
+
get.dynamic_filters = make_shared_ptr<DynamicTableFilterSet>();
|
143
|
+
}
|
144
|
+
pushdown_info->dynamic_filters = get.dynamic_filters;
|
141
145
|
|
142
146
|
// set up the filter pushdown in the join itself
|
143
147
|
join.filter_pushdown = std::move(pushdown_info);
|
@@ -2,10 +2,10 @@
|
|
2
2
|
#include "duckdb/common/enums/join_type.hpp"
|
3
3
|
#include "duckdb/common/limits.hpp"
|
4
4
|
#include "duckdb/common/printer.hpp"
|
5
|
-
#include "duckdb/planner/expression_iterator.hpp"
|
6
5
|
#include "duckdb/function/table/table_scan.hpp"
|
7
6
|
#include "duckdb/optimizer/join_order/join_node.hpp"
|
8
7
|
#include "duckdb/optimizer/join_order/query_graph_manager.hpp"
|
8
|
+
#include "duckdb/planner/expression_iterator.hpp"
|
9
9
|
#include "duckdb/planner/operator/logical_comparison_join.hpp"
|
10
10
|
#include "duckdb/storage/data_table.hpp"
|
11
11
|
|
@@ -291,10 +291,18 @@ DenomInfo CardinalityEstimator::GetDenominator(JoinRelationSet &set) {
|
|
291
291
|
// and we start to choose the filters that join relations in the set.
|
292
292
|
|
293
293
|
// edges are guaranteed to be in order of largest tdom to smallest tdom.
|
294
|
+
unordered_set<idx_t> unused_edge_tdoms;
|
294
295
|
auto edges = GetEdges(relations_to_tdoms, set);
|
295
296
|
for (auto &edge : edges) {
|
296
|
-
|
297
|
+
if (subgraphs.size() == 1 && subgraphs.at(0).relations->ToString() == set.ToString()) {
|
298
|
+
// the first subgraph has connected all the desired relations, just skip the rest of the edges
|
299
|
+
if (edge.has_tdom_hll) {
|
300
|
+
unused_edge_tdoms.insert(edge.tdom_hll);
|
301
|
+
}
|
302
|
+
continue;
|
303
|
+
}
|
297
304
|
|
305
|
+
auto subgraph_connections = SubgraphsConnectedByEdge(edge, subgraphs);
|
298
306
|
if (subgraph_connections.empty()) {
|
299
307
|
// create a subgraph out of left and right, then merge right into left and add left to subgraphs.
|
300
308
|
// this helps cover a case where there are no subgraphs yet, and the only join filter is a SEMI JOIN
|
@@ -342,13 +350,11 @@ DenomInfo CardinalityEstimator::GetDenominator(JoinRelationSet &set) {
|
|
342
350
|
[](Subgraph2Denominator &s) { return !s.relations; });
|
343
351
|
subgraphs.erase(remove_start, subgraphs.end());
|
344
352
|
}
|
345
|
-
if (subgraphs.size() == 1 && subgraphs.at(0).relations->ToString() == set.ToString()) {
|
346
|
-
// the first subgraph has connected all the desired relations, no need to iterate
|
347
|
-
// through the rest of the edges.
|
348
|
-
break;
|
349
|
-
}
|
350
353
|
}
|
351
354
|
|
355
|
+
// Slight penalty to cardinality for unused edges
|
356
|
+
auto denom_multiplier = 1.0 + static_cast<double>(unused_edge_tdoms.size());
|
357
|
+
|
352
358
|
// It's possible cross-products were added and are not present in the filters in the relation_2_tdom
|
353
359
|
// structures. When that's the case, merge all remaining subgraphs.
|
354
360
|
if (subgraphs.size() > 1) {
|
@@ -367,7 +373,7 @@ DenomInfo CardinalityEstimator::GetDenominator(JoinRelationSet &set) {
|
|
367
373
|
// denominator is 1 and numerators are a cross product of cardinalities.
|
368
374
|
return DenomInfo(set, 1, 1);
|
369
375
|
}
|
370
|
-
return DenomInfo(*subgraphs.at(0).numerator_relations, 1, subgraphs.at(0).denom);
|
376
|
+
return DenomInfo(*subgraphs.at(0).numerator_relations, 1, subgraphs.at(0).denom * denom_multiplier);
|
371
377
|
}
|
372
378
|
|
373
379
|
template <>
|
@@ -253,7 +253,9 @@ GenerateJoinRelation QueryGraphManager::GenerateJoins(vector<unique_ptr<LogicalO
|
|
253
253
|
auto right = GenerateJoins(extracted_relations, node->right_set);
|
254
254
|
if (dp_entry->second->info->filters.empty()) {
|
255
255
|
// no filters, create a cross product
|
256
|
+
auto cardinality = left.op->estimated_cardinality * right.op->estimated_cardinality;
|
256
257
|
result_operator = LogicalCrossProduct::Create(std::move(left.op), std::move(right.op));
|
258
|
+
result_operator->SetEstimatedCardinality(cardinality);
|
257
259
|
} else {
|
258
260
|
// we have filters, create a join node
|
259
261
|
auto chosen_filter = node->info->filters.at(0);
|
@@ -85,6 +85,7 @@ static bool OperatorNeedsRelation(LogicalOperatorType op_type) {
|
|
85
85
|
case LogicalOperatorType::LOGICAL_PROJECTION:
|
86
86
|
case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
|
87
87
|
case LogicalOperatorType::LOGICAL_GET:
|
88
|
+
case LogicalOperatorType::LOGICAL_UNNEST:
|
88
89
|
case LogicalOperatorType::LOGICAL_DELIM_GET:
|
89
90
|
case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
|
90
91
|
case LogicalOperatorType::LOGICAL_WINDOW:
|
@@ -269,6 +270,20 @@ bool RelationManager::ExtractJoinRelations(JoinOrderOptimizer &optimizer, Logica
|
|
269
270
|
AddAggregateOrWindowRelation(input_op, parent, operator_stats, op->type);
|
270
271
|
return true;
|
271
272
|
}
|
273
|
+
case LogicalOperatorType::LOGICAL_UNNEST: {
|
274
|
+
// optimize children of unnest
|
275
|
+
RelationStats child_stats;
|
276
|
+
auto child_optimizer = optimizer.CreateChildOptimizer();
|
277
|
+
op->children[0] = child_optimizer.Optimize(std::move(op->children[0]), &child_stats);
|
278
|
+
// the extracted cardinality should be set for window
|
279
|
+
if (!datasource_filters.empty()) {
|
280
|
+
child_stats.cardinality = LossyNumericCast<idx_t>(static_cast<double>(child_stats.cardinality) *
|
281
|
+
RelationStatisticsHelper::DEFAULT_SELECTIVITY);
|
282
|
+
}
|
283
|
+
ModifyStatsIfLimit(limit_op.get(), child_stats);
|
284
|
+
AddRelation(input_op, parent, child_stats);
|
285
|
+
return true;
|
286
|
+
}
|
272
287
|
case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: {
|
273
288
|
auto &join = op->Cast<LogicalComparisonJoin>();
|
274
289
|
// Adding relations of the left side to the current join order optimizer
|
@@ -95,7 +95,10 @@ void Optimizer::RunBuiltInOptimizers() {
|
|
95
95
|
case LogicalOperatorType::LOGICAL_CREATE_SECRET:
|
96
96
|
case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR:
|
97
97
|
// skip optimizing simple & often-occurring plans unaffected by rewrites
|
98
|
-
|
98
|
+
if (plan->children.empty()) {
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
break;
|
99
102
|
default:
|
100
103
|
break;
|
101
104
|
}
|
@@ -14,9 +14,6 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownCrossProduct(unique_ptr<Logi
|
|
14
14
|
switch (op->type) {
|
15
15
|
case LogicalOperatorType::LOGICAL_CROSS_PRODUCT:
|
16
16
|
break;
|
17
|
-
case LogicalOperatorType::LOGICAL_ASOF_JOIN:
|
18
|
-
join_ref_type = JoinRefType::ASOF;
|
19
|
-
break;
|
20
17
|
default:
|
21
18
|
throw InternalException("Unsupported join type for cross product push down");
|
22
19
|
}
|
@@ -33,14 +30,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownCrossProduct(unique_ptr<Logi
|
|
33
30
|
// bindings match left side: push into left
|
34
31
|
left_pushdown.filters.push_back(std::move(f));
|
35
32
|
} else if (side == JoinSide::RIGHT) {
|
36
|
-
|
37
|
-
if (join_ref_type == JoinRefType::ASOF) {
|
38
|
-
// AsOf is really a table lookup, so we don't push filters
|
39
|
-
// down into the lookup (right) table
|
40
|
-
join_expressions.push_back(std::move(f->filter));
|
41
|
-
} else {
|
42
|
-
right_pushdown.filters.push_back(std::move(f));
|
43
|
-
}
|
33
|
+
right_pushdown.filters.push_back(std::move(f));
|
44
34
|
} else {
|
45
35
|
D_ASSERT(side == JoinSide::BOTH || side == JoinSide::NONE);
|
46
36
|
// bindings match both: turn into join condition
|
@@ -26,8 +26,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownInnerJoin(unique_ptr<Logical
|
|
26
26
|
}
|
27
27
|
} else {
|
28
28
|
// comparison join
|
29
|
-
D_ASSERT(op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN
|
30
|
-
op->type == LogicalOperatorType::LOGICAL_ASOF_JOIN);
|
29
|
+
D_ASSERT(op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN);
|
31
30
|
auto &comp_join = join.Cast<LogicalComparisonJoin>();
|
32
31
|
// turn the conditions into filters
|
33
32
|
for (auto &i : comp_join.conditions) {
|
@@ -40,11 +39,6 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownInnerJoin(unique_ptr<Logical
|
|
40
39
|
}
|
41
40
|
GenerateFilters();
|
42
41
|
|
43
|
-
// For AsOf joins, just use the original op
|
44
|
-
if (op->type == LogicalOperatorType::LOGICAL_ASOF_JOIN) {
|
45
|
-
return PushdownCrossProduct(std::move(op));
|
46
|
-
}
|
47
|
-
|
48
42
|
// turn the inner join into a cross product
|
49
43
|
auto cross_product = make_uniq<LogicalCrossProduct>(std::move(op->children[0]), std::move(op->children[1]));
|
50
44
|
|
@@ -93,7 +93,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownLeftJoin(unique_ptr<LogicalO
|
|
93
93
|
// erase the filter from the list of filters
|
94
94
|
filters.erase_at(i);
|
95
95
|
i--;
|
96
|
-
} else {
|
96
|
+
} else if (op->type != LogicalOperatorType::LOGICAL_ASOF_JOIN) {
|
97
97
|
// bindings match right side or both sides: we cannot directly push it into the right
|
98
98
|
// however, if the filter removes rows with null values from the RHS we can turn the left outer join
|
99
99
|
// in an inner join, and then push down as we would push down an inner join
|
@@ -27,6 +27,9 @@ static unique_ptr<BaseStatistics> StatisticsNumericCastSwitch(const BaseStatisti
|
|
27
27
|
case LogicalTypeId::TIME: {
|
28
28
|
switch (input.GetType().id()) {
|
29
29
|
case LogicalTypeId::TIMESTAMP:
|
30
|
+
case LogicalTypeId::TIMESTAMP_SEC:
|
31
|
+
case LogicalTypeId::TIMESTAMP_MS:
|
32
|
+
case LogicalTypeId::TIMESTAMP_NS:
|
30
33
|
case LogicalTypeId::TIMESTAMP_TZ:
|
31
34
|
return nullptr;
|
32
35
|
default:
|
@@ -104,6 +104,7 @@ void StatisticsPropagator::PropagateStatistics(LogicalComparisonJoin &join, uniq
|
|
104
104
|
// TODO: write better CE logic for limits so that we can just look at
|
105
105
|
// join.children[1].estimated_cardinality.
|
106
106
|
auto limit = make_uniq<LogicalLimit>(BoundLimitNode::ConstantValue(1), BoundLimitNode());
|
107
|
+
limit->SetEstimatedCardinality(1);
|
107
108
|
limit->AddChild(std::move(join.children[1]));
|
108
109
|
auto cross_product = LogicalCrossProduct::Create(std::move(join.children[0]), std::move(limit));
|
109
110
|
node_ptr = std::move(cross_product);
|
@@ -5,6 +5,10 @@
|
|
5
5
|
namespace duckdb {
|
6
6
|
|
7
7
|
bool KeywordHelper::IsKeyword(const string &text) {
|
8
|
+
return Parser::IsKeyword(text) != KeywordCategory::KEYWORD_NONE;
|
9
|
+
}
|
10
|
+
|
11
|
+
KeywordCategory KeywordHelper::KeywordCategoryType(const string &text) {
|
8
12
|
return Parser::IsKeyword(text);
|
9
13
|
}
|
10
14
|
|