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.
Files changed (242) hide show
  1. package/binding.gyp +2 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/icu/icu-extension.cpp +2 -0
  4. package/src/duckdb/extension/icu/icu-table-range.cpp +194 -0
  5. package/src/duckdb/extension/icu/include/icu-table-range.hpp +17 -0
  6. package/src/duckdb/extension/parquet/column_reader.cpp +5 -6
  7. package/src/duckdb/extension/parquet/column_writer.cpp +0 -1
  8. package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -2
  9. package/src/duckdb/extension/parquet/include/generated_column_reader.hpp +1 -11
  10. package/src/duckdb/extension/parquet/parquet-extension.cpp +11 -2
  11. package/src/duckdb/extension/parquet/parquet_statistics.cpp +26 -32
  12. package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +4 -0
  13. package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +7 -6
  14. package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +20 -1
  15. package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
  16. package/src/duckdb/src/common/sort/sort_state.cpp +5 -7
  17. package/src/duckdb/src/common/types/bit.cpp +95 -58
  18. package/src/duckdb/src/common/types/value.cpp +149 -53
  19. package/src/duckdb/src/common/types/vector.cpp +13 -10
  20. package/src/duckdb/src/execution/column_binding_resolver.cpp +6 -0
  21. package/src/duckdb/src/execution/operator/aggregate/physical_perfecthash_aggregate.cpp +4 -5
  22. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +1 -1
  23. package/src/duckdb/src/execution/operator/helper/physical_vacuum.cpp +2 -3
  24. package/src/duckdb/src/execution/operator/join/physical_blockwise_nl_join.cpp +32 -6
  25. package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +1 -1
  26. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +15 -15
  27. package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +18 -12
  28. package/src/duckdb/src/function/aggregate/algebraic/avg.cpp +0 -6
  29. package/src/duckdb/src/function/aggregate/distributive/bitagg.cpp +99 -95
  30. package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +254 -0
  31. package/src/duckdb/src/function/aggregate/distributive/count.cpp +2 -4
  32. package/src/duckdb/src/function/aggregate/distributive/sum.cpp +11 -16
  33. package/src/duckdb/src/function/aggregate/distributive_functions.cpp +1 -0
  34. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +16 -5
  35. package/src/duckdb/src/function/cast/bit_cast.cpp +0 -2
  36. package/src/duckdb/src/function/cast/blob_cast.cpp +0 -1
  37. package/src/duckdb/src/function/scalar/bit/bitstring.cpp +99 -0
  38. package/src/duckdb/src/function/scalar/date/date_diff.cpp +0 -1
  39. package/src/duckdb/src/function/scalar/date/date_part.cpp +17 -25
  40. package/src/duckdb/src/function/scalar/date/date_sub.cpp +0 -1
  41. package/src/duckdb/src/function/scalar/date/date_trunc.cpp +10 -14
  42. package/src/duckdb/src/function/scalar/generic/stats.cpp +2 -4
  43. package/src/duckdb/src/function/scalar/list/flatten.cpp +5 -12
  44. package/src/duckdb/src/function/scalar/list/list_concat.cpp +3 -8
  45. package/src/duckdb/src/function/scalar/list/list_extract.cpp +5 -12
  46. package/src/duckdb/src/function/scalar/list/list_value.cpp +5 -9
  47. package/src/duckdb/src/function/scalar/map/map_entries.cpp +61 -0
  48. package/src/duckdb/src/function/scalar/map/map_keys_values.cpp +97 -0
  49. package/src/duckdb/src/function/scalar/math/numeric.cpp +14 -17
  50. package/src/duckdb/src/function/scalar/nested_functions.cpp +3 -0
  51. package/src/duckdb/src/function/scalar/operators/add.cpp +0 -9
  52. package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +29 -48
  53. package/src/duckdb/src/function/scalar/operators/bitwise.cpp +0 -63
  54. package/src/duckdb/src/function/scalar/operators/multiply.cpp +0 -6
  55. package/src/duckdb/src/function/scalar/operators/subtract.cpp +0 -6
  56. package/src/duckdb/src/function/scalar/string/caseconvert.cpp +2 -6
  57. package/src/duckdb/src/function/scalar/string/instr.cpp +2 -6
  58. package/src/duckdb/src/function/scalar/string/length.cpp +2 -6
  59. package/src/duckdb/src/function/scalar/string/like.cpp +2 -6
  60. package/src/duckdb/src/function/scalar/string/substring.cpp +2 -6
  61. package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
  62. package/src/duckdb/src/function/scalar/struct/struct_extract.cpp +4 -9
  63. package/src/duckdb/src/function/scalar/struct/struct_insert.cpp +10 -13
  64. package/src/duckdb/src/function/scalar/struct/struct_pack.cpp +5 -6
  65. package/src/duckdb/src/function/table/read_csv.cpp +9 -0
  66. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  67. package/src/duckdb/src/function/table_function.cpp +19 -0
  68. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +6 -8
  69. package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -19
  70. package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
  71. package/src/duckdb/src/include/duckdb/common/enums/tableref_type.hpp +2 -1
  72. package/src/duckdb/src/include/duckdb/common/types/bit.hpp +5 -1
  73. package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -8
  74. package/src/duckdb/src/include/duckdb/common/types.hpp +1 -2
  75. package/src/duckdb/src/include/duckdb/execution/operator/aggregate/physical_perfecthash_aggregate.hpp +1 -1
  76. package/src/duckdb/src/include/duckdb/function/aggregate/distributive_functions.hpp +5 -0
  77. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +12 -3
  78. package/src/duckdb/src/include/duckdb/function/scalar/bit_functions.hpp +4 -0
  79. package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +12 -0
  80. package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +2 -2
  81. package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
  82. package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +2 -0
  83. package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
  84. package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
  85. package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +2 -2
  86. package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
  87. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +2 -1
  88. package/src/duckdb/src/include/duckdb/parser/parsed_data/{alter_function_info.hpp → alter_scalar_function_info.hpp} +13 -13
  89. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +47 -0
  90. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_function_info.hpp +2 -1
  91. package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
  92. package/src/duckdb/src/include/duckdb/parser/statement/multi_statement.hpp +28 -0
  93. package/src/duckdb/src/include/duckdb/parser/tableref/list.hpp +1 -0
  94. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +76 -0
  95. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +2 -0
  96. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +28 -0
  97. package/src/duckdb/src/include/duckdb/planner/bind_context.hpp +2 -0
  98. package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -0
  99. package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +2 -0
  100. package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +76 -44
  101. package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +3 -2
  102. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_compress.hpp +2 -2
  103. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_fetch.hpp +1 -1
  104. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_scan.hpp +1 -1
  105. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_compress.hpp +2 -2
  106. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_fetch.hpp +1 -1
  107. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_scan.hpp +1 -1
  108. package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +5 -2
  109. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
  110. package/src/duckdb/src/include/duckdb/storage/statistics/base_statistics.hpp +93 -29
  111. package/src/duckdb/src/include/duckdb/storage/statistics/column_statistics.hpp +22 -3
  112. package/src/duckdb/src/include/duckdb/storage/statistics/distinct_statistics.hpp +6 -6
  113. package/src/duckdb/src/include/duckdb/storage/statistics/list_stats.hpp +41 -0
  114. package/src/duckdb/src/include/duckdb/storage/statistics/node_statistics.hpp +26 -0
  115. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats.hpp +157 -0
  116. package/src/duckdb/src/include/duckdb/storage/statistics/segment_statistics.hpp +2 -7
  117. package/src/duckdb/src/include/duckdb/storage/statistics/string_stats.hpp +74 -0
  118. package/src/duckdb/src/include/duckdb/storage/statistics/struct_stats.hpp +42 -0
  119. package/src/duckdb/src/include/duckdb/storage/string_uncompressed.hpp +2 -3
  120. package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +2 -2
  121. package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +1 -1
  122. package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +2 -1
  123. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +4 -3
  124. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +3 -2
  125. package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +2 -0
  126. package/src/duckdb/src/include/duckdb/storage/table/table_statistics.hpp +5 -0
  127. package/src/duckdb/src/include/duckdb.h +49 -1
  128. package/src/duckdb/src/include/duckdb.hpp +0 -1
  129. package/src/duckdb/src/main/capi/pending-c.cpp +16 -3
  130. package/src/duckdb/src/main/capi/result-c.cpp +27 -1
  131. package/src/duckdb/src/main/capi/stream-c.cpp +25 -0
  132. package/src/duckdb/src/main/client_context.cpp +8 -1
  133. package/src/duckdb/src/main/config.cpp +66 -1
  134. package/src/duckdb/src/main/database.cpp +10 -2
  135. package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +98 -67
  136. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +16 -3
  137. package/src/duckdb/src/optimizer/statistics/expression/propagate_aggregate.cpp +9 -3
  138. package/src/duckdb/src/optimizer/statistics/expression/propagate_and_compress.cpp +6 -7
  139. package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +14 -11
  140. package/src/duckdb/src/optimizer/statistics/expression/propagate_columnref.cpp +1 -1
  141. package/src/duckdb/src/optimizer/statistics/expression/propagate_comparison.cpp +13 -15
  142. package/src/duckdb/src/optimizer/statistics/expression/propagate_conjunction.cpp +0 -1
  143. package/src/duckdb/src/optimizer/statistics/expression/propagate_constant.cpp +3 -75
  144. package/src/duckdb/src/optimizer/statistics/expression/propagate_function.cpp +7 -2
  145. package/src/duckdb/src/optimizer/statistics/expression/propagate_operator.cpp +10 -0
  146. package/src/duckdb/src/optimizer/statistics/operator/propagate_aggregate.cpp +2 -3
  147. package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +28 -31
  148. package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +4 -5
  149. package/src/duckdb/src/optimizer/statistics/operator/propagate_set_operation.cpp +3 -3
  150. package/src/duckdb/src/optimizer/statistics_propagator.cpp +1 -1
  151. package/src/duckdb/src/parser/parsed_data/alter_info.cpp +7 -3
  152. package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +56 -0
  153. package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +51 -0
  154. package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +3 -2
  155. package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +6 -0
  156. package/src/duckdb/src/parser/parsed_expression_iterator.cpp +8 -0
  157. package/src/duckdb/src/parser/query_node.cpp +1 -1
  158. package/src/duckdb/src/parser/statement/multi_statement.cpp +18 -0
  159. package/src/duckdb/src/parser/tableref/pivotref.cpp +296 -0
  160. package/src/duckdb/src/parser/tableref.cpp +3 -0
  161. package/src/duckdb/src/parser/transform/helpers/transform_alias.cpp +12 -6
  162. package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +24 -0
  163. package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +4 -0
  164. package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +4 -0
  165. package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +150 -0
  166. package/src/duckdb/src/parser/transform/statement/transform_select.cpp +8 -0
  167. package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -1
  168. package/src/duckdb/src/parser/transform/tableref/transform_join.cpp +4 -0
  169. package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +105 -0
  170. package/src/duckdb/src/parser/transform/tableref/transform_tableref.cpp +2 -0
  171. package/src/duckdb/src/parser/transformer.cpp +15 -3
  172. package/src/duckdb/src/planner/bind_context.cpp +16 -0
  173. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +11 -3
  174. package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +0 -1
  175. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +1 -1
  176. package/src/duckdb/src/planner/binder/statement/bind_logical_plan.cpp +17 -0
  177. package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +9 -0
  178. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +365 -0
  179. package/src/duckdb/src/planner/binder.cpp +7 -1
  180. package/src/duckdb/src/planner/bound_result_modifier.cpp +1 -1
  181. package/src/duckdb/src/planner/expression/bound_window_expression.cpp +1 -1
  182. package/src/duckdb/src/planner/filter/constant_filter.cpp +4 -6
  183. package/src/duckdb/src/planner/pragma_handler.cpp +10 -2
  184. package/src/duckdb/src/storage/buffer_manager.cpp +44 -46
  185. package/src/duckdb/src/storage/checkpoint/row_group_writer.cpp +1 -1
  186. package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +1 -4
  187. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +4 -4
  188. package/src/duckdb/src/storage/compression/bitpacking.cpp +28 -24
  189. package/src/duckdb/src/storage/compression/fixed_size_uncompressed.cpp +43 -45
  190. package/src/duckdb/src/storage/compression/numeric_constant.cpp +9 -10
  191. package/src/duckdb/src/storage/compression/patas.cpp +1 -1
  192. package/src/duckdb/src/storage/compression/rle.cpp +19 -15
  193. package/src/duckdb/src/storage/compression/validity_uncompressed.cpp +5 -5
  194. package/src/duckdb/src/storage/data_table.cpp +4 -6
  195. package/src/duckdb/src/storage/statistics/base_statistics.cpp +373 -128
  196. package/src/duckdb/src/storage/statistics/column_statistics.cpp +58 -3
  197. package/src/duckdb/src/storage/statistics/distinct_statistics.cpp +4 -9
  198. package/src/duckdb/src/storage/statistics/list_stats.cpp +117 -0
  199. package/src/duckdb/src/storage/statistics/numeric_stats.cpp +529 -0
  200. package/src/duckdb/src/storage/statistics/segment_statistics.cpp +2 -11
  201. package/src/duckdb/src/storage/statistics/string_stats.cpp +273 -0
  202. package/src/duckdb/src/storage/statistics/struct_stats.cpp +131 -0
  203. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  204. package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +3 -4
  205. package/src/duckdb/src/storage/table/column_data.cpp +16 -11
  206. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +2 -3
  207. package/src/duckdb/src/storage/table/column_segment.cpp +6 -8
  208. package/src/duckdb/src/storage/table/list_column_data.cpp +39 -58
  209. package/src/duckdb/src/storage/table/row_group.cpp +24 -23
  210. package/src/duckdb/src/storage/table/row_group_collection.cpp +12 -12
  211. package/src/duckdb/src/storage/table/standard_column_data.cpp +6 -6
  212. package/src/duckdb/src/storage/table/struct_column_data.cpp +15 -16
  213. package/src/duckdb/src/storage/table/table_statistics.cpp +27 -7
  214. package/src/duckdb/src/storage/table/update_segment.cpp +10 -12
  215. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +3 -0
  216. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +34 -1
  217. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +1020 -530
  218. package/src/duckdb/third_party/libpg_query/include/parser/kwlist.hpp +7 -0
  219. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +23560 -22737
  220. package/src/duckdb/ub_src_function_aggregate_distributive.cpp +2 -0
  221. package/src/duckdb/ub_src_function_scalar_bit.cpp +2 -0
  222. package/src/duckdb/ub_src_function_scalar_map.cpp +4 -0
  223. package/src/duckdb/ub_src_main_capi.cpp +2 -0
  224. package/src/duckdb/ub_src_parser_parsed_data.cpp +4 -2
  225. package/src/duckdb/ub_src_parser_statement.cpp +2 -0
  226. package/src/duckdb/ub_src_parser_tableref.cpp +2 -0
  227. package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
  228. package/src/duckdb/ub_src_parser_transform_tableref.cpp +2 -0
  229. package/src/duckdb/ub_src_planner_binder_tableref.cpp +2 -0
  230. package/src/duckdb/ub_src_storage_statistics.cpp +4 -6
  231. package/src/duckdb/src/include/duckdb/main/loadable_extension.hpp +0 -59
  232. package/src/duckdb/src/include/duckdb/storage/statistics/list_statistics.hpp +0 -36
  233. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_statistics.hpp +0 -75
  234. package/src/duckdb/src/include/duckdb/storage/statistics/string_statistics.hpp +0 -49
  235. package/src/duckdb/src/include/duckdb/storage/statistics/struct_statistics.hpp +0 -36
  236. package/src/duckdb/src/include/duckdb/storage/statistics/validity_statistics.hpp +0 -45
  237. package/src/duckdb/src/parser/parsed_data/alter_function_info.cpp +0 -55
  238. package/src/duckdb/src/storage/statistics/list_statistics.cpp +0 -94
  239. package/src/duckdb/src/storage/statistics/numeric_statistics.cpp +0 -307
  240. package/src/duckdb/src/storage/statistics/string_statistics.cpp +0 -220
  241. package/src/duckdb/src/storage/statistics/struct_statistics.cpp +0 -108
  242. 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 "", &quota, &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 "", &quota) != 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 = std::thread::hardware_concurrency();
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->type == LogicalOperatorType::LOGICAL_GET) {
16
- auto get = (LogicalGet *)op;
17
- TableCatalogEntry *entry = get->GetTable();
18
- return entry;
14
+ if (!op) {
15
+ return nullptr;
19
16
  }
20
- for (auto &child : op->children) {
21
- TableCatalogEntry *entry = GetCatalogTableEntry(child.get());
22
- if (entry != nullptr) {
23
- return entry;
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
- // TODO: inspect child operators to get a more accurate cost
374
- // and cardinality estimation. If an base op is a Logical Comparison join
375
- // it is probably a left join, so cost of the larger table is a fine
376
- // estimate
377
- // No need to update a mark join cost because I say so.
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 with filters
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 either HLL, or assume it to be
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 (catalog_table) {
410
- relation_attributes[relation_id].original_name = catalog_table->name;
411
- // Get HLL stats here
412
- auto actual_binding = relation_column_to_original_column[key];
426
+ if (get_updated) {
427
+ catalog_table = GetCatalogTableEntry(get);
428
+ }
413
429
 
414
- auto base_stats = catalog_table->GetStatistics(context, actual_binding.column_index);
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
- count = base_stats->GetDistinctCount();
434
+ distinct_count = base_stats->GetDistinctCount();
417
435
  }
418
436
 
419
- // means you have a direct filter on a column. The count/total domain for the column
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
- count = node->GetCardinality<idx_t>();
442
+ distinct_count = node->GetCardinality<idx_t>();
425
443
  }
426
444
 
427
- // HLL has estimation error, count can't be greater than cardinality of the table before filters
428
- if (count > node->GetBaseTableCardinality()) {
429
- count = node->GetBaseTableCardinality();
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 with filter
433
- // otherwise assume the total domain is still the cardinality
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
- count = node->GetCardinality<idx_t>();
453
+ distinct_count = node->GetCardinality<idx_t>();
436
454
  } else {
437
- count = node->GetBaseTableCardinality();
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 < count) {
448
- relation_to_tdom.tdom_hll = count;
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 > count) {
452
- relation_to_tdom.tdom_no_hll = count;
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 > count && !relation_to_tdom.has_tdom_hll) {
460
- relation_to_tdom.tdom_no_hll = count;
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
- // First check table filters
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
- auto table_filters = GetTableFilters(op);
583
+ D_ASSERT(node->set->count == 1);
584
+ auto relation_id = node->set->relations[0];
566
585
 
567
- auto card_after_filters = node->GetBaseTableCardinality();
568
- if (table_filters) {
569
- double inspect_result = (double)InspectTableFilters(card_after_filters, op, table_filters);
570
- card_after_filters = MinValue(inspect_result, (double)card_after_filters);
571
- }
572
- if (has_logical_filter) {
573
- card_after_filters *= DEFAULT_SELECTIVITY;
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(card_after_filters);
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 of the filter bindings the new join order optimizer makes
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 witin the subquery as well
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
- relation_mapping[proj->table_index] = relations.size();
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<unique_ptr<BaseStatistics>> stats;
8
+ vector<BaseStatistics> stats;
9
9
  stats.reserve(aggr.children.size());
10
10
  for (auto &child : aggr.children) {
11
- stats.push_back(PropagateExpression(child));
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
- return aggr.function.statistics(context, aggr, aggr.bind_info.get(), stats, node_stats.get());
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, NumericStatistics &num_stats) {
46
+ unique_ptr<Expression> TemplatedCastToSmallestType(unique_ptr<Expression> expr, BaseStatistics &stats) {
48
47
  // Compute range
49
- if (num_stats.min.IsNull() || num_stats.max.IsNull()) {
48
+ if (!NumericStats::HasMinMax(stats)) {
50
49
  return expr;
51
50
  }
52
51
 
53
- auto signed_min_val = num_stats.min.GetValue<T>();
54
- auto signed_max_val = num_stats.max.GetValue<T>();
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, NumericStatistics &num_stats) {
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), (NumericStatistics &)*stats);
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 *input_p,
6
+ static unique_ptr<BaseStatistics> StatisticsOperationsNumericNumericCast(const BaseStatistics &input,
8
7
  const LogicalType &target) {
9
- auto &input = (NumericStatistics &)*input_p;
10
-
11
- Value min = input.min, max = input.max;
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 stats = make_unique<NumericStatistics>(target, std::move(min), std::move(max), input.stats_type);
17
- stats->CopyBase(*input_p);
18
- return std::move(stats);
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 *input, const LogicalType &target) {
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.get(), cast.return_type);
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->validity_stats = make_unique<ValidityStatistics>(true, true);
60
+ result_stats->Set(StatsInfo::CAN_HAVE_NULL_VALUES);
58
61
  }
59
62
  return result_stats;
60
63
  }
@@ -9,7 +9,7 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundColumn
9
9
  if (stats == statistics_map.end()) {
10
10
  return nullptr;
11
11
  }
12
- return stats->second->Copy();
12
+ return stats->second->ToUnique();
13
13
  }
14
14
 
15
15
  } // namespace duckdb