duckdb 0.7.2-dev16.0 → 0.7.2-dev314.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 -0
- package/package.json +1 -1
- package/src/duckdb/extension/icu/icu-extension.cpp +2 -0
- package/src/duckdb/extension/icu/icu-table-range.cpp +194 -0
- package/src/duckdb/extension/icu/include/icu-table-range.hpp +17 -0
- package/src/duckdb/extension/parquet/column_reader.cpp +5 -6
- package/src/duckdb/extension/parquet/column_writer.cpp +0 -1
- package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -2
- package/src/duckdb/extension/parquet/include/generated_column_reader.hpp +1 -11
- package/src/duckdb/extension/parquet/parquet-extension.cpp +11 -2
- package/src/duckdb/extension/parquet/parquet_statistics.cpp +26 -32
- package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +4 -0
- package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +7 -6
- package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +20 -1
- package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
- package/src/duckdb/src/common/sort/sort_state.cpp +5 -7
- package/src/duckdb/src/common/types/bit.cpp +95 -58
- package/src/duckdb/src/common/types/value.cpp +149 -53
- package/src/duckdb/src/common/types/vector.cpp +13 -10
- package/src/duckdb/src/execution/column_binding_resolver.cpp +6 -0
- package/src/duckdb/src/execution/operator/aggregate/physical_perfecthash_aggregate.cpp +4 -5
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +1 -1
- package/src/duckdb/src/execution/operator/helper/physical_vacuum.cpp +2 -3
- package/src/duckdb/src/execution/operator/join/physical_blockwise_nl_join.cpp +32 -6
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +15 -15
- package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +18 -12
- package/src/duckdb/src/function/aggregate/algebraic/avg.cpp +0 -6
- package/src/duckdb/src/function/aggregate/distributive/bitagg.cpp +99 -95
- package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +254 -0
- package/src/duckdb/src/function/aggregate/distributive/count.cpp +2 -4
- package/src/duckdb/src/function/aggregate/distributive/sum.cpp +11 -16
- package/src/duckdb/src/function/aggregate/distributive_functions.cpp +1 -0
- package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +16 -5
- package/src/duckdb/src/function/cast/bit_cast.cpp +0 -2
- package/src/duckdb/src/function/cast/blob_cast.cpp +0 -1
- package/src/duckdb/src/function/scalar/bit/bitstring.cpp +99 -0
- package/src/duckdb/src/function/scalar/date/date_diff.cpp +0 -1
- package/src/duckdb/src/function/scalar/date/date_part.cpp +17 -25
- package/src/duckdb/src/function/scalar/date/date_sub.cpp +0 -1
- package/src/duckdb/src/function/scalar/date/date_trunc.cpp +10 -14
- package/src/duckdb/src/function/scalar/generic/stats.cpp +2 -4
- package/src/duckdb/src/function/scalar/list/flatten.cpp +5 -12
- package/src/duckdb/src/function/scalar/list/list_concat.cpp +3 -8
- package/src/duckdb/src/function/scalar/list/list_extract.cpp +5 -12
- package/src/duckdb/src/function/scalar/list/list_value.cpp +5 -9
- package/src/duckdb/src/function/scalar/map/map_entries.cpp +61 -0
- package/src/duckdb/src/function/scalar/map/map_keys_values.cpp +97 -0
- package/src/duckdb/src/function/scalar/math/numeric.cpp +14 -17
- package/src/duckdb/src/function/scalar/nested_functions.cpp +3 -0
- package/src/duckdb/src/function/scalar/operators/add.cpp +0 -9
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +29 -48
- package/src/duckdb/src/function/scalar/operators/bitwise.cpp +0 -63
- package/src/duckdb/src/function/scalar/operators/multiply.cpp +0 -6
- package/src/duckdb/src/function/scalar/operators/subtract.cpp +0 -6
- package/src/duckdb/src/function/scalar/string/caseconvert.cpp +2 -6
- package/src/duckdb/src/function/scalar/string/instr.cpp +2 -6
- package/src/duckdb/src/function/scalar/string/length.cpp +2 -6
- package/src/duckdb/src/function/scalar/string/like.cpp +2 -6
- package/src/duckdb/src/function/scalar/string/substring.cpp +2 -6
- package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
- package/src/duckdb/src/function/scalar/struct/struct_extract.cpp +4 -9
- package/src/duckdb/src/function/scalar/struct/struct_insert.cpp +10 -13
- package/src/duckdb/src/function/scalar/struct/struct_pack.cpp +5 -6
- package/src/duckdb/src/function/table/read_csv.cpp +9 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/function/table_function.cpp +19 -0
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +6 -8
- package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -19
- package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/enums/tableref_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/types/bit.hpp +5 -1
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -8
- package/src/duckdb/src/include/duckdb/common/types.hpp +1 -2
- package/src/duckdb/src/include/duckdb/execution/operator/aggregate/physical_perfecthash_aggregate.hpp +1 -1
- package/src/duckdb/src/include/duckdb/function/aggregate/distributive_functions.hpp +5 -0
- package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +12 -3
- package/src/duckdb/src/include/duckdb/function/scalar/bit_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +12 -0
- package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +2 -2
- package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/parsed_data/{alter_function_info.hpp → alter_scalar_function_info.hpp} +13 -13
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +47 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_function_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/statement/multi_statement.hpp +28 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/list.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +76 -0
- package/src/duckdb/src/include/duckdb/parser/tokens.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +28 -0
- package/src/duckdb/src/include/duckdb/planner/bind_context.hpp +2 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -0
- package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +76 -44
- package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +3 -2
- package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_compress.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_fetch.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_scan.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_compress.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_fetch.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_scan.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +5 -2
- package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/statistics/base_statistics.hpp +93 -29
- package/src/duckdb/src/include/duckdb/storage/statistics/column_statistics.hpp +22 -3
- package/src/duckdb/src/include/duckdb/storage/statistics/distinct_statistics.hpp +6 -6
- package/src/duckdb/src/include/duckdb/storage/statistics/list_stats.hpp +41 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/node_statistics.hpp +26 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats.hpp +157 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/segment_statistics.hpp +2 -7
- package/src/duckdb/src/include/duckdb/storage/statistics/string_stats.hpp +74 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/struct_stats.hpp +42 -0
- package/src/duckdb/src/include/duckdb/storage/string_uncompressed.hpp +2 -3
- package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +2 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +4 -3
- package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +3 -2
- package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/table/table_statistics.hpp +5 -0
- package/src/duckdb/src/include/duckdb.h +49 -1
- package/src/duckdb/src/include/duckdb.hpp +0 -1
- package/src/duckdb/src/main/capi/pending-c.cpp +16 -3
- package/src/duckdb/src/main/capi/result-c.cpp +27 -1
- package/src/duckdb/src/main/capi/stream-c.cpp +25 -0
- package/src/duckdb/src/main/client_context.cpp +8 -1
- package/src/duckdb/src/main/config.cpp +66 -1
- package/src/duckdb/src/main/database.cpp +10 -2
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +98 -67
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +16 -3
- package/src/duckdb/src/optimizer/statistics/expression/propagate_aggregate.cpp +9 -3
- package/src/duckdb/src/optimizer/statistics/expression/propagate_and_compress.cpp +6 -7
- package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +14 -11
- package/src/duckdb/src/optimizer/statistics/expression/propagate_columnref.cpp +1 -1
- package/src/duckdb/src/optimizer/statistics/expression/propagate_comparison.cpp +13 -15
- package/src/duckdb/src/optimizer/statistics/expression/propagate_conjunction.cpp +0 -1
- package/src/duckdb/src/optimizer/statistics/expression/propagate_constant.cpp +3 -75
- package/src/duckdb/src/optimizer/statistics/expression/propagate_function.cpp +7 -2
- package/src/duckdb/src/optimizer/statistics/expression/propagate_operator.cpp +10 -0
- package/src/duckdb/src/optimizer/statistics/operator/propagate_aggregate.cpp +2 -3
- package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +28 -31
- package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +4 -5
- package/src/duckdb/src/optimizer/statistics/operator/propagate_set_operation.cpp +3 -3
- package/src/duckdb/src/optimizer/statistics_propagator.cpp +1 -1
- package/src/duckdb/src/parser/parsed_data/alter_info.cpp +7 -3
- package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +56 -0
- package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +51 -0
- package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +3 -2
- package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +6 -0
- package/src/duckdb/src/parser/parsed_expression_iterator.cpp +8 -0
- package/src/duckdb/src/parser/query_node.cpp +1 -1
- package/src/duckdb/src/parser/statement/multi_statement.cpp +18 -0
- package/src/duckdb/src/parser/tableref/pivotref.cpp +296 -0
- package/src/duckdb/src/parser/tableref.cpp +3 -0
- package/src/duckdb/src/parser/transform/helpers/transform_alias.cpp +12 -6
- package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +24 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +150 -0
- package/src/duckdb/src/parser/transform/statement/transform_select.cpp +8 -0
- package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -1
- package/src/duckdb/src/parser/transform/tableref/transform_join.cpp +4 -0
- package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +105 -0
- package/src/duckdb/src/parser/transform/tableref/transform_tableref.cpp +2 -0
- package/src/duckdb/src/parser/transformer.cpp +15 -3
- package/src/duckdb/src/planner/bind_context.cpp +16 -0
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +11 -3
- package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +0 -1
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +1 -1
- package/src/duckdb/src/planner/binder/statement/bind_logical_plan.cpp +17 -0
- package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +9 -0
- package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +365 -0
- package/src/duckdb/src/planner/binder.cpp +7 -1
- package/src/duckdb/src/planner/bound_result_modifier.cpp +1 -1
- package/src/duckdb/src/planner/expression/bound_window_expression.cpp +1 -1
- package/src/duckdb/src/planner/filter/constant_filter.cpp +4 -6
- package/src/duckdb/src/planner/pragma_handler.cpp +10 -2
- package/src/duckdb/src/storage/buffer_manager.cpp +44 -46
- package/src/duckdb/src/storage/checkpoint/row_group_writer.cpp +1 -1
- package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +1 -4
- package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +4 -4
- package/src/duckdb/src/storage/compression/bitpacking.cpp +28 -24
- package/src/duckdb/src/storage/compression/fixed_size_uncompressed.cpp +43 -45
- package/src/duckdb/src/storage/compression/numeric_constant.cpp +9 -10
- package/src/duckdb/src/storage/compression/patas.cpp +1 -1
- package/src/duckdb/src/storage/compression/rle.cpp +19 -15
- package/src/duckdb/src/storage/compression/validity_uncompressed.cpp +5 -5
- package/src/duckdb/src/storage/data_table.cpp +4 -6
- package/src/duckdb/src/storage/statistics/base_statistics.cpp +373 -128
- package/src/duckdb/src/storage/statistics/column_statistics.cpp +58 -3
- package/src/duckdb/src/storage/statistics/distinct_statistics.cpp +4 -9
- package/src/duckdb/src/storage/statistics/list_stats.cpp +117 -0
- package/src/duckdb/src/storage/statistics/numeric_stats.cpp +529 -0
- package/src/duckdb/src/storage/statistics/segment_statistics.cpp +2 -11
- package/src/duckdb/src/storage/statistics/string_stats.cpp +273 -0
- package/src/duckdb/src/storage/statistics/struct_stats.cpp +131 -0
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +3 -4
- package/src/duckdb/src/storage/table/column_data.cpp +16 -11
- package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +2 -3
- package/src/duckdb/src/storage/table/column_segment.cpp +6 -8
- package/src/duckdb/src/storage/table/list_column_data.cpp +39 -58
- package/src/duckdb/src/storage/table/row_group.cpp +24 -23
- package/src/duckdb/src/storage/table/row_group_collection.cpp +12 -12
- package/src/duckdb/src/storage/table/standard_column_data.cpp +6 -6
- package/src/duckdb/src/storage/table/struct_column_data.cpp +15 -16
- package/src/duckdb/src/storage/table/table_statistics.cpp +27 -7
- package/src/duckdb/src/storage/table/update_segment.cpp +10 -12
- package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +3 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +34 -1
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +1020 -530
- package/src/duckdb/third_party/libpg_query/include/parser/kwlist.hpp +7 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +23560 -22737
- package/src/duckdb/ub_src_function_aggregate_distributive.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_bit.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_map.cpp +4 -0
- package/src/duckdb/ub_src_main_capi.cpp +2 -0
- package/src/duckdb/ub_src_parser_parsed_data.cpp +4 -2
- package/src/duckdb/ub_src_parser_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_tableref.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_tableref.cpp +2 -0
- package/src/duckdb/ub_src_planner_binder_tableref.cpp +2 -0
- package/src/duckdb/ub_src_storage_statistics.cpp +4 -6
- package/src/duckdb/src/include/duckdb/main/loadable_extension.hpp +0 -59
- package/src/duckdb/src/include/duckdb/storage/statistics/list_statistics.hpp +0 -36
- package/src/duckdb/src/include/duckdb/storage/statistics/numeric_statistics.hpp +0 -75
- package/src/duckdb/src/include/duckdb/storage/statistics/string_statistics.hpp +0 -49
- package/src/duckdb/src/include/duckdb/storage/statistics/struct_statistics.hpp +0 -36
- package/src/duckdb/src/include/duckdb/storage/statistics/validity_statistics.hpp +0 -45
- package/src/duckdb/src/parser/parsed_data/alter_function_info.cpp +0 -55
- package/src/duckdb/src/storage/statistics/list_statistics.cpp +0 -94
- package/src/duckdb/src/storage/statistics/numeric_statistics.cpp +0 -307
- package/src/duckdb/src/storage/statistics/string_statistics.cpp +0 -220
- package/src/duckdb/src/storage/statistics/struct_statistics.cpp +0 -108
- package/src/duckdb/src/storage/statistics/validity_statistics.cpp +0 -91
@@ -813,12 +813,14 @@ unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_str
|
|
813
813
|
|
814
814
|
unique_ptr<QueryResult> result;
|
815
815
|
QueryResult *last_result = nullptr;
|
816
|
+
bool last_had_result = false;
|
816
817
|
for (idx_t i = 0; i < statements.size(); i++) {
|
817
818
|
auto &statement = statements[i];
|
818
819
|
bool is_last_statement = i + 1 == statements.size();
|
819
820
|
PendingQueryParameters parameters;
|
820
821
|
parameters.allow_stream_result = allow_stream_result && is_last_statement;
|
821
822
|
auto pending_query = PendingQueryInternal(*lock, std::move(statement), parameters);
|
823
|
+
auto has_result = pending_query->properties.return_type == StatementReturnType::QUERY_RESULT;
|
822
824
|
unique_ptr<QueryResult> current_result;
|
823
825
|
if (pending_query->HasError()) {
|
824
826
|
current_result = make_unique<MaterializedQueryResult>(pending_query->GetErrorObject());
|
@@ -826,12 +828,17 @@ unique_ptr<QueryResult> ClientContext::Query(const string &query, bool allow_str
|
|
826
828
|
current_result = ExecutePendingQueryInternal(*lock, *pending_query);
|
827
829
|
}
|
828
830
|
// now append the result to the list of results
|
829
|
-
if (!last_result) {
|
831
|
+
if (!last_result || !last_had_result) {
|
830
832
|
// first result of the query
|
831
833
|
result = std::move(current_result);
|
832
834
|
last_result = result.get();
|
835
|
+
last_had_result = has_result;
|
833
836
|
} else {
|
834
837
|
// later results; attach to the result chain
|
838
|
+
// but only if there is a result
|
839
|
+
if (!has_result) {
|
840
|
+
continue;
|
841
|
+
}
|
835
842
|
last_result->next = std::move(current_result);
|
836
843
|
last_result = last_result->next.get();
|
837
844
|
}
|
@@ -9,6 +9,9 @@
|
|
9
9
|
#include "duckdb/common/thread.hpp"
|
10
10
|
#endif
|
11
11
|
|
12
|
+
#include <cstdio>
|
13
|
+
#include <inttypes.h>
|
14
|
+
|
12
15
|
namespace duckdb {
|
13
16
|
|
14
17
|
#define DUCKDB_GLOBAL(_PARAM) \
|
@@ -214,9 +217,71 @@ void DBConfig::SetDefaultMaxMemory() {
|
|
214
217
|
}
|
215
218
|
}
|
216
219
|
|
220
|
+
idx_t CGroupBandwidthQuota(idx_t physical_cores, FileSystem &fs) {
|
221
|
+
static constexpr const char *CPU_MAX = "/sys/fs/cgroup/cpu.max";
|
222
|
+
static constexpr const char *CFS_QUOTA = "/sys/fs/cgroup/cpu/cpu.cfs_quota_us";
|
223
|
+
static constexpr const char *CFS_PERIOD = "/sys/fs/cgroup/cpu/cpu.cfs_period_us";
|
224
|
+
|
225
|
+
int64_t quota, period;
|
226
|
+
char byte_buffer[1000];
|
227
|
+
unique_ptr<FileHandle> handle;
|
228
|
+
int64_t read_bytes;
|
229
|
+
|
230
|
+
if (fs.FileExists(CPU_MAX)) {
|
231
|
+
// cgroup v2
|
232
|
+
// https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
233
|
+
handle =
|
234
|
+
fs.OpenFile(CPU_MAX, FileFlags::FILE_FLAGS_READ, FileSystem::DEFAULT_LOCK, FileSystem::DEFAULT_COMPRESSION);
|
235
|
+
read_bytes = fs.Read(*handle, (void *)byte_buffer, 999);
|
236
|
+
byte_buffer[read_bytes] = '\0';
|
237
|
+
if (std::sscanf(byte_buffer, "%" SCNd64 " %" SCNd64 "", "a, &period) != 2) {
|
238
|
+
return physical_cores;
|
239
|
+
}
|
240
|
+
} else if (fs.FileExists(CFS_QUOTA) && fs.FileExists(CFS_PERIOD)) {
|
241
|
+
// cgroup v1
|
242
|
+
// https://www.kernel.org/doc/html/latest/scheduler/sched-bwc.html#management
|
243
|
+
|
244
|
+
// Read the quota, this indicates how many microseconds the CPU can be utilized by this cgroup per period
|
245
|
+
handle = fs.OpenFile(CFS_QUOTA, FileFlags::FILE_FLAGS_READ, FileSystem::DEFAULT_LOCK,
|
246
|
+
FileSystem::DEFAULT_COMPRESSION);
|
247
|
+
read_bytes = fs.Read(*handle, (void *)byte_buffer, 999);
|
248
|
+
byte_buffer[read_bytes] = '\0';
|
249
|
+
if (std::sscanf(byte_buffer, "%" SCNd64 "", "a) != 1) {
|
250
|
+
return physical_cores;
|
251
|
+
}
|
252
|
+
|
253
|
+
// Read the time period, a cgroup can utilize the CPU up to quota microseconds every period
|
254
|
+
handle = fs.OpenFile(CFS_PERIOD, FileFlags::FILE_FLAGS_READ, FileSystem::DEFAULT_LOCK,
|
255
|
+
FileSystem::DEFAULT_COMPRESSION);
|
256
|
+
read_bytes = fs.Read(*handle, (void *)byte_buffer, 999);
|
257
|
+
byte_buffer[read_bytes] = '\0';
|
258
|
+
if (std::sscanf(byte_buffer, "%" SCNd64 "", &period) != 1) {
|
259
|
+
return physical_cores;
|
260
|
+
}
|
261
|
+
} else {
|
262
|
+
// No cgroup quota
|
263
|
+
return physical_cores;
|
264
|
+
}
|
265
|
+
if (quota > 0 && period > 0) {
|
266
|
+
return idx_t(std::ceil((double)quota / (double)period));
|
267
|
+
} else {
|
268
|
+
return physical_cores;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
idx_t GetSystemMaxThreadsInternal(FileSystem &fs) {
|
273
|
+
idx_t physical_cores = std::thread::hardware_concurrency();
|
274
|
+
#ifdef __linux__
|
275
|
+
auto cores_available_per_period = CGroupBandwidthQuota(physical_cores, fs);
|
276
|
+
return MaxValue<idx_t>(cores_available_per_period, 1);
|
277
|
+
#else
|
278
|
+
return physical_cores;
|
279
|
+
#endif
|
280
|
+
}
|
281
|
+
|
217
282
|
void DBConfig::SetDefaultMaxThreads() {
|
218
283
|
#ifndef DUCKDB_NO_THREADS
|
219
|
-
options.maximum_threads =
|
284
|
+
options.maximum_threads = GetSystemMaxThreadsInternal(*file_system);
|
220
285
|
#else
|
221
286
|
options.maximum_threads = 1;
|
222
287
|
#endif
|
@@ -191,8 +191,7 @@ void DatabaseInstance::Initialize(const char *database_path, DBConfig *user_conf
|
|
191
191
|
}
|
192
192
|
|
193
193
|
db_manager = make_unique<DatabaseManager>(*this);
|
194
|
-
buffer_manager =
|
195
|
-
make_unique<BufferManager>(*this, config.options.temporary_directory, config.options.maximum_memory);
|
194
|
+
buffer_manager = make_unique<BufferManager>(*this, config.options.temporary_directory);
|
196
195
|
scheduler = make_unique<TaskScheduler>(*this);
|
197
196
|
object_cache = make_unique<ObjectCache>();
|
198
197
|
connection_manager = make_unique<ConnectionManager>();
|
@@ -271,6 +270,10 @@ BufferManager &DatabaseInstance::GetBufferManager() {
|
|
271
270
|
return *buffer_manager;
|
272
271
|
}
|
273
272
|
|
273
|
+
BufferPool &DatabaseInstance::GetBufferPool() {
|
274
|
+
return *config.buffer_pool;
|
275
|
+
}
|
276
|
+
|
274
277
|
DatabaseManager &DatabaseManager::Get(DatabaseInstance &db) {
|
275
278
|
return db.GetDatabaseManager();
|
276
279
|
}
|
@@ -340,6 +343,11 @@ void DatabaseInstance::Configure(DBConfig &new_config) {
|
|
340
343
|
if (!config.default_allocator) {
|
341
344
|
config.default_allocator = Allocator::DefaultAllocatorReference();
|
342
345
|
}
|
346
|
+
if (new_config.buffer_pool) {
|
347
|
+
config.buffer_pool = std::move(new_config.buffer_pool);
|
348
|
+
} else {
|
349
|
+
config.buffer_pool = make_shared<BufferPool>(config.options.maximum_memory);
|
350
|
+
}
|
343
351
|
}
|
344
352
|
|
345
353
|
DBConfig &DBConfig::GetConfig(ClientContext &context) {
|
@@ -6,24 +6,18 @@
|
|
6
6
|
#include "duckdb/planner/operator/logical_comparison_join.hpp"
|
7
7
|
#include "duckdb/planner/operator/logical_get.hpp"
|
8
8
|
#include "duckdb/storage/data_table.hpp"
|
9
|
-
#include "duckdb/storage/statistics/numeric_statistics.hpp"
|
10
9
|
#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
|
11
10
|
|
12
11
|
namespace duckdb {
|
13
12
|
|
14
13
|
static TableCatalogEntry *GetCatalogTableEntry(LogicalOperator *op) {
|
15
|
-
if (op
|
16
|
-
|
17
|
-
TableCatalogEntry *entry = get->GetTable();
|
18
|
-
return entry;
|
14
|
+
if (!op) {
|
15
|
+
return nullptr;
|
19
16
|
}
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
25
|
-
}
|
26
|
-
return nullptr;
|
17
|
+
D_ASSERT(op->type == LogicalOperatorType::LOGICAL_GET);
|
18
|
+
auto get = (LogicalGet *)op;
|
19
|
+
TableCatalogEntry *entry = get->GetTable();
|
20
|
+
return entry;
|
27
21
|
}
|
28
22
|
|
29
23
|
// The filter was made on top of a logical sample or other projection,
|
@@ -304,23 +298,36 @@ static bool IsLogicalFilter(LogicalOperator *op) {
|
|
304
298
|
return op->type == LogicalOperatorType::LOGICAL_FILTER;
|
305
299
|
}
|
306
300
|
|
307
|
-
static LogicalGet *GetLogicalGet(LogicalOperator *op) {
|
301
|
+
static LogicalGet *GetLogicalGet(LogicalOperator *op, idx_t table_index = DConstants::INVALID_INDEX) {
|
308
302
|
LogicalGet *get = nullptr;
|
309
303
|
switch (op->type) {
|
310
304
|
case LogicalOperatorType::LOGICAL_GET:
|
311
305
|
get = (LogicalGet *)op;
|
312
306
|
break;
|
313
307
|
case LogicalOperatorType::LOGICAL_FILTER:
|
314
|
-
get = GetLogicalGet(op->children.at(0).get());
|
308
|
+
get = GetLogicalGet(op->children.at(0).get(), table_index);
|
315
309
|
break;
|
316
310
|
case LogicalOperatorType::LOGICAL_PROJECTION:
|
317
|
-
get = GetLogicalGet(op->children.at(0).get());
|
311
|
+
get = GetLogicalGet(op->children.at(0).get(), table_index);
|
318
312
|
break;
|
319
313
|
case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: {
|
320
314
|
LogicalComparisonJoin *join = (LogicalComparisonJoin *)op;
|
315
|
+
// We should never be calling GetLogicalGet without a valid table_index.
|
316
|
+
// We are attempting to get the catalog table for a relation (for statistics/cardinality estimation)
|
317
|
+
// A logical join means there is a non-reorderable relation in the join plan. This means we need
|
318
|
+
// to know the exact table index to return.
|
319
|
+
D_ASSERT(table_index != DConstants::INVALID_INDEX);
|
321
320
|
if (join->join_type == JoinType::MARK || join->join_type == JoinType::LEFT) {
|
322
321
|
auto child = join->children.at(0).get();
|
323
|
-
get = GetLogicalGet(child);
|
322
|
+
get = GetLogicalGet(child, table_index);
|
323
|
+
if (get && get->table_index == table_index) {
|
324
|
+
return get;
|
325
|
+
}
|
326
|
+
child = join->children.at(1).get();
|
327
|
+
get = GetLogicalGet(child, table_index);
|
328
|
+
if (get && get->table_index == table_index) {
|
329
|
+
return get;
|
330
|
+
}
|
324
331
|
}
|
325
332
|
break;
|
326
333
|
}
|
@@ -370,16 +377,17 @@ void CardinalityEstimator::InitCardinalityEstimatorProps(vector<NodeOp> *node_op
|
|
370
377
|
if (op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) {
|
371
378
|
auto &join = (LogicalComparisonJoin &)*op;
|
372
379
|
if (join.join_type == JoinType::LEFT) {
|
373
|
-
//
|
374
|
-
//
|
375
|
-
//
|
376
|
-
//
|
377
|
-
//
|
380
|
+
// If a base op is a Logical Comparison join it is probably a left join,
|
381
|
+
// so the cost of the larger table is a fine estimate.
|
382
|
+
// TODO: provide better estimates for cost of mark joins
|
383
|
+
// MARK joins are used for anti and semi joins, so the cost can conceivably be
|
384
|
+
// less than the base table cardinality.
|
378
385
|
join_node->SetCost(join_node->GetBaseTableCardinality());
|
379
386
|
}
|
380
387
|
}
|
381
|
-
// update cardinality
|
388
|
+
// Total domains can be affected by filters. So we update base table cardinality first
|
382
389
|
EstimateBaseTableCardinality(join_node, op);
|
390
|
+
// Then update total domains.
|
383
391
|
UpdateTotalDomains(join_node, op);
|
384
392
|
}
|
385
393
|
|
@@ -390,74 +398,84 @@ void CardinalityEstimator::InitCardinalityEstimatorProps(vector<NodeOp> *node_op
|
|
390
398
|
void CardinalityEstimator::UpdateTotalDomains(JoinNode *node, LogicalOperator *op) {
|
391
399
|
auto relation_id = node->set->relations[0];
|
392
400
|
relation_attributes[relation_id].cardinality = node->GetCardinality<double>();
|
401
|
+
//! Initialize the distinct count for all columns used in joins with the current relation.
|
402
|
+
idx_t distinct_count = node->GetBaseTableCardinality();
|
393
403
|
TableCatalogEntry *catalog_table = nullptr;
|
394
|
-
auto get = GetLogicalGet(op);
|
395
|
-
if (get) {
|
396
|
-
catalog_table = GetCatalogTableEntry(get);
|
397
|
-
}
|
398
|
-
|
399
|
-
//! Initialize the tdoms for all columns the relation uses in join conditions.
|
400
|
-
unordered_set<idx_t>::iterator ite;
|
401
|
-
idx_t count = node->GetBaseTableCardinality();
|
402
404
|
|
403
405
|
bool direct_filter = false;
|
406
|
+
LogicalGet *get = nullptr;
|
407
|
+
bool get_updated = true;
|
404
408
|
for (auto &column : relation_attributes[relation_id].columns) {
|
405
|
-
//! for every column in the relation, get the count via
|
409
|
+
//! for every column used in a filter in the relation, get the distinct count via HLL, or assume it to be
|
406
410
|
//! the cardinality
|
407
411
|
ColumnBinding key = ColumnBinding(relation_id, column);
|
412
|
+
auto actual_binding = relation_column_to_original_column.find(key);
|
413
|
+
// each relation has columns that are either projected or used as filters
|
414
|
+
// In order to get column statistics we need to make sure the actual binding still
|
415
|
+
// refers to the same base table relation, as non-reorderable joins may involve 2+
|
416
|
+
// base table relations and therefore the columns may also refer to 2 different
|
417
|
+
// base table relations
|
418
|
+
if (actual_binding != relation_column_to_original_column.end() &&
|
419
|
+
(!get || get->table_index != actual_binding->second.table_index)) {
|
420
|
+
get = GetLogicalGet(op, actual_binding->second.table_index);
|
421
|
+
get_updated = true;
|
422
|
+
} else {
|
423
|
+
get_updated = false;
|
424
|
+
}
|
408
425
|
|
409
|
-
if (
|
410
|
-
|
411
|
-
|
412
|
-
auto actual_binding = relation_column_to_original_column[key];
|
426
|
+
if (get_updated) {
|
427
|
+
catalog_table = GetCatalogTableEntry(get);
|
428
|
+
}
|
413
429
|
|
414
|
-
|
430
|
+
if (catalog_table && actual_binding != relation_column_to_original_column.end()) {
|
431
|
+
// Get HLL stats here
|
432
|
+
auto base_stats = catalog_table->GetStatistics(context, actual_binding->second.column_index);
|
415
433
|
if (base_stats) {
|
416
|
-
|
434
|
+
distinct_count = base_stats->GetDistinctCount();
|
417
435
|
}
|
418
436
|
|
419
|
-
// means you have a direct filter on a column. The
|
437
|
+
// means you have a direct filter on a column. The distinct_count/total domain for the column
|
420
438
|
// should be decreased to match the predicted total domain matching the filter.
|
421
439
|
// We decrease the total domain for all columns in the equivalence set because filter pushdown
|
422
440
|
// will mean all columns are affected.
|
423
441
|
if (direct_filter) {
|
424
|
-
|
442
|
+
distinct_count = node->GetCardinality<idx_t>();
|
425
443
|
}
|
426
444
|
|
427
|
-
// HLL has estimation error,
|
428
|
-
if (
|
429
|
-
|
445
|
+
// HLL has estimation error, distinct_count can't be greater than cardinality of the table before filters
|
446
|
+
if (distinct_count > node->GetBaseTableCardinality()) {
|
447
|
+
distinct_count = node->GetBaseTableCardinality();
|
430
448
|
}
|
431
449
|
} else {
|
432
|
-
// No HLL. So if we know there is a direct filter, reduce count to cardinality
|
433
|
-
//
|
450
|
+
// No HLL. So if we know there is a direct filter, reduce the distinct count to the cardinality
|
451
|
+
// with filter effects. Otherwise assume the distinct count is still the cardinality
|
434
452
|
if (direct_filter) {
|
435
|
-
|
453
|
+
distinct_count = node->GetCardinality<idx_t>();
|
436
454
|
} else {
|
437
|
-
|
455
|
+
distinct_count = node->GetBaseTableCardinality();
|
438
456
|
}
|
439
457
|
}
|
440
|
-
|
458
|
+
// Update the relation_to_tdom set with the estimated distinct count (or tdom) calculated above
|
441
459
|
for (auto &relation_to_tdom : relations_to_tdoms) {
|
442
460
|
column_binding_set_t i_set = relation_to_tdom.equivalent_relations;
|
443
461
|
if (i_set.count(key) != 1) {
|
444
462
|
continue;
|
445
463
|
}
|
446
464
|
if (catalog_table) {
|
447
|
-
if (relation_to_tdom.tdom_hll <
|
448
|
-
relation_to_tdom.tdom_hll =
|
465
|
+
if (relation_to_tdom.tdom_hll < distinct_count) {
|
466
|
+
relation_to_tdom.tdom_hll = distinct_count;
|
449
467
|
relation_to_tdom.has_tdom_hll = true;
|
450
468
|
}
|
451
|
-
if (relation_to_tdom.tdom_no_hll >
|
452
|
-
relation_to_tdom.tdom_no_hll =
|
469
|
+
if (relation_to_tdom.tdom_no_hll > distinct_count) {
|
470
|
+
relation_to_tdom.tdom_no_hll = distinct_count;
|
453
471
|
}
|
454
472
|
} else {
|
455
473
|
// Here we don't have catalog statistics, and the following is how we determine
|
456
474
|
// the tdom
|
457
475
|
// 1. If there is any hll data in the equivalence set, use that
|
458
476
|
// 2. Otherwise, use the table with the smallest cardinality
|
459
|
-
if (relation_to_tdom.tdom_no_hll >
|
460
|
-
relation_to_tdom.tdom_no_hll =
|
477
|
+
if (relation_to_tdom.tdom_no_hll > distinct_count && !relation_to_tdom.has_tdom_hll) {
|
478
|
+
relation_to_tdom.tdom_no_hll = distinct_count;
|
461
479
|
}
|
462
480
|
}
|
463
481
|
break;
|
@@ -465,9 +483,8 @@ void CardinalityEstimator::UpdateTotalDomains(JoinNode *node, LogicalOperator *o
|
|
465
483
|
}
|
466
484
|
}
|
467
485
|
|
468
|
-
TableFilterSet *CardinalityEstimator::GetTableFilters(LogicalOperator *op) {
|
469
|
-
|
470
|
-
auto get = GetLogicalGet(op);
|
486
|
+
TableFilterSet *CardinalityEstimator::GetTableFilters(LogicalOperator *op, idx_t table_index) {
|
487
|
+
auto get = GetLogicalGet(op, table_index);
|
471
488
|
return get ? &get->table_filters : nullptr;
|
472
489
|
}
|
473
490
|
|
@@ -529,9 +546,10 @@ idx_t CardinalityEstimator::InspectConjunctionOR(idx_t cardinality, idx_t column
|
|
529
546
|
return cardinality_after_filters;
|
530
547
|
}
|
531
548
|
|
532
|
-
idx_t CardinalityEstimator::InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters
|
549
|
+
idx_t CardinalityEstimator::InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters,
|
550
|
+
idx_t table_index) {
|
533
551
|
idx_t cardinality_after_filters = cardinality;
|
534
|
-
auto get = GetLogicalGet(op);
|
552
|
+
auto get = GetLogicalGet(op, table_index);
|
535
553
|
unique_ptr<BaseStatistics> column_statistics;
|
536
554
|
for (auto &it : table_filters->filters) {
|
537
555
|
column_statistics = nullptr;
|
@@ -562,17 +580,30 @@ idx_t CardinalityEstimator::InspectTableFilters(idx_t cardinality, LogicalOperat
|
|
562
580
|
|
563
581
|
void CardinalityEstimator::EstimateBaseTableCardinality(JoinNode *node, LogicalOperator *op) {
|
564
582
|
auto has_logical_filter = IsLogicalFilter(op);
|
565
|
-
|
583
|
+
D_ASSERT(node->set->count == 1);
|
584
|
+
auto relation_id = node->set->relations[0];
|
566
585
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
586
|
+
double lowest_card_found = NumericLimits<double>::Maximum();
|
587
|
+
for (auto &column : relation_attributes[relation_id].columns) {
|
588
|
+
auto card_after_filters = node->GetBaseTableCardinality();
|
589
|
+
ColumnBinding key = ColumnBinding(relation_id, column);
|
590
|
+
TableFilterSet *table_filters = nullptr;
|
591
|
+
auto actual_binding = relation_column_to_original_column.find(key);
|
592
|
+
if (actual_binding != relation_column_to_original_column.end()) {
|
593
|
+
table_filters = GetTableFilters(op, actual_binding->second.table_index);
|
594
|
+
}
|
595
|
+
|
596
|
+
if (table_filters) {
|
597
|
+
double inspect_result =
|
598
|
+
(double)InspectTableFilters(card_after_filters, op, table_filters, actual_binding->second.table_index);
|
599
|
+
card_after_filters = MinValue(inspect_result, (double)card_after_filters);
|
600
|
+
}
|
601
|
+
if (has_logical_filter) {
|
602
|
+
card_after_filters *= DEFAULT_SELECTIVITY;
|
603
|
+
}
|
604
|
+
lowest_card_found = MinValue(card_after_filters, lowest_card_found);
|
574
605
|
}
|
575
|
-
node->SetEstimatedCardinality(
|
606
|
+
node->SetEstimatedCardinality(lowest_card_found);
|
576
607
|
}
|
577
608
|
|
578
609
|
} // namespace duckdb
|
@@ -152,7 +152,7 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
|
|
152
152
|
// new NULL values in the right side, so pushing this condition through the join leads to incorrect results
|
153
153
|
// for this reason, we just start a new JoinOptimizer pass in each of the children of the join
|
154
154
|
|
155
|
-
// Keep track of all
|
155
|
+
// Keep track of all filter bindings the new join order optimizer makes
|
156
156
|
vector<column_binding_map_t<ColumnBinding>> child_binding_maps;
|
157
157
|
idx_t child_bindings_it = 0;
|
158
158
|
for (auto &child : op->children) {
|
@@ -222,12 +222,25 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
|
|
222
222
|
}
|
223
223
|
case LogicalOperatorType::LOGICAL_PROJECTION: {
|
224
224
|
auto proj = (LogicalProjection *)op;
|
225
|
-
// we run the join order optimizer
|
225
|
+
// we run the join order optimizer within the subquery as well
|
226
226
|
JoinOrderOptimizer optimizer(context);
|
227
227
|
op->children[0] = optimizer.Optimize(std::move(op->children[0]));
|
228
228
|
// projection, add to the set of relations
|
229
229
|
auto relation = make_unique<SingleJoinRelation>(&input_op, parent);
|
230
|
-
|
230
|
+
auto relation_id = relations.size();
|
231
|
+
// push one child column binding map back.
|
232
|
+
vector<column_binding_map_t<ColumnBinding>> child_binding_maps;
|
233
|
+
child_binding_maps.emplace_back(column_binding_map_t<ColumnBinding>());
|
234
|
+
optimizer.cardinality_estimator.CopyRelationMap(child_binding_maps.at(0));
|
235
|
+
// This logical projection may sit on top of a logical comparison join that has been pushed down
|
236
|
+
// we want to copy the binding info of both tables
|
237
|
+
relation_mapping[proj->table_index] = relation_id;
|
238
|
+
for (auto &binding_info : child_binding_maps.at(0)) {
|
239
|
+
cardinality_estimator.AddRelationToColumnMapping(
|
240
|
+
ColumnBinding(proj->table_index, binding_info.first.column_index), binding_info.second);
|
241
|
+
cardinality_estimator.AddColumnToRelationMap(binding_info.second.table_index,
|
242
|
+
binding_info.second.column_index);
|
243
|
+
}
|
231
244
|
relations.push_back(std::move(relation));
|
232
245
|
return true;
|
233
246
|
}
|
@@ -5,15 +5,21 @@ namespace duckdb {
|
|
5
5
|
|
6
6
|
unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundAggregateExpression &aggr,
|
7
7
|
unique_ptr<Expression> *expr_ptr) {
|
8
|
-
vector<
|
8
|
+
vector<BaseStatistics> stats;
|
9
9
|
stats.reserve(aggr.children.size());
|
10
10
|
for (auto &child : aggr.children) {
|
11
|
-
|
11
|
+
auto stat = PropagateExpression(child);
|
12
|
+
if (!stat) {
|
13
|
+
stats.push_back(BaseStatistics::CreateUnknown(child->return_type));
|
14
|
+
} else {
|
15
|
+
stats.push_back(stat->Copy());
|
16
|
+
}
|
12
17
|
}
|
13
18
|
if (!aggr.function.statistics) {
|
14
19
|
return nullptr;
|
15
20
|
}
|
16
|
-
|
21
|
+
AggregateStatisticsInput input(aggr.bind_info.get(), stats, node_stats.get());
|
22
|
+
return aggr.function.statistics(context, aggr, input);
|
17
23
|
}
|
18
24
|
|
19
25
|
} // namespace duckdb
|
@@ -5,7 +5,6 @@
|
|
5
5
|
#include "duckdb/planner/expression/bound_constant_expression.hpp"
|
6
6
|
#include "duckdb/planner/expression/bound_function_expression.hpp"
|
7
7
|
#include "duckdb/storage/statistics/base_statistics.hpp"
|
8
|
-
#include "duckdb/storage/statistics/numeric_statistics.hpp"
|
9
8
|
#include "duckdb/common/operator/subtract.hpp"
|
10
9
|
|
11
10
|
namespace duckdb {
|
@@ -44,14 +43,14 @@ bool GetCastType(hugeint_t range, LogicalType &cast_type) {
|
|
44
43
|
}
|
45
44
|
|
46
45
|
template <class T>
|
47
|
-
unique_ptr<Expression> TemplatedCastToSmallestType(unique_ptr<Expression> expr,
|
46
|
+
unique_ptr<Expression> TemplatedCastToSmallestType(unique_ptr<Expression> expr, BaseStatistics &stats) {
|
48
47
|
// Compute range
|
49
|
-
if (
|
48
|
+
if (!NumericStats::HasMinMax(stats)) {
|
50
49
|
return expr;
|
51
50
|
}
|
52
51
|
|
53
|
-
auto signed_min_val =
|
54
|
-
auto signed_max_val =
|
52
|
+
auto signed_min_val = NumericStats::Min(stats).GetValue<T>();
|
53
|
+
auto signed_max_val = NumericStats::Max(stats).GetValue<T>();
|
55
54
|
if (signed_max_val < signed_min_val) {
|
56
55
|
return expr;
|
57
56
|
}
|
@@ -82,7 +81,7 @@ unique_ptr<Expression> TemplatedCastToSmallestType(unique_ptr<Expression> expr,
|
|
82
81
|
return BoundCastExpression::AddDefaultCastToType(std::move(minus_expr), cast_type);
|
83
82
|
}
|
84
83
|
|
85
|
-
unique_ptr<Expression> CastToSmallestType(unique_ptr<Expression> expr,
|
84
|
+
unique_ptr<Expression> CastToSmallestType(unique_ptr<Expression> expr, BaseStatistics &num_stats) {
|
86
85
|
auto physical_type = expr->return_type.InternalType();
|
87
86
|
switch (physical_type) {
|
88
87
|
case PhysicalType::UINT8:
|
@@ -111,7 +110,7 @@ void StatisticsPropagator::PropagateAndCompress(unique_ptr<Expression> &expr, un
|
|
111
110
|
stats = PropagateExpression(expr);
|
112
111
|
if (stats) {
|
113
112
|
if (expr->return_type.IsIntegral()) {
|
114
|
-
expr = CastToSmallestType(std::move(expr),
|
113
|
+
expr = CastToSmallestType(std::move(expr), *stats);
|
115
114
|
}
|
116
115
|
}
|
117
116
|
}
|
@@ -1,24 +1,27 @@
|
|
1
1
|
#include "duckdb/optimizer/statistics_propagator.hpp"
|
2
2
|
#include "duckdb/planner/expression/bound_cast_expression.hpp"
|
3
|
-
#include "duckdb/storage/statistics/numeric_statistics.hpp"
|
4
3
|
|
5
4
|
namespace duckdb {
|
6
5
|
|
7
|
-
static unique_ptr<BaseStatistics> StatisticsOperationsNumericNumericCast(const BaseStatistics
|
6
|
+
static unique_ptr<BaseStatistics> StatisticsOperationsNumericNumericCast(const BaseStatistics &input,
|
8
7
|
const LogicalType &target) {
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
if (!NumericStats::HasMinMax(input)) {
|
9
|
+
return nullptr;
|
10
|
+
}
|
11
|
+
Value min = NumericStats::Min(input);
|
12
|
+
Value max = NumericStats::Max(input);
|
12
13
|
if (!min.DefaultTryCastAs(target) || !max.DefaultTryCastAs(target)) {
|
13
14
|
// overflow in cast: bailout
|
14
15
|
return nullptr;
|
15
16
|
}
|
16
|
-
auto
|
17
|
-
|
18
|
-
|
17
|
+
auto result = NumericStats::CreateEmpty(target);
|
18
|
+
result.CopyBase(input);
|
19
|
+
NumericStats::SetMin(result, min);
|
20
|
+
NumericStats::SetMax(result, max);
|
21
|
+
return result.ToUnique();
|
19
22
|
}
|
20
23
|
|
21
|
-
static unique_ptr<BaseStatistics> StatisticsNumericCastSwitch(const BaseStatistics
|
24
|
+
static unique_ptr<BaseStatistics> StatisticsNumericCastSwitch(const BaseStatistics &input, const LogicalType &target) {
|
22
25
|
switch (target.InternalType()) {
|
23
26
|
case PhysicalType::INT8:
|
24
27
|
case PhysicalType::INT16:
|
@@ -48,13 +51,13 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundCastEx
|
|
48
51
|
case PhysicalType::INT128:
|
49
52
|
case PhysicalType::FLOAT:
|
50
53
|
case PhysicalType::DOUBLE:
|
51
|
-
result_stats = StatisticsNumericCastSwitch(child_stats
|
54
|
+
result_stats = StatisticsNumericCastSwitch(*child_stats, cast.return_type);
|
52
55
|
break;
|
53
56
|
default:
|
54
57
|
return nullptr;
|
55
58
|
}
|
56
59
|
if (cast.try_cast && result_stats) {
|
57
|
-
result_stats->
|
60
|
+
result_stats->Set(StatsInfo::CAN_HAVE_NULL_VALUES);
|
58
61
|
}
|
59
62
|
return result_stats;
|
60
63
|
}
|