duckdb 0.7.2-dev2507.0 → 0.7.2-dev2675.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 (254) hide show
  1. package/binding.gyp +7 -7
  2. package/package.json +2 -2
  3. package/src/connection.cpp +1 -1
  4. package/src/duckdb/extension/icu/icu-dateadd.cpp +3 -3
  5. package/src/duckdb/extension/icu/icu-datepart.cpp +3 -3
  6. package/src/duckdb/extension/icu/icu-datesub.cpp +2 -2
  7. package/src/duckdb/extension/icu/icu-datetrunc.cpp +1 -1
  8. package/src/duckdb/extension/icu/icu-extension.cpp +3 -3
  9. package/src/duckdb/extension/icu/icu-list-range.cpp +2 -2
  10. package/src/duckdb/extension/icu/icu-makedate.cpp +1 -1
  11. package/src/duckdb/extension/icu/icu-strptime.cpp +4 -4
  12. package/src/duckdb/extension/icu/icu-table-range.cpp +2 -2
  13. package/src/duckdb/extension/icu/icu-timebucket.cpp +1 -1
  14. package/src/duckdb/extension/icu/icu-timezone.cpp +4 -4
  15. package/src/duckdb/extension/json/json-extension.cpp +6 -6
  16. package/src/duckdb/extension/parquet/parquet-extension.cpp +9 -8
  17. package/src/duckdb/extension/parquet/parquet_statistics.cpp +3 -0
  18. package/src/duckdb/src/catalog/catalog.cpp +166 -127
  19. package/src/duckdb/src/catalog/catalog_entry/copy_function_catalog_entry.cpp +3 -3
  20. package/src/duckdb/src/catalog/catalog_entry/duck_index_entry.cpp +1 -1
  21. package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +90 -82
  22. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +65 -67
  23. package/src/duckdb/src/catalog/catalog_entry/index_catalog_entry.cpp +3 -3
  24. package/src/duckdb/src/catalog/catalog_entry/pragma_function_catalog_entry.cpp +4 -4
  25. package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +8 -8
  26. package/src/duckdb/src/catalog/catalog_entry/scalar_macro_catalog_entry.cpp +10 -10
  27. package/src/duckdb/src/catalog/catalog_entry/schema_catalog_entry.cpp +6 -6
  28. package/src/duckdb/src/catalog/catalog_entry/sequence_catalog_entry.cpp +6 -6
  29. package/src/duckdb/src/catalog/catalog_entry/table_catalog_entry.cpp +4 -4
  30. package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +9 -9
  31. package/src/duckdb/src/catalog/catalog_entry/type_catalog_entry.cpp +5 -5
  32. package/src/duckdb/src/catalog/catalog_entry/view_catalog_entry.cpp +23 -23
  33. package/src/duckdb/src/catalog/catalog_entry.cpp +27 -6
  34. package/src/duckdb/src/catalog/catalog_search_path.cpp +2 -2
  35. package/src/duckdb/src/catalog/catalog_set.cpp +84 -87
  36. package/src/duckdb/src/catalog/catalog_transaction.cpp +1 -1
  37. package/src/duckdb/src/catalog/default/default_functions.cpp +1 -1
  38. package/src/duckdb/src/catalog/default/default_schemas.cpp +1 -1
  39. package/src/duckdb/src/catalog/default/default_types.cpp +1 -1
  40. package/src/duckdb/src/catalog/default/default_views.cpp +1 -1
  41. package/src/duckdb/src/catalog/dependency_list.cpp +2 -2
  42. package/src/duckdb/src/catalog/dependency_manager.cpp +9 -10
  43. package/src/duckdb/src/catalog/duck_catalog.cpp +30 -26
  44. package/src/duckdb/src/catalog/similar_catalog_entry.cpp +1 -1
  45. package/src/duckdb/src/common/radix_partitioning.cpp +1 -1
  46. package/src/duckdb/src/common/types.cpp +15 -27
  47. package/src/duckdb/src/execution/index/art/art.cpp +286 -269
  48. package/src/duckdb/src/execution/index/art/art_key.cpp +22 -32
  49. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +224 -0
  50. package/src/duckdb/src/execution/index/art/iterator.cpp +142 -123
  51. package/src/duckdb/src/execution/index/art/leaf.cpp +319 -170
  52. package/src/duckdb/src/execution/index/art/leaf_segment.cpp +42 -0
  53. package/src/duckdb/src/execution/index/art/node.cpp +444 -379
  54. package/src/duckdb/src/execution/index/art/node16.cpp +178 -114
  55. package/src/duckdb/src/execution/index/art/node256.cpp +117 -79
  56. package/src/duckdb/src/execution/index/art/node4.cpp +169 -114
  57. package/src/duckdb/src/execution/index/art/node48.cpp +175 -105
  58. package/src/duckdb/src/execution/index/art/prefix.cpp +405 -127
  59. package/src/duckdb/src/execution/index/art/prefix_segment.cpp +42 -0
  60. package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +10 -85
  61. package/src/duckdb/src/execution/operator/join/physical_index_join.cpp +4 -3
  62. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +2 -2
  63. package/src/duckdb/src/execution/operator/persistent/csv_reader_options.cpp +2 -0
  64. package/src/duckdb/src/execution/operator/persistent/physical_batch_insert.cpp +4 -3
  65. package/src/duckdb/src/execution/operator/persistent/physical_export.cpp +19 -18
  66. package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +5 -5
  67. package/src/duckdb/src/execution/operator/schema/physical_alter.cpp +1 -1
  68. package/src/duckdb/src/execution/operator/schema/physical_create_function.cpp +1 -1
  69. package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +17 -17
  70. package/src/duckdb/src/execution/operator/schema/physical_create_schema.cpp +1 -1
  71. package/src/duckdb/src/execution/operator/schema/physical_create_sequence.cpp +1 -1
  72. package/src/duckdb/src/execution/operator/schema/physical_create_table.cpp +2 -2
  73. package/src/duckdb/src/execution/operator/schema/physical_create_type.cpp +4 -3
  74. package/src/duckdb/src/execution/operator/schema/physical_create_view.cpp +1 -1
  75. package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +1 -1
  76. package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +2 -2
  77. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +1 -1
  78. package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +4 -4
  79. package/src/duckdb/src/execution/physical_plan/plan_create_table.cpp +4 -3
  80. package/src/duckdb/src/execution/physical_plan/plan_delete.cpp +1 -1
  81. package/src/duckdb/src/execution/physical_plan/plan_insert.cpp +1 -1
  82. package/src/duckdb/src/execution/physical_plan/plan_update.cpp +1 -1
  83. package/src/duckdb/src/function/built_in_functions.cpp +10 -10
  84. package/src/duckdb/src/function/function_binder.cpp +3 -3
  85. package/src/duckdb/src/function/scalar/list/list_aggregates.cpp +5 -6
  86. package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +2 -2
  87. package/src/duckdb/src/function/scalar/sequence/nextval.cpp +9 -8
  88. package/src/duckdb/src/function/scalar/system/aggregate_export.cpp +6 -6
  89. package/src/duckdb/src/function/table/arrow.cpp +5 -5
  90. package/src/duckdb/src/function/table/read_csv.cpp +5 -1
  91. package/src/duckdb/src/function/table/system/duckdb_columns.cpp +8 -7
  92. package/src/duckdb/src/function/table/system/duckdb_constraints.cpp +14 -14
  93. package/src/duckdb/src/function/table/system/duckdb_databases.cpp +2 -2
  94. package/src/duckdb/src/function/table/system/duckdb_functions.cpp +26 -25
  95. package/src/duckdb/src/function/table/system/duckdb_indexes.cpp +13 -12
  96. package/src/duckdb/src/function/table/system/duckdb_schemas.cpp +7 -7
  97. package/src/duckdb/src/function/table/system/duckdb_sequences.cpp +8 -9
  98. package/src/duckdb/src/function/table/system/duckdb_tables.cpp +10 -9
  99. package/src/duckdb/src/function/table/system/duckdb_types.cpp +13 -13
  100. package/src/duckdb/src/function/table/system/duckdb_views.cpp +11 -10
  101. package/src/duckdb/src/function/table/system/pragma_collations.cpp +2 -2
  102. package/src/duckdb/src/function/table/system/pragma_database_size.cpp +5 -5
  103. package/src/duckdb/src/function/table/system/pragma_storage_info.cpp +3 -3
  104. package/src/duckdb/src/function/table/system/pragma_table_info.cpp +2 -2
  105. package/src/duckdb/src/function/table/table_scan.cpp +39 -37
  106. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  107. package/src/duckdb/src/function/udf_function.cpp +2 -2
  108. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +122 -81
  109. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp +2 -3
  110. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/collate_catalog_entry.hpp +3 -3
  111. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/copy_function_catalog_entry.hpp +1 -1
  112. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +1 -1
  113. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_schema_entry.hpp +24 -20
  114. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp +3 -3
  115. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
  116. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/macro_catalog_entry.hpp +2 -2
  117. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/pragma_function_catalog_entry.hpp +1 -1
  118. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp +2 -2
  119. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp +1 -1
  120. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/schema_catalog_entry.hpp +22 -17
  121. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp +1 -1
  122. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp +1 -1
  123. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +2 -2
  124. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_macro_catalog_entry.hpp +1 -1
  125. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/type_catalog_entry.hpp +1 -1
  126. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/view_catalog_entry.hpp +3 -3
  127. package/src/duckdb/src/include/duckdb/catalog/catalog_entry.hpp +28 -7
  128. package/src/duckdb/src/include/duckdb/catalog/catalog_set.hpp +20 -19
  129. package/src/duckdb/src/include/duckdb/catalog/duck_catalog.hpp +9 -9
  130. package/src/duckdb/src/include/duckdb/catalog/similar_catalog_entry.hpp +2 -1
  131. package/src/duckdb/src/include/duckdb/catalog/standard_entry.hpp +10 -4
  132. package/src/duckdb/src/include/duckdb/common/enums/on_entry_not_found.hpp +17 -0
  133. package/src/duckdb/src/include/duckdb/common/queue.hpp +1 -1
  134. package/src/duckdb/src/include/duckdb/common/types.hpp +3 -4
  135. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +53 -45
  136. package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +29 -24
  137. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +114 -0
  138. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +26 -20
  139. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +63 -39
  140. package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +36 -0
  141. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +98 -116
  142. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +48 -36
  143. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +52 -35
  144. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +46 -36
  145. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +57 -35
  146. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +57 -50
  147. package/src/duckdb/src/include/duckdb/execution/index/art/prefix_segment.hpp +40 -0
  148. package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +38 -31
  149. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_file_handle.hpp +2 -1
  150. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
  151. package/src/duckdb/src/include/duckdb/function/function_serialization.hpp +4 -4
  152. package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +3 -2
  153. package/src/duckdb/src/include/duckdb/function/table/table_scan.hpp +5 -4
  154. package/src/duckdb/src/include/duckdb/function/table_function.hpp +28 -15
  155. package/src/duckdb/src/include/duckdb/main/attached_database.hpp +2 -0
  156. package/src/duckdb/src/include/duckdb/main/client_context.hpp +1 -1
  157. package/src/duckdb/src/include/duckdb/main/database_manager.hpp +3 -2
  158. package/src/duckdb/src/include/duckdb/parser/expression/bound_expression.hpp +2 -0
  159. package/src/duckdb/src/include/duckdb/parser/keyword_helper.hpp +2 -2
  160. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +7 -5
  161. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_info.hpp +1 -1
  162. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_info.hpp +1 -1
  163. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_view_info.hpp +1 -1
  164. package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +3 -2
  165. package/src/duckdb/src/include/duckdb/parser/parsed_data/drop_info.hpp +5 -5
  166. package/src/duckdb/src/include/duckdb/parser/parsed_data/parse_info.hpp +13 -0
  167. package/src/duckdb/src/include/duckdb/parser/statement/insert_statement.hpp +4 -1
  168. package/src/duckdb/src/include/duckdb/parser/tableref.hpp +5 -2
  169. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +4 -1
  170. package/src/duckdb/src/include/duckdb/planner/binder.hpp +2 -2
  171. package/src/duckdb/src/include/duckdb/planner/expression_binder/base_select_binder.hpp +1 -2
  172. package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +4 -7
  173. package/src/duckdb/src/include/duckdb/planner/operator/logical_get.hpp +1 -1
  174. package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +0 -5
  175. package/src/duckdb/src/include/duckdb/storage/index.hpp +13 -28
  176. package/src/duckdb/src/include/duckdb/storage/standard_buffer_manager.hpp +0 -2
  177. package/src/duckdb/src/include/duckdb/transaction/cleanup_state.hpp +5 -0
  178. package/src/duckdb/src/include/duckdb/transaction/transaction.hpp +12 -0
  179. package/src/duckdb/src/include/duckdb.h +26 -0
  180. package/src/duckdb/src/main/attached_database.cpp +12 -6
  181. package/src/duckdb/src/main/capi/helper-c.cpp +7 -0
  182. package/src/duckdb/src/main/capi/table_function-c.cpp +17 -16
  183. package/src/duckdb/src/main/client_context.cpp +12 -11
  184. package/src/duckdb/src/main/database_manager.cpp +13 -12
  185. package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +1 -2
  186. package/src/duckdb/src/parser/parsed_data/alter_info.cpp +3 -3
  187. package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +2 -2
  188. package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +2 -2
  189. package/src/duckdb/src/parser/parsed_data/alter_table_info.cpp +9 -9
  190. package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +2 -2
  191. package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +2 -2
  192. package/src/duckdb/src/parser/parsed_data/create_table_info.cpp +2 -2
  193. package/src/duckdb/src/parser/parsed_data/create_view_info.cpp +2 -2
  194. package/src/duckdb/src/parser/statement/insert_statement.cpp +15 -6
  195. package/src/duckdb/src/parser/transform/constraint/transform_constraint.cpp +1 -1
  196. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +18 -5
  197. package/src/duckdb/src/parser/transform/statement/transform_alter_sequence.cpp +3 -2
  198. package/src/duckdb/src/parser/transform/statement/transform_alter_table.cpp +5 -1
  199. package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +1 -1
  200. package/src/duckdb/src/parser/transform/statement/transform_drop.cpp +1 -1
  201. package/src/duckdb/src/parser/transform/statement/transform_insert.cpp +5 -7
  202. package/src/duckdb/src/parser/transform/statement/transform_rename.cpp +1 -1
  203. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +26 -27
  204. package/src/duckdb/src/planner/binder/expression/bind_between_expression.cpp +17 -17
  205. package/src/duckdb/src/planner/binder/expression/bind_case_expression.cpp +9 -9
  206. package/src/duckdb/src/planner/binder/expression/bind_cast_expression.cpp +6 -6
  207. package/src/duckdb/src/planner/binder/expression/bind_collate_expression.cpp +6 -6
  208. package/src/duckdb/src/planner/binder/expression/bind_columnref_expression.cpp +2 -2
  209. package/src/duckdb/src/planner/binder/expression/bind_comparison_expression.cpp +21 -21
  210. package/src/duckdb/src/planner/binder/expression/bind_conjunction_expression.cpp +2 -3
  211. package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +33 -36
  212. package/src/duckdb/src/planner/binder/expression/bind_macro_expression.cpp +5 -5
  213. package/src/duckdb/src/planner/binder/expression/bind_operator_expression.cpp +23 -23
  214. package/src/duckdb/src/planner/binder/expression/bind_subquery_expression.cpp +4 -4
  215. package/src/duckdb/src/planner/binder/expression/bind_unnest_expression.cpp +7 -7
  216. package/src/duckdb/src/planner/binder/expression/bind_window_expression.cpp +23 -23
  217. package/src/duckdb/src/planner/binder/query_node/bind_table_macro_node.cpp +4 -4
  218. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +14 -13
  219. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +56 -42
  220. package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +3 -3
  221. package/src/duckdb/src/planner/binder/statement/bind_delete.cpp +1 -1
  222. package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +4 -4
  223. package/src/duckdb/src/planner/binder/statement/bind_export.cpp +10 -10
  224. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +16 -11
  225. package/src/duckdb/src/planner/binder/statement/bind_pragma.cpp +4 -4
  226. package/src/duckdb/src/planner/binder/statement/bind_simple.cpp +5 -4
  227. package/src/duckdb/src/planner/binder/statement/bind_update.cpp +1 -1
  228. package/src/duckdb/src/planner/binder/tableref/bind_basetableref.cpp +3 -3
  229. package/src/duckdb/src/planner/binder/tableref/bind_table_function.cpp +10 -12
  230. package/src/duckdb/src/planner/binder.cpp +2 -2
  231. package/src/duckdb/src/planner/expression/bound_expression.cpp +11 -2
  232. package/src/duckdb/src/planner/operator/logical_copy_to_file.cpp +2 -5
  233. package/src/duckdb/src/planner/operator/logical_create.cpp +2 -1
  234. package/src/duckdb/src/planner/operator/logical_create_index.cpp +2 -2
  235. package/src/duckdb/src/planner/operator/logical_delete.cpp +2 -2
  236. package/src/duckdb/src/planner/operator/logical_get.cpp +1 -1
  237. package/src/duckdb/src/planner/operator/logical_insert.cpp +2 -7
  238. package/src/duckdb/src/planner/operator/logical_update.cpp +2 -6
  239. package/src/duckdb/src/planner/parsed_data/bound_create_table_info.cpp +2 -2
  240. package/src/duckdb/src/planner/pragma_handler.cpp +3 -4
  241. package/src/duckdb/src/storage/checkpoint_manager.cpp +57 -55
  242. package/src/duckdb/src/storage/data_table.cpp +9 -9
  243. package/src/duckdb/src/storage/index.cpp +18 -6
  244. package/src/duckdb/src/storage/local_storage.cpp +8 -2
  245. package/src/duckdb/src/storage/standard_buffer_manager.cpp +0 -9
  246. package/src/duckdb/src/storage/table/update_segment.cpp +1 -1
  247. package/src/duckdb/src/storage/wal_replay.cpp +29 -31
  248. package/src/duckdb/src/storage/write_ahead_log.cpp +8 -8
  249. package/src/duckdb/src/transaction/cleanup_state.cpp +7 -1
  250. package/src/duckdb/src/transaction/commit_state.cpp +3 -4
  251. package/src/duckdb/src/transaction/transaction_context.cpp +1 -1
  252. package/src/duckdb/src/transaction/undo_buffer.cpp +8 -0
  253. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
  254. package/src/duckdb/ub_src_execution_index_art.cpp +7 -1
@@ -5,12 +5,20 @@
5
5
  #include "duckdb/execution/expression_executor.hpp"
6
6
  #include "duckdb/storage/arena_allocator.hpp"
7
7
  #include "duckdb/execution/index/art/art_key.hpp"
8
+ #include "duckdb/execution/index/art/prefix_segment.hpp"
9
+ #include "duckdb/execution/index/art/leaf_segment.hpp"
10
+ #include "duckdb/execution/index/art/prefix.hpp"
11
+ #include "duckdb/execution/index/art/leaf.hpp"
12
+ #include "duckdb/execution/index/art/node4.hpp"
13
+ #include "duckdb/execution/index/art/node16.hpp"
14
+ #include "duckdb/execution/index/art/node48.hpp"
15
+ #include "duckdb/execution/index/art/node256.hpp"
16
+ #include "duckdb/execution/index/art/iterator.hpp"
8
17
  #include "duckdb/common/types/conflict_manager.hpp"
9
18
  #include "duckdb/storage/table/scan_state.hpp"
10
19
 
11
20
  #include <algorithm>
12
21
  #include <cstring>
13
- #include <ctgmath>
14
22
 
15
23
  namespace duckdb {
16
24
 
@@ -27,23 +35,30 @@ struct ARTIndexScanState : public IndexScanState {
27
35
  };
28
36
 
29
37
  ART::ART(const vector<column_t> &column_ids, TableIOManager &table_io_manager,
30
- const vector<unique_ptr<Expression>> &unbound_expressions, IndexConstraintType constraint_type,
31
- AttachedDatabase &db, bool track_memory, idx_t block_id, idx_t block_offset)
38
+ const vector<unique_ptr<Expression>> &unbound_expressions, const IndexConstraintType constraint_type,
39
+ AttachedDatabase &db, const idx_t block_id, const idx_t block_offset)
32
40
 
33
- : Index(db, IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type, track_memory) {
41
+ : Index(db, IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type) {
34
42
 
35
43
  if (!Radix::IsLittleEndian()) {
36
44
  throw NotImplementedException("ART indexes are not supported on big endian architectures");
37
45
  }
38
46
 
47
+ // initialize all allocators
48
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(PrefixSegment), buffer_manager.GetBufferAllocator()));
49
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(LeafSegment), buffer_manager.GetBufferAllocator()));
50
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(Leaf), buffer_manager.GetBufferAllocator()));
51
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(Node4), buffer_manager.GetBufferAllocator()));
52
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(Node16), buffer_manager.GetBufferAllocator()));
53
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(Node48), buffer_manager.GetBufferAllocator()));
54
+ allocators.emplace_back(make_uniq<FixedSizeAllocator>(sizeof(Node256), buffer_manager.GetBufferAllocator()));
55
+
39
56
  // set the root node of the tree
40
- tree = nullptr;
57
+ tree = make_uniq<Node>();
41
58
  if (block_id != DConstants::INVALID_INDEX) {
42
- tree = Node::Deserialize(*this, block_id, block_offset);
43
- Verify();
44
- if (track_memory) {
45
- buffer_manager.IncreaseUsedMemory(memory_size);
46
- }
59
+ tree->buffer_id = block_id;
60
+ tree->offset = block_offset;
61
+ tree->Deserialize(*this);
47
62
  }
48
63
  serialized_data_pointer = BlockPointer(block_id, block_offset);
49
64
 
@@ -71,15 +86,7 @@ ART::ART(const vector<column_t> &column_ids, TableIOManager &table_io_manager,
71
86
  }
72
87
 
73
88
  ART::~ART() {
74
- if (!tree) {
75
- return;
76
- }
77
- Verify();
78
- if (track_memory) {
79
- buffer_manager.DecreaseUsedMemory(memory_size);
80
- }
81
- Node::Delete(tree);
82
- tree = nullptr;
89
+ tree->Reset();
83
90
  }
84
91
 
85
92
  //===--------------------------------------------------------------------===//
@@ -87,7 +94,7 @@ ART::~ART() {
87
94
  //===--------------------------------------------------------------------===//
88
95
 
89
96
  unique_ptr<IndexScanState> ART::InitializeScanSinglePredicate(const Transaction &transaction, const Value &value,
90
- ExpressionType expression_type) {
97
+ const ExpressionType expression_type) {
91
98
  // initialize point lookup
92
99
  auto result = make_uniq<ARTIndexScanState>();
93
100
  result->values[0] = value;
@@ -95,9 +102,10 @@ unique_ptr<IndexScanState> ART::InitializeScanSinglePredicate(const Transaction
95
102
  return std::move(result);
96
103
  }
97
104
 
98
- unique_ptr<IndexScanState> ART::InitializeScanTwoPredicates(Transaction &transaction, const Value &low_value,
99
- ExpressionType low_expression_type, const Value &high_value,
100
- ExpressionType high_expression_type) {
105
+ unique_ptr<IndexScanState> ART::InitializeScanTwoPredicates(const Transaction &transaction, const Value &low_value,
106
+ const ExpressionType low_expression_type,
107
+ const Value &high_value,
108
+ const ExpressionType high_expression_type) {
101
109
  // initialize range lookup
102
110
  auto result = make_uniq<ARTIndexScanState>();
103
111
  result->values[0] = low_value;
@@ -112,7 +120,7 @@ unique_ptr<IndexScanState> ART::InitializeScanTwoPredicates(Transaction &transac
112
120
  //===--------------------------------------------------------------------===//
113
121
 
114
122
  template <class T>
115
- static void TemplatedGenerateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector<Key> &keys) {
123
+ static void TemplatedGenerateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector<ARTKey> &keys) {
116
124
  UnifiedVectorFormat idata;
117
125
  input.ToUnifiedFormat(count, idata);
118
126
 
@@ -121,13 +129,13 @@ static void TemplatedGenerateKeys(ArenaAllocator &allocator, Vector &input, idx_
121
129
  for (idx_t i = 0; i < count; i++) {
122
130
  auto idx = idata.sel->get_index(i);
123
131
  if (idata.validity.RowIsValid(idx)) {
124
- Key::CreateKey<T>(allocator, input.GetType(), keys[i], input_data[idx]);
132
+ ARTKey::CreateARTKey<T>(allocator, input.GetType(), keys[i], input_data[idx]);
125
133
  }
126
134
  }
127
135
  }
128
136
 
129
137
  template <class T>
130
- static void ConcatenateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector<Key> &keys) {
138
+ static void ConcatenateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector<ARTKey> &keys) {
131
139
  UnifiedVectorFormat idata;
132
140
  input.ToUnifiedFormat(count, idata);
133
141
 
@@ -139,16 +147,16 @@ static void ConcatenateKeys(ArenaAllocator &allocator, Vector &input, idx_t coun
139
147
  if (!keys[i].Empty()) {
140
148
  if (!idata.validity.RowIsValid(idx)) {
141
149
  // this column entry is NULL, set whole key to NULL
142
- keys[i] = Key();
150
+ keys[i] = ARTKey();
143
151
  } else {
144
- auto other_key = Key::CreateKey<T>(allocator, input.GetType(), input_data[idx]);
145
- keys[i].ConcatenateKey(allocator, other_key);
152
+ auto other_key = ARTKey::CreateARTKey<T>(allocator, input.GetType(), input_data[idx]);
153
+ keys[i].ConcatenateARTKey(allocator, other_key);
146
154
  }
147
155
  }
148
156
  }
149
157
  }
150
158
 
151
- void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<Key> &keys) {
159
+ void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<ARTKey> &keys) {
152
160
  // generate keys for the first input column
153
161
  switch (input.data[0].GetType().InternalType()) {
154
162
  case PhysicalType::BOOL:
@@ -249,7 +257,7 @@ void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<Key>
249
257
  struct KeySection {
250
258
  KeySection(idx_t start_p, idx_t end_p, idx_t depth_p, data_t key_byte_p)
251
259
  : start(start_p), end(end_p), depth(depth_p), key_byte(key_byte_p) {};
252
- KeySection(idx_t start_p, idx_t end_p, vector<Key> &keys, KeySection &key_section)
260
+ KeySection(idx_t start_p, idx_t end_p, vector<ARTKey> &keys, KeySection &key_section)
253
261
  : start(start_p), end(end_p), depth(key_section.depth + 1), key_byte(keys[end_p].data[key_section.depth]) {};
254
262
  idx_t start;
255
263
  idx_t end;
@@ -257,7 +265,7 @@ struct KeySection {
257
265
  data_t key_byte;
258
266
  };
259
267
 
260
- void GetChildSections(vector<KeySection> &child_sections, vector<Key> &keys, KeySection &key_section) {
268
+ void GetChildSections(vector<KeySection> &child_sections, vector<ARTKey> &keys, KeySection &key_section) {
261
269
 
262
270
  idx_t child_start_idx = key_section.start;
263
271
  for (idx_t i = key_section.start + 1; i <= key_section.end; i++) {
@@ -269,7 +277,7 @@ void GetChildSections(vector<KeySection> &child_sections, vector<Key> &keys, Key
269
277
  child_sections.emplace_back(child_start_idx, key_section.end, keys, key_section);
270
278
  }
271
279
 
272
- bool Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySection &key_section,
280
+ bool Construct(ART &art, vector<ARTKey> &keys, row_t *row_ids, Node &node, KeySection &key_section,
273
281
  bool &has_constraint) {
274
282
 
275
283
  D_ASSERT(key_section.start < keys.size());
@@ -297,29 +305,28 @@ bool Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySect
297
305
  }
298
306
 
299
307
  if (single_row_id) {
300
- node = Leaf::New(start_key, prefix_start, row_ids[key_section.start]);
308
+ Leaf::New(art, node, start_key, prefix_start, row_ids[key_section.start]);
301
309
  } else {
302
- node = Leaf::New(start_key, prefix_start, row_ids + key_section.start, num_row_ids);
310
+ Leaf::New(art, node, start_key, prefix_start, row_ids + key_section.start, num_row_ids);
303
311
  }
304
- art.IncreaseMemorySize(node->MemorySize(art, false));
305
312
  return true;
306
313
  }
314
+
307
315
  // create a new node and recurse
308
316
 
309
317
  // we will find at least two child entries of this node, otherwise we'd have reached a leaf
310
318
  vector<KeySection> child_sections;
311
319
  GetChildSections(child_sections, keys, key_section);
312
320
 
313
- auto node_type = Node::GetTypeBySize(child_sections.size());
314
- Node::New(node_type, node);
321
+ auto node_type = Node::GetARTNodeTypeByCount(child_sections.size());
322
+ Node::New(art, node, node_type);
315
323
 
316
324
  auto prefix_length = key_section.depth - prefix_start;
317
- node->prefix = Prefix(start_key, prefix_start, prefix_length);
318
- art.IncreaseMemorySize(node->MemorySize(art, false));
325
+ node.GetPrefix(art).Initialize(art, start_key, prefix_start, prefix_length);
319
326
 
320
327
  // recurse on each child section
321
328
  for (auto &child_section : child_sections) {
322
- Node *new_child = nullptr;
329
+ Node new_child;
323
330
  auto no_violation = Construct(art, keys, row_ids, new_child, child_section, has_constraint);
324
331
  Node::InsertChild(art, node, child_section.key_byte, new_child);
325
332
  if (!no_violation) {
@@ -329,7 +336,7 @@ bool Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySect
329
336
  return true;
330
337
  }
331
338
 
332
- bool ART::ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identifiers) {
339
+ bool ART::ConstructFromSorted(idx_t count, vector<ARTKey> &keys, Vector &row_identifiers) {
333
340
 
334
341
  // prepare the row_identifiers
335
342
  row_identifiers.Flatten(count);
@@ -337,7 +344,7 @@ bool ART::ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identi
337
344
 
338
345
  auto key_section = KeySection(0, count - 1, 0, 0);
339
346
  auto has_constraint = IsUnique();
340
- return Construct(*this, keys, row_ids, this->tree, key_section, has_constraint);
347
+ return Construct(*this, keys, row_ids, *this->tree, key_section, has_constraint);
341
348
  }
342
349
 
343
350
  //===--------------------------------------------------------------------===//
@@ -348,11 +355,9 @@ PreservedError ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
348
355
  D_ASSERT(row_ids.GetType().InternalType() == ROW_TYPE);
349
356
  D_ASSERT(logical_types[0] == input.data[0].GetType());
350
357
 
351
- auto old_memory_size = memory_size;
352
-
353
358
  // generate the keys for the given input
354
359
  ArenaAllocator arena_allocator(BufferAllocator::Get(db));
355
- vector<Key> keys(input.size());
360
+ vector<ARTKey> keys(input.size());
356
361
  GenerateKeys(arena_allocator, input, keys);
357
362
 
358
363
  // get the corresponding row IDs
@@ -367,7 +372,7 @@ PreservedError ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
367
372
  }
368
373
 
369
374
  row_t row_id = row_identifiers[i];
370
- if (!Insert(tree, keys[i], 0, row_id)) {
375
+ if (!Insert(*tree, keys[i], 0, row_id)) {
371
376
  // failed to insert because of constraint violation
372
377
  failed_index = i;
373
378
  break;
@@ -381,11 +386,10 @@ PreservedError ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
381
386
  continue;
382
387
  }
383
388
  row_t row_id = row_identifiers[i];
384
- Erase(tree, keys[i], 0, row_id);
389
+ Erase(*tree, keys[i], 0, row_id);
385
390
  }
386
391
  }
387
392
 
388
- IncreaseAndVerifyMemorySize(old_memory_size);
389
393
  if (failed_index != DConstants::INVALID_INDEX) {
390
394
  return PreservedError(ConstraintException("PRIMARY KEY or UNIQUE constraint violated: duplicate key \"%s\"",
391
395
  AppendRowError(input, failed_index)));
@@ -414,10 +418,13 @@ void ART::VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) {
414
418
  CheckConstraintsForChunk(chunk, conflict_manager);
415
419
  }
416
420
 
417
- bool ART::InsertToLeaf(Leaf &leaf, row_t row_id) {
421
+ bool ART::InsertToLeaf(Node &leaf_node, const row_t &row_id) {
422
+
423
+ auto &leaf = Leaf::Get(*this, leaf_node);
424
+
418
425
  #ifdef DEBUG
419
426
  for (idx_t k = 0; k < leaf.count; k++) {
420
- D_ASSERT(leaf.GetRowId(k) != row_id);
427
+ D_ASSERT(leaf.GetRowId(*this, k) != row_id);
421
428
  }
422
429
  #endif
423
430
  if (IsUnique() && leaf.count != 0) {
@@ -427,86 +434,75 @@ bool ART::InsertToLeaf(Leaf &leaf, row_t row_id) {
427
434
  return true;
428
435
  }
429
436
 
430
- bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
437
+ bool ART::Insert(Node &node, const ARTKey &key, idx_t depth, const row_t &row_id) {
431
438
 
432
- if (!node) {
439
+ if (!node.IsSet()) {
433
440
  // node is currently empty, create a leaf here with the key
434
- node = Leaf::New(key, depth, row_id);
435
- IncreaseMemorySize(node->MemorySize(*this, false));
441
+ Leaf::New(*this, node, key, depth, row_id);
436
442
  return true;
437
443
  }
438
444
 
439
- if (node->type == NodeType::NLeaf) {
440
- // replace leaf with Node4 and store both leaves in it
441
- // or add a row ID to a leaf, if they have the same key
442
- auto leaf = (Leaf *)node;
443
- uint32_t new_prefix_length = 0;
444
-
445
- // FIXME: this code (if and while) can be optimized, less branching, see Construct
446
- // leaf node is already there (its key matches the current key), update row_id vector
447
- if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) {
448
- return InsertToLeaf(*leaf, row_id);
449
- }
450
- while (leaf->prefix[new_prefix_length] == key[depth + new_prefix_length]) {
451
- new_prefix_length++;
452
- // leaf node is already there (its key matches the current key), update row_id vector
453
- if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) {
454
- return InsertToLeaf(*leaf, row_id);
455
- }
445
+ if (node.DecodeARTNodeType() == NType::LEAF) {
446
+
447
+ // add a row ID to a leaf, if they have the same key
448
+ auto &leaf = Leaf::Get(*this, node);
449
+ auto mismatch_position = leaf.prefix.KeyMismatchPosition(*this, key, depth);
450
+ if (mismatch_position == leaf.prefix.count && depth + leaf.prefix.count == key.len) {
451
+ return InsertToLeaf(node, row_id);
456
452
  }
457
453
 
458
- Node *new_node = Node4::New();
459
- new_node->prefix = Prefix(key, depth, new_prefix_length);
460
- IncreaseMemorySize(new_node->MemorySize(*this, false));
454
+ // replace leaf with Node4 and store both leaves in it
455
+ auto old_node = node;
456
+ auto &new_n4 = Node4::New(*this, node);
457
+ new_n4.prefix.Initialize(*this, key, depth, mismatch_position);
461
458
 
462
- auto key_byte = node->prefix.Reduce(*this, new_prefix_length);
463
- Node4::InsertChild(*this, new_node, key_byte, node);
459
+ auto key_byte = old_node.GetPrefix(*this).Reduce(*this, mismatch_position);
460
+ Node4::InsertChild(*this, node, key_byte, old_node);
464
461
 
465
- Node *leaf_node = Leaf::New(key, depth + new_prefix_length + 1, row_id);
466
- Node4::InsertChild(*this, new_node, key[depth + new_prefix_length], leaf_node);
467
- IncreaseMemorySize(leaf_node->MemorySize(*this, false));
462
+ Node leaf_node;
463
+ Leaf::New(*this, leaf_node, key, depth + mismatch_position + 1, row_id);
464
+ Node4::InsertChild(*this, node, key[depth + mismatch_position], leaf_node);
468
465
 
469
- node = new_node;
470
466
  return true;
471
467
  }
472
468
 
473
469
  // handle prefix of inner node
474
- if (node->prefix.Size()) {
470
+ auto &old_node_prefix = node.GetPrefix(*this);
471
+ if (old_node_prefix.count) {
472
+
473
+ auto mismatch_position = old_node_prefix.KeyMismatchPosition(*this, key, depth);
474
+ if (mismatch_position != old_node_prefix.count) {
475
475
 
476
- uint32_t mismatch_pos = node->prefix.KeyMismatchPosition(key, depth);
477
- if (mismatch_pos != node->prefix.Size()) {
478
476
  // prefix differs, create new node
479
- Node *new_node = Node4::New();
480
- new_node->prefix = Prefix(key, depth, mismatch_pos);
481
- IncreaseMemorySize(new_node->MemorySize(*this, false));
477
+ auto old_node = node;
478
+ auto &new_n4 = Node4::New(*this, node);
479
+ new_n4.prefix.Initialize(*this, key, depth, mismatch_position);
482
480
 
483
- // break up prefix
484
- auto key_byte = node->prefix.Reduce(*this, mismatch_pos);
485
- Node4::InsertChild(*this, new_node, key_byte, node);
481
+ auto key_byte = old_node_prefix.Reduce(*this, mismatch_position);
482
+ Node4::InsertChild(*this, node, key_byte, old_node);
486
483
 
487
- Node *leaf_node = Leaf::New(key, depth + mismatch_pos + 1, row_id);
488
- Node4::InsertChild(*this, new_node, key[depth + mismatch_pos], leaf_node);
489
- IncreaseMemorySize(leaf_node->MemorySize(*this, false));
484
+ Node leaf_node;
485
+ Leaf::New(*this, leaf_node, key, depth + mismatch_position + 1, row_id);
486
+ Node4::InsertChild(*this, node, key[depth + mismatch_position], leaf_node);
490
487
 
491
- node = new_node;
492
488
  return true;
493
489
  }
494
- depth += node->prefix.Size();
490
+ depth += node.GetPrefix(*this).count;
495
491
  }
496
492
 
497
493
  // recurse
498
494
  D_ASSERT(depth < key.len);
499
- idx_t pos = node->GetChildPos(key[depth]);
500
- if (pos != DConstants::INVALID_INDEX) {
501
- auto child = node->GetChild(*this, pos);
502
- bool insertion_result = Insert(child, key, depth + 1, row_id);
503
- node->ReplaceChildPointer(pos, child);
504
- return insertion_result;
495
+ auto child = node.GetChild(*this, key[depth]);
496
+ if (child) {
497
+ bool success = Insert(*child, key, depth + 1, row_id);
498
+ node.ReplaceChild(*this, key[depth], *child);
499
+ return success;
505
500
  }
506
501
 
507
- Node *leaf_node = Leaf::New(key, depth + 1, row_id);
502
+ // insert at position
503
+ Node leaf_node;
504
+ Leaf::New(*this, leaf_node, key, depth + 1, row_id);
508
505
  Node::InsertChild(*this, node, key[depth], leaf_node);
509
- IncreaseMemorySize(leaf_node->MemorySize(*this, false));
510
506
  return true;
511
507
  }
512
508
 
@@ -524,11 +520,9 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
524
520
 
525
521
  // then generate the keys for the given input
526
522
  ArenaAllocator arena_allocator(BufferAllocator::Get(db));
527
- vector<Key> keys(expression.size());
523
+ vector<ARTKey> keys(expression.size());
528
524
  GenerateKeys(arena_allocator, expression, keys);
529
525
 
530
- auto old_memory_size = memory_size;
531
-
532
526
  // now erase the elements from the database
533
527
  row_ids.Flatten(input.size());
534
528
  auto row_identifiers = FlatVector::GetData<row_t>(row_ids);
@@ -537,75 +531,65 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
537
531
  if (keys[i].Empty()) {
538
532
  continue;
539
533
  }
540
- Erase(tree, keys[i], 0, row_identifiers[i]);
534
+ Erase(*tree, keys[i], 0, row_identifiers[i]);
541
535
  #ifdef DEBUG
542
- auto node = Lookup(tree, keys[i], 0);
543
- if (node) {
544
- auto leaf = (Leaf *)node;
545
- for (idx_t k = 0; k < leaf->count; k++) {
546
- D_ASSERT(leaf->GetRowId(k) != row_identifiers[i]);
536
+ auto node = Lookup(*tree, keys[i], 0);
537
+ if (node.IsSet()) {
538
+ auto &leaf = Leaf::Get(*this, node);
539
+ for (idx_t k = 0; k < leaf.count; k++) {
540
+ D_ASSERT(leaf.GetRowId(*this, k) != row_identifiers[i]);
547
541
  }
548
542
  }
549
543
  #endif
550
544
  }
551
-
552
- // if we deserialize nodes while erasing, then we might end up with more
553
- // memory afterwards, so we have to either increase or decrease the used memory
554
- Verify();
555
- if (track_memory && old_memory_size >= memory_size) {
556
- buffer_manager.DecreaseUsedMemory(old_memory_size - memory_size);
557
- } else if (track_memory) {
558
- buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
559
- }
560
545
  }
561
546
 
562
- void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
547
+ void ART::Erase(Node &node, const ARTKey &key, idx_t depth, const row_t &row_id) {
563
548
 
564
- if (!node) {
549
+ if (!node.IsSet()) {
565
550
  return;
566
551
  }
567
552
 
568
- // delete a leaf from a tree
569
- if (node->type == NodeType::NLeaf) {
570
- auto leaf = (Leaf *)node;
571
- leaf->Remove(*this, row_id);
553
+ // delete a row ID from a leaf
554
+ if (node.DecodeARTNodeType() == NType::LEAF) {
555
+ auto &leaf = Leaf::Get(*this, node);
556
+ leaf.Remove(*this, row_id);
572
557
 
573
- if (leaf->count == 0) {
574
- DecreaseMemorySize(leaf->MemorySize(*this, false));
575
- Node::Delete(node);
576
- node = nullptr;
558
+ if (leaf.count == 0) {
559
+ Node::Free(*this, node);
560
+ node.Reset();
577
561
  }
578
562
  return;
579
563
  }
580
564
 
581
565
  // handle prefix
582
- if (node->prefix.Size()) {
583
- if (node->prefix.KeyMismatchPosition(key, depth) != node->prefix.Size()) {
566
+ auto &node_prefix = node.GetPrefix(*this);
567
+ if (node_prefix.count) {
568
+ if (node_prefix.KeyMismatchPosition(*this, key, depth) != node_prefix.count) {
584
569
  return;
585
570
  }
586
- depth += node->prefix.Size();
571
+ depth += node_prefix.count;
587
572
  }
588
573
 
589
- idx_t pos = node->GetChildPos(key[depth]);
590
- if (pos != DConstants::INVALID_INDEX) {
591
- auto child = node->GetChild(*this, pos);
592
- D_ASSERT(child);
574
+ auto child = node.GetChild(*this, key[depth]);
575
+ if (child) {
576
+ D_ASSERT(child->IsSet());
593
577
 
594
- if (child->type == NodeType::NLeaf) {
578
+ if (child->DecodeARTNodeType() == NType::LEAF) {
595
579
  // leaf found, remove entry
596
- auto leaf = (Leaf *)child;
597
- leaf->Remove(*this, row_id);
580
+ auto &leaf = Leaf::Get(*this, *child);
581
+ leaf.Remove(*this, row_id);
598
582
 
599
- if (leaf->count == 0) {
583
+ if (leaf.count == 0) {
600
584
  // leaf is empty, delete leaf, decrement node counter and maybe shrink node
601
- Node::EraseChild(*this, node, pos);
585
+ Node::DeleteChild(*this, node, key[depth]);
602
586
  }
603
-
604
- } else {
605
- // recurse
606
- Erase(child, key, depth + 1, row_id);
607
- node->ReplaceChildPointer(pos, child);
587
+ return;
608
588
  }
589
+
590
+ // recurse
591
+ Erase(*child, key, depth + 1, row_id);
592
+ node.ReplaceChild(*this, key[depth], *child);
609
593
  }
610
594
  }
611
595
 
@@ -613,116 +597,114 @@ void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
613
597
  // Point Query (Equal)
614
598
  //===--------------------------------------------------------------------===//
615
599
 
616
- static Key CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value) {
600
+ static ARTKey CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value) {
617
601
  D_ASSERT(type == value.type().InternalType());
618
602
  switch (type) {
619
603
  case PhysicalType::BOOL:
620
- return Key::CreateKey<bool>(allocator, value.type(), value);
604
+ return ARTKey::CreateARTKey<bool>(allocator, value.type(), value);
621
605
  case PhysicalType::INT8:
622
- return Key::CreateKey<int8_t>(allocator, value.type(), value);
606
+ return ARTKey::CreateARTKey<int8_t>(allocator, value.type(), value);
623
607
  case PhysicalType::INT16:
624
- return Key::CreateKey<int16_t>(allocator, value.type(), value);
608
+ return ARTKey::CreateARTKey<int16_t>(allocator, value.type(), value);
625
609
  case PhysicalType::INT32:
626
- return Key::CreateKey<int32_t>(allocator, value.type(), value);
610
+ return ARTKey::CreateARTKey<int32_t>(allocator, value.type(), value);
627
611
  case PhysicalType::INT64:
628
- return Key::CreateKey<int64_t>(allocator, value.type(), value);
612
+ return ARTKey::CreateARTKey<int64_t>(allocator, value.type(), value);
629
613
  case PhysicalType::UINT8:
630
- return Key::CreateKey<uint8_t>(allocator, value.type(), value);
614
+ return ARTKey::CreateARTKey<uint8_t>(allocator, value.type(), value);
631
615
  case PhysicalType::UINT16:
632
- return Key::CreateKey<uint16_t>(allocator, value.type(), value);
616
+ return ARTKey::CreateARTKey<uint16_t>(allocator, value.type(), value);
633
617
  case PhysicalType::UINT32:
634
- return Key::CreateKey<uint32_t>(allocator, value.type(), value);
618
+ return ARTKey::CreateARTKey<uint32_t>(allocator, value.type(), value);
635
619
  case PhysicalType::UINT64:
636
- return Key::CreateKey<uint64_t>(allocator, value.type(), value);
620
+ return ARTKey::CreateARTKey<uint64_t>(allocator, value.type(), value);
637
621
  case PhysicalType::INT128:
638
- return Key::CreateKey<hugeint_t>(allocator, value.type(), value);
622
+ return ARTKey::CreateARTKey<hugeint_t>(allocator, value.type(), value);
639
623
  case PhysicalType::FLOAT:
640
- return Key::CreateKey<float>(allocator, value.type(), value);
624
+ return ARTKey::CreateARTKey<float>(allocator, value.type(), value);
641
625
  case PhysicalType::DOUBLE:
642
- return Key::CreateKey<double>(allocator, value.type(), value);
626
+ return ARTKey::CreateARTKey<double>(allocator, value.type(), value);
643
627
  case PhysicalType::VARCHAR:
644
- return Key::CreateKey<string_t>(allocator, value.type(), value);
628
+ return ARTKey::CreateARTKey<string_t>(allocator, value.type(), value);
645
629
  default:
646
- throw InternalException("Invalid type for index");
630
+ throw InternalException("Invalid type for the ART key");
647
631
  }
648
632
  }
649
633
 
650
- bool ART::SearchEqual(Key &key, idx_t max_count, vector<row_t> &result_ids) {
651
-
652
- auto old_memory_size = memory_size;
653
- auto leaf = (Leaf *)(Lookup(tree, key, 0));
654
- IncreaseAndVerifyMemorySize(old_memory_size);
634
+ bool ART::SearchEqual(ARTKey &key, idx_t max_count, vector<row_t> &result_ids) {
655
635
 
656
- if (!leaf) {
636
+ auto leaf_node = Lookup(*tree, key, 0);
637
+ if (!leaf_node.IsSet()) {
657
638
  return true;
658
639
  }
659
- if (leaf->count > max_count) {
640
+
641
+ auto &leaf = Leaf::Get(*this, leaf_node);
642
+ if (leaf.count > max_count) {
660
643
  return false;
661
644
  }
662
- for (idx_t i = 0; i < leaf->count; i++) {
663
- row_t row_id = leaf->GetRowId(i);
645
+ for (idx_t i = 0; i < leaf.count; i++) {
646
+ row_t row_id = leaf.GetRowId(*this, i);
664
647
  result_ids.push_back(row_id);
665
648
  }
666
649
  return true;
667
650
  }
668
651
 
669
- void ART::SearchEqualJoinNoFetch(Key &key, idx_t &result_size) {
670
- result_size = 0;
652
+ void ART::SearchEqualJoinNoFetch(ARTKey &key, idx_t &result_size) {
671
653
 
672
654
  // we need to look for a leaf
673
- auto old_memory_size = memory_size;
674
- auto leaf = Lookup(tree, key, 0);
675
- IncreaseAndVerifyMemorySize(old_memory_size);
676
-
677
- if (!leaf) {
655
+ auto leaf_node = Lookup(*tree, key, 0);
656
+ if (!leaf_node.IsSet()) {
657
+ result_size = 0;
678
658
  return;
679
659
  }
680
- result_size = leaf->count;
660
+
661
+ auto &leaf = Leaf::Get(*this, leaf_node);
662
+ result_size = leaf.count;
681
663
  }
682
664
 
683
665
  //===--------------------------------------------------------------------===//
684
666
  // Lookup
685
667
  //===--------------------------------------------------------------------===//
686
668
 
687
- Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
669
+ Node ART::Lookup(Node node, const ARTKey &key, idx_t depth) {
688
670
 
689
- while (node) {
690
- if (node->type == NodeType::NLeaf) {
691
- auto leaf = (Leaf *)node;
692
- auto &leaf_prefix = leaf->prefix;
671
+ while (node.IsSet()) {
672
+ if (node.DecodeARTNodeType() == NType::LEAF) {
673
+ auto &leaf = Leaf::Get(*this, node);
693
674
 
694
675
  // check if leaf contains key
695
- for (idx_t i = 0; i < leaf->prefix.Size(); i++) {
696
- if (leaf_prefix[i] != key[i + depth]) {
697
- return nullptr;
676
+ for (idx_t i = 0; i < leaf.prefix.count; i++) {
677
+ if (leaf.prefix.GetByte(*this, i) != key[i + depth]) {
678
+ return Node();
698
679
  }
699
680
  }
700
- return (Leaf *)node;
681
+ return node;
701
682
  }
702
683
 
703
- if (node->prefix.Size()) {
704
- for (idx_t pos = 0; pos < node->prefix.Size(); pos++) {
705
- if (key[depth + pos] != node->prefix[pos]) {
706
- // prefix mismatch, does not contain key
707
- return nullptr;
684
+ auto &node_prefix = node.GetPrefix(*this);
685
+ if (node_prefix.count) {
686
+ for (idx_t pos = 0; pos < node_prefix.count; pos++) {
687
+ if (key[depth + pos] != node_prefix.GetByte(*this, pos)) {
688
+ // prefix mismatch, subtree of node does not contain key
689
+ return Node();
708
690
  }
709
691
  }
710
- depth += node->prefix.Size();
692
+ depth += node_prefix.count;
711
693
  }
712
694
 
713
695
  // prefix matches key, but no child at byte, does not contain key
714
- idx_t pos = node->GetChildPos(key[depth]);
715
- if (pos == DConstants::INVALID_INDEX) {
716
- return nullptr;
696
+ auto child = node.GetChild(*this, key[depth]);
697
+ if (!child) {
698
+ return Node();
717
699
  }
718
700
 
719
701
  // recurse into child
720
- node = node->GetChild(*this, pos);
721
- D_ASSERT(node);
702
+ node = *child;
703
+ D_ASSERT(node.IsSet());
722
704
  depth++;
723
705
  }
724
706
 
725
- return nullptr;
707
+ return Node();
726
708
  }
727
709
 
728
710
  //===--------------------------------------------------------------------===//
@@ -731,42 +713,37 @@ Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
731
713
  // False (Otherwise)
732
714
  //===--------------------------------------------------------------------===//
733
715
 
734
- bool ART::SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_t max_count,
716
+ bool ART::SearchGreater(ARTIndexScanState *state, ARTKey &key, bool inclusive, idx_t max_count,
735
717
  vector<row_t> &result_ids) {
736
718
 
737
- auto old_memory_size = memory_size;
738
719
  Iterator *it = &state->iterator;
739
720
 
740
721
  // greater than scan: first set the iterator to the node at which we will start our scan by finding the lowest node
741
722
  // that satisfies our requirement
742
723
  if (!it->art) {
743
724
  it->art = this;
744
- bool found = it->LowerBound(tree, key, inclusive);
745
- if (!found) {
746
- IncreaseAndVerifyMemorySize(old_memory_size);
725
+ if (!it->LowerBound(*tree, key, inclusive)) {
747
726
  return true;
748
727
  }
749
728
  }
729
+
750
730
  // after that we continue the scan; we don't need to check the bounds as any value following this value is
751
731
  // automatically bigger and hence satisfies our predicate
752
- Key empty_key = Key();
753
- auto success = it->Scan(empty_key, max_count, result_ids, false);
754
- IncreaseAndVerifyMemorySize(old_memory_size);
755
- return success;
732
+ ARTKey empty_key = ARTKey();
733
+ return it->Scan(empty_key, max_count, result_ids, false);
756
734
  }
757
735
 
758
736
  //===--------------------------------------------------------------------===//
759
737
  // Less Than
760
738
  //===--------------------------------------------------------------------===//
761
739
 
762
- bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive, idx_t max_count,
740
+ bool ART::SearchLess(ARTIndexScanState *state, ARTKey &upper_bound, bool inclusive, idx_t max_count,
763
741
  vector<row_t> &result_ids) {
764
742
 
765
- if (!tree) {
743
+ if (!tree->IsSet()) {
766
744
  return true;
767
745
  }
768
746
 
769
- auto old_memory_size = memory_size;
770
747
  Iterator *it = &state->iterator;
771
748
 
772
749
  if (!it->art) {
@@ -775,43 +752,37 @@ bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive,
775
752
  it->FindMinimum(*tree);
776
753
  // early out min value higher than upper bound query
777
754
  if (it->cur_key > upper_bound) {
778
- IncreaseAndVerifyMemorySize(old_memory_size);
779
755
  return true;
780
756
  }
781
757
  }
758
+
782
759
  // now continue the scan until we reach the upper bound
783
- auto success = it->Scan(upper_bound, max_count, result_ids, inclusive);
784
- IncreaseAndVerifyMemorySize(old_memory_size);
785
- return success;
760
+ return it->Scan(upper_bound, max_count, result_ids, inclusive);
786
761
  }
787
762
 
788
763
  //===--------------------------------------------------------------------===//
789
764
  // Closed Range Query
790
765
  //===--------------------------------------------------------------------===//
791
766
 
792
- bool ART::SearchCloseRange(ARTIndexScanState *state, Key &lower_bound, Key &upper_bound, bool left_inclusive,
767
+ bool ART::SearchCloseRange(ARTIndexScanState *state, ARTKey &lower_bound, ARTKey &upper_bound, bool left_inclusive,
793
768
  bool right_inclusive, idx_t max_count, vector<row_t> &result_ids) {
794
769
 
795
- auto old_memory_size = memory_size;
796
770
  Iterator *it = &state->iterator;
797
771
 
798
772
  // first find the first node that satisfies the left predicate
799
773
  if (!it->art) {
800
774
  it->art = this;
801
- bool found = it->LowerBound(tree, lower_bound, left_inclusive);
802
- if (!found) {
803
- IncreaseAndVerifyMemorySize(old_memory_size);
775
+ if (!it->LowerBound(*tree, lower_bound, left_inclusive)) {
804
776
  return true;
805
777
  }
806
778
  }
779
+
807
780
  // now continue the scan until we reach the upper bound
808
- auto success = it->Scan(upper_bound, max_count, result_ids, right_inclusive);
809
- IncreaseAndVerifyMemorySize(old_memory_size);
810
- return success;
781
+ return it->Scan(upper_bound, max_count, result_ids, right_inclusive);
811
782
  }
812
783
 
813
- bool ART::Scan(Transaction &transaction, DataTable &table, IndexScanState &table_state, idx_t max_count,
814
- vector<row_t> &result_ids) {
784
+ bool ART::Scan(const Transaction &transaction, const DataTable &table, IndexScanState &table_state,
785
+ const idx_t max_count, vector<row_t> &result_ids) {
815
786
 
816
787
  auto state = (ARTIndexScanState *)&table_state;
817
788
  vector<row_t> row_ids;
@@ -931,8 +902,6 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m
931
902
  // don't alter the index during constraint checking
932
903
  lock_guard<mutex> l(lock);
933
904
 
934
- auto old_memory_size = memory_size;
935
-
936
905
  // first resolve the expressions for the index
937
906
  DataChunk expression_chunk;
938
907
  expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types);
@@ -940,7 +909,7 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m
940
909
 
941
910
  // generate the keys for the given input
942
911
  ArenaAllocator arena_allocator(BufferAllocator::Get(db));
943
- vector<Key> keys(expression_chunk.size());
912
+ vector<ARTKey> keys(expression_chunk.size());
944
913
  GenerateKeys(arena_allocator, expression_chunk, keys);
945
914
 
946
915
  idx_t found_conflict = DConstants::INVALID_INDEX;
@@ -953,8 +922,8 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m
953
922
  continue;
954
923
  }
955
924
 
956
- Leaf *leaf_ptr = Lookup(tree, keys[i], 0);
957
- if (leaf_ptr == nullptr) {
925
+ auto leaf_node = Lookup(*tree, keys[i], 0);
926
+ if (!leaf_node.IsSet()) {
958
927
  if (conflict_manager.AddMiss(i)) {
959
928
  found_conflict = i;
960
929
  }
@@ -963,18 +932,17 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m
963
932
 
964
933
  // When we find a node, we need to update the 'matches' and 'row_ids'
965
934
  // NOTE: Leafs can have more than one row_id, but for UNIQUE/PRIMARY KEY they will only have one
966
- D_ASSERT(leaf_ptr->count == 1);
967
- auto row_id = leaf_ptr->GetRowId(0);
935
+ Leaf &leaf = Leaf::Get(*this, leaf_node);
936
+ D_ASSERT(leaf.count == 1);
937
+ auto row_id = leaf.GetRowId(*this, 0);
968
938
  if (conflict_manager.AddHit(i, row_id)) {
969
939
  found_conflict = i;
970
940
  }
971
941
  }
972
942
 
973
943
  conflict_manager.FinishLookup();
974
- IncreaseAndVerifyMemorySize(old_memory_size);
975
944
 
976
945
  if (found_conflict == DConstants::INVALID_INDEX) {
977
- // No conflicts detected
978
946
  return;
979
947
  }
980
948
 
@@ -988,65 +956,114 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m
988
956
  //===--------------------------------------------------------------------===//
989
957
 
990
958
  BlockPointer ART::Serialize(MetaBlockWriter &writer) {
959
+
991
960
  lock_guard<mutex> l(lock);
992
- auto old_memory_size = memory_size;
993
- if (tree) {
961
+ if (tree->IsSet()) {
994
962
  serialized_data_pointer = tree->Serialize(*this, writer);
995
963
  } else {
996
964
  serialized_data_pointer = {(block_id_t)DConstants::INVALID_INDEX, (uint32_t)DConstants::INVALID_INDEX};
997
965
  }
998
- IncreaseAndVerifyMemorySize(old_memory_size);
966
+
999
967
  return serialized_data_pointer;
1000
968
  }
1001
969
 
1002
970
  //===--------------------------------------------------------------------===//
1003
- // Merging
971
+ // Vacuum
1004
972
  //===--------------------------------------------------------------------===//
1005
- bool ART::MergeIndexes(IndexLock &state, Index &other_index) {
1006
- auto &other_art = other_index.Cast<ART>();
1007
973
 
1008
- if (!this->tree) {
1009
- IncreaseMemorySize(other_art.memory_size);
1010
- tree = other_art.tree;
1011
- other_art.tree = nullptr;
1012
- return true;
974
+ void ART::InitializeVacuum(ARTFlags &flags) {
975
+
976
+ flags.vacuum_flags.reserve(allocators.size());
977
+ for (auto &allocator : allocators) {
978
+ flags.vacuum_flags.push_back(allocator->InitializeVacuum());
1013
979
  }
980
+ }
1014
981
 
1015
- return Node::MergeARTs(this, &other_art);
982
+ void ART::FinalizeVacuum(const ARTFlags &flags) {
983
+
984
+ for (idx_t i = 0; i < allocators.size(); i++) {
985
+ if (flags.vacuum_flags[i]) {
986
+ allocators[i]->FinalizeVacuum();
987
+ }
988
+ }
989
+ }
990
+
991
+ void ART::Vacuum(IndexLock &state) {
992
+
993
+ if (!tree->IsSet()) {
994
+ for (auto &allocator : allocators) {
995
+ allocator->Reset();
996
+ }
997
+ return;
998
+ }
999
+
1000
+ // holds true, if an allocator needs a vacuum, and false otherwise
1001
+ ARTFlags flags;
1002
+ InitializeVacuum(flags);
1003
+
1004
+ // skip vacuum if no allocators require it
1005
+ auto perform_vacuum = false;
1006
+ for (const auto &vacuum_flag : flags.vacuum_flags) {
1007
+ if (vacuum_flag) {
1008
+ perform_vacuum = true;
1009
+ break;
1010
+ }
1011
+ }
1012
+ if (!perform_vacuum) {
1013
+ return;
1014
+ }
1015
+
1016
+ // traverse the allocated memory of the tree to perform a vacuum
1017
+ Node::Vacuum(*this, *tree, flags);
1018
+
1019
+ // finalize the vacuum operation
1020
+ FinalizeVacuum(flags);
1016
1021
  }
1017
1022
 
1018
1023
  //===--------------------------------------------------------------------===//
1019
- // Utility
1024
+ // Merging
1020
1025
  //===--------------------------------------------------------------------===//
1021
1026
 
1022
- string ART::ToString() {
1023
- if (tree) {
1024
- return tree->ToString(*this);
1027
+ void ART::InitializeMerge(ARTFlags &flags) {
1028
+
1029
+ flags.merge_buffer_counts.reserve(allocators.size());
1030
+ for (auto &allocator : allocators) {
1031
+ flags.merge_buffer_counts.emplace_back(allocator->buffers.size());
1025
1032
  }
1026
- return "[empty]";
1027
1033
  }
1028
1034
 
1029
- void ART::Verify() {
1030
- #ifdef DEBUG
1031
- idx_t current_mem_size = 0;
1032
- if (tree) {
1033
- current_mem_size = tree->MemorySize(*this, true);
1035
+ bool ART::MergeIndexes(IndexLock &state, Index &other_index) {
1036
+
1037
+ auto &other_art = other_index.Cast<ART>();
1038
+
1039
+ if (tree->IsSet()) {
1040
+ // fully deserialize other_index, and traverse it to increment its buffer IDs
1041
+ ARTFlags flags;
1042
+ InitializeMerge(flags);
1043
+ other_art.tree->InitializeMerge(other_art, flags);
1034
1044
  }
1035
- if (memory_size != current_mem_size) {
1036
- throw InternalException("Memory_size value (%d) does not match actual memory size (%d).", memory_size,
1037
- current_mem_size);
1045
+
1046
+ // merge the node storage
1047
+ for (idx_t i = 0; i < allocators.size(); i++) {
1048
+ allocators[i]->Merge(*other_art.allocators[i]);
1038
1049
  }
1039
- #endif
1050
+
1051
+ // merge the ARTs
1052
+ if (!tree->Merge(*this, *other_art.tree)) {
1053
+ return false;
1054
+ }
1055
+ return true;
1040
1056
  }
1041
1057
 
1042
- void ART::IncreaseAndVerifyMemorySize(idx_t old_memory_size) {
1043
- // since we lazily deserialize ART nodes, it is possible that its in-memory size
1044
- // increased during lookups
1045
- Verify();
1046
- D_ASSERT(memory_size >= old_memory_size);
1047
- if (track_memory) {
1048
- buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
1058
+ //===--------------------------------------------------------------------===//
1059
+ // Utility
1060
+ //===--------------------------------------------------------------------===//
1061
+
1062
+ string ART::ToString() {
1063
+ if (tree->IsSet()) {
1064
+ return tree->ToString(*this);
1049
1065
  }
1066
+ return "[empty]";
1050
1067
  }
1051
1068
 
1052
1069
  } // namespace duckdb