duckdb 0.8.1-dev96.0 → 0.8.2-dev1.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 (243) hide show
  1. package/binding.gyp +8 -8
  2. package/package.json +3 -1
  3. package/src/duckdb/extension/icu/icu-datepart.cpp +1 -1
  4. package/src/duckdb/extension/icu/icu-extension.cpp +1 -1
  5. package/src/duckdb/extension/icu/icu-makedate.cpp +5 -4
  6. package/src/duckdb/extension/icu/icu-strptime.cpp +1 -1
  7. package/src/duckdb/extension/icu/third_party/icu/i18n/nfsubs.cpp +0 -2
  8. package/src/duckdb/extension/json/buffered_json_reader.cpp +23 -14
  9. package/src/duckdb/extension/json/include/buffered_json_reader.hpp +6 -6
  10. package/src/duckdb/extension/json/include/json_common.hpp +12 -2
  11. package/src/duckdb/extension/json/include/json_scan.hpp +5 -2
  12. package/src/duckdb/extension/json/json_functions/json_contains.cpp +5 -0
  13. package/src/duckdb/extension/json/json_functions/json_create.cpp +10 -10
  14. package/src/duckdb/extension/json/json_functions/json_merge_patch.cpp +2 -2
  15. package/src/duckdb/extension/json/json_functions/json_serialize_sql.cpp +2 -2
  16. package/src/duckdb/extension/json/json_functions/json_structure.cpp +5 -3
  17. package/src/duckdb/extension/json/json_functions/json_transform.cpp +11 -11
  18. package/src/duckdb/extension/json/json_functions/read_json.cpp +2 -1
  19. package/src/duckdb/extension/json/json_functions.cpp +6 -3
  20. package/src/duckdb/extension/json/json_scan.cpp +43 -27
  21. package/src/duckdb/extension/parquet/column_reader.cpp +5 -1
  22. package/src/duckdb/extension/parquet/include/decode_utils.hpp +6 -0
  23. package/src/duckdb/extension/parquet/parquet-extension.cpp +26 -1
  24. package/src/duckdb/src/catalog/catalog.cpp +5 -17
  25. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +7 -1
  26. package/src/duckdb/src/catalog/catalog_entry/table_catalog_entry.cpp +121 -0
  27. package/src/duckdb/src/catalog/catalog_search_path.cpp +49 -12
  28. package/src/duckdb/src/catalog/default/default_types.cpp +9 -84
  29. package/src/duckdb/src/common/adbc/adbc.cpp +118 -12
  30. package/src/duckdb/src/common/adbc/driver_manager.cpp +0 -20
  31. package/src/duckdb/src/common/arrow/arrow_converter.cpp +11 -12
  32. package/src/duckdb/src/common/arrow/arrow_wrapper.cpp +4 -3
  33. package/src/duckdb/src/common/exception.cpp +4 -1
  34. package/src/duckdb/src/common/exception_format_value.cpp +24 -15
  35. package/src/duckdb/src/common/multi_file_reader.cpp +3 -0
  36. package/src/duckdb/src/common/random_engine.cpp +1 -1
  37. package/src/duckdb/src/common/types/row/row_data_collection_scanner.cpp +5 -4
  38. package/src/duckdb/src/common/types/row/tuple_data_scatter_gather.cpp +44 -7
  39. package/src/duckdb/src/common/types/time.cpp +2 -8
  40. package/src/duckdb/src/common/types/timestamp.cpp +37 -1
  41. package/src/duckdb/src/common/types/value.cpp +1 -0
  42. package/src/duckdb/src/common/types.cpp +4 -0
  43. package/src/duckdb/src/core_functions/aggregate/algebraic/avg.cpp +30 -33
  44. package/src/duckdb/src/core_functions/aggregate/algebraic/covar.cpp +0 -4
  45. package/src/duckdb/src/core_functions/aggregate/distributive/approx_count.cpp +30 -33
  46. package/src/duckdb/src/core_functions/aggregate/distributive/arg_min_max.cpp +52 -65
  47. package/src/duckdb/src/core_functions/aggregate/distributive/bitagg.cpp +48 -48
  48. package/src/duckdb/src/core_functions/aggregate/distributive/bitstring_agg.cpp +39 -40
  49. package/src/duckdb/src/core_functions/aggregate/distributive/bool.cpp +32 -32
  50. package/src/duckdb/src/core_functions/aggregate/distributive/entropy.cpp +34 -34
  51. package/src/duckdb/src/core_functions/aggregate/distributive/kurtosis.cpp +30 -31
  52. package/src/duckdb/src/core_functions/aggregate/distributive/minmax.cpp +88 -100
  53. package/src/duckdb/src/core_functions/aggregate/distributive/product.cpp +17 -17
  54. package/src/duckdb/src/core_functions/aggregate/distributive/skew.cpp +25 -27
  55. package/src/duckdb/src/core_functions/aggregate/distributive/string_agg.cpp +37 -38
  56. package/src/duckdb/src/core_functions/aggregate/distributive/sum.cpp +22 -22
  57. package/src/duckdb/src/core_functions/aggregate/holistic/approximate_quantile.cpp +44 -80
  58. package/src/duckdb/src/core_functions/aggregate/holistic/mode.cpp +49 -51
  59. package/src/duckdb/src/core_functions/aggregate/holistic/quantile.cpp +104 -122
  60. package/src/duckdb/src/core_functions/aggregate/holistic/reservoir_quantile.cpp +57 -93
  61. package/src/duckdb/src/core_functions/aggregate/nested/histogram.cpp +22 -23
  62. package/src/duckdb/src/core_functions/aggregate/nested/list.cpp +18 -19
  63. package/src/duckdb/src/core_functions/aggregate/regression/regr_avg.cpp +16 -18
  64. package/src/duckdb/src/core_functions/aggregate/regression/regr_intercept.cpp +22 -25
  65. package/src/duckdb/src/core_functions/aggregate/regression/regr_r2.cpp +19 -24
  66. package/src/duckdb/src/core_functions/aggregate/regression/regr_sxx_syy.cpp +18 -23
  67. package/src/duckdb/src/core_functions/aggregate/regression/regr_sxy.cpp +14 -18
  68. package/src/duckdb/src/core_functions/function_list.cpp +1 -0
  69. package/src/duckdb/src/core_functions/scalar/date/date_part.cpp +1 -1
  70. package/src/duckdb/src/core_functions/scalar/date/make_date.cpp +3 -0
  71. package/src/duckdb/src/core_functions/scalar/generic/system_functions.cpp +14 -0
  72. package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +1 -1
  73. package/src/duckdb/src/core_functions/scalar/list/list_aggregates.cpp +23 -6
  74. package/src/duckdb/src/core_functions/scalar/list/list_lambdas.cpp +1 -2
  75. package/src/duckdb/src/core_functions/scalar/map/map_concat.cpp +3 -0
  76. package/src/duckdb/src/core_functions/scalar/math/numeric.cpp +3 -3
  77. package/src/duckdb/src/execution/index/art/art.cpp +80 -7
  78. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +20 -1
  79. package/src/duckdb/src/execution/index/art/leaf.cpp +11 -11
  80. package/src/duckdb/src/execution/index/art/leaf_segment.cpp +10 -0
  81. package/src/duckdb/src/execution/index/art/node.cpp +48 -35
  82. package/src/duckdb/src/execution/index/art/node16.cpp +3 -0
  83. package/src/duckdb/src/execution/index/art/node256.cpp +1 -0
  84. package/src/duckdb/src/execution/index/art/node4.cpp +3 -0
  85. package/src/duckdb/src/execution/index/art/node48.cpp +2 -0
  86. package/src/duckdb/src/execution/index/art/prefix.cpp +2 -0
  87. package/src/duckdb/src/execution/join_hashtable.cpp +2 -0
  88. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +26 -9
  89. package/src/duckdb/src/execution/operator/helper/physical_reset.cpp +5 -2
  90. package/src/duckdb/src/execution/operator/helper/physical_set.cpp +5 -1
  91. package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +3 -6
  92. package/src/duckdb/src/execution/operator/projection/physical_tableinout_function.cpp +1 -0
  93. package/src/duckdb/src/execution/operator/projection/physical_unnest.cpp +8 -3
  94. package/src/duckdb/src/execution/operator/schema/physical_attach.cpp +0 -1
  95. package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +29 -3
  96. package/src/duckdb/src/execution/reservoir_sample.cpp +18 -4
  97. package/src/duckdb/src/function/aggregate/distributive/count.cpp +159 -21
  98. package/src/duckdb/src/function/aggregate/distributive/first.cpp +67 -74
  99. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +7 -7
  100. package/src/duckdb/src/function/cast/list_casts.cpp +2 -4
  101. package/src/duckdb/src/function/pragma/pragma_queries.cpp +33 -23
  102. package/src/duckdb/src/function/scalar/list/list_extract.cpp +1 -1
  103. package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +1 -1
  104. package/src/duckdb/src/function/scalar/string/regexp/regexp_util.cpp +6 -2
  105. package/src/duckdb/src/function/scalar/system/aggregate_export.cpp +2 -2
  106. package/src/duckdb/src/function/table/arrow.cpp +2 -2
  107. package/src/duckdb/src/function/table/checkpoint.cpp +3 -0
  108. package/src/duckdb/src/function/table/read_csv.cpp +15 -17
  109. package/src/duckdb/src/function/table/repeat.cpp +3 -0
  110. package/src/duckdb/src/function/table/repeat_row.cpp +8 -1
  111. package/src/duckdb/src/function/table/system/pragma_storage_info.cpp +4 -4
  112. package/src/duckdb/src/function/table/system/test_vector_types.cpp +81 -25
  113. package/src/duckdb/src/function/table/table_scan.cpp +2 -2
  114. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  115. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +0 -3
  116. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp +2 -0
  117. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp +11 -1
  118. package/src/duckdb/src/include/duckdb/catalog/catalog_search_path.hpp +8 -2
  119. package/src/duckdb/src/include/duckdb/catalog/default/builtin_types/types.hpp +97 -0
  120. package/src/duckdb/src/include/duckdb/common/arrow/arrow_appender.hpp +1 -1
  121. package/src/duckdb/src/include/duckdb/common/arrow/arrow_converter.hpp +2 -3
  122. package/src/duckdb/src/include/duckdb/common/arrow/arrow_options.hpp +8 -1
  123. package/src/duckdb/src/include/duckdb/common/arrow/result_arrow_wrapper.hpp +0 -1
  124. package/src/duckdb/src/include/duckdb/common/bit_utils.hpp +16 -22
  125. package/src/duckdb/src/include/duckdb/common/exception.hpp +3 -0
  126. package/src/duckdb/src/include/duckdb/common/types/time.hpp +2 -0
  127. package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +4 -14
  128. package/src/duckdb/src/include/duckdb/common/vector_operations/aggregate_executor.hpp +92 -57
  129. package/src/duckdb/src/include/duckdb/core_functions/aggregate/algebraic/corr.hpp +20 -24
  130. package/src/duckdb/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp +36 -39
  131. package/src/duckdb/src/include/duckdb/core_functions/aggregate/algebraic/stddev.hpp +57 -53
  132. package/src/duckdb/src/include/duckdb/core_functions/aggregate/regression/regr_count.hpp +8 -9
  133. package/src/duckdb/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp +16 -18
  134. package/src/duckdb/src/include/duckdb/core_functions/aggregate/sum_helpers.hpp +7 -8
  135. package/src/duckdb/src/include/duckdb/core_functions/scalar/generic_functions.hpp +9 -0
  136. package/src/duckdb/src/include/duckdb/core_functions/scalar/map_functions.hpp +2 -6
  137. package/src/duckdb/src/include/duckdb/core_functions/scalar/string_functions.hpp +16 -36
  138. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +10 -4
  139. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +3 -0
  140. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +1 -1
  141. package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +2 -0
  142. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +13 -3
  143. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +1 -0
  144. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +9 -30
  145. package/src/duckdb/src/include/duckdb/function/aggregate_state.hpp +95 -0
  146. package/src/duckdb/src/include/duckdb/function/function_serialization.hpp +4 -2
  147. package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +1 -1
  148. package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +2 -1
  149. package/src/duckdb/src/include/duckdb/function/table_function.hpp +3 -2
  150. package/src/duckdb/src/include/duckdb/main/attached_database.hpp +4 -1
  151. package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +3 -1
  152. package/src/duckdb/src/include/duckdb/main/config.hpp +5 -0
  153. package/src/duckdb/src/include/duckdb/main/database_manager.hpp +1 -0
  154. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +142 -136
  155. package/src/duckdb/src/include/duckdb/main/query_result.hpp +6 -0
  156. package/src/duckdb/src/include/duckdb/main/settings.hpp +19 -0
  157. package/src/duckdb/src/include/duckdb/optimizer/unnest_rewriter.hpp +4 -0
  158. package/src/duckdb/src/include/duckdb/parallel/meta_pipeline.hpp +12 -3
  159. package/src/duckdb/src/include/duckdb/parser/parser.hpp +2 -0
  160. package/src/duckdb/src/include/duckdb/parser/tableref/emptytableref.hpp +1 -1
  161. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +2 -2
  162. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +0 -2
  163. package/src/duckdb/src/include/duckdb/planner/bind_context.hpp +1 -1
  164. package/src/duckdb/src/include/duckdb/planner/bound_result_modifier.hpp +3 -0
  165. package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +1 -1
  166. package/src/duckdb/src/include/duckdb/planner/logical_operator.hpp +5 -0
  167. package/src/duckdb/src/include/duckdb/planner/operator/logical_copy_to_file.hpp +6 -2
  168. package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +4 -0
  169. package/src/duckdb/src/include/duckdb/planner/operator/logical_explain.hpp +5 -1
  170. package/src/duckdb/src/include/duckdb/planner/operator/logical_get.hpp +5 -1
  171. package/src/duckdb/src/include/duckdb/planner/operator/logical_pragma.hpp +6 -2
  172. package/src/duckdb/src/include/duckdb/planner/operator/logical_prepare.hpp +4 -0
  173. package/src/duckdb/src/include/duckdb/storage/compression/chimp/algorithm/byte_reader.hpp +4 -0
  174. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
  175. package/src/duckdb/src/include/duckdb/storage/in_memory_block_manager.hpp +13 -13
  176. package/src/duckdb/src/include/duckdb/storage/index.hpp +4 -2
  177. package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +0 -6
  178. package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +1 -1
  179. package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +2 -1
  180. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +2 -2
  181. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +2 -1
  182. package/src/duckdb/src/include/duckdb/storage/table/standard_column_data.hpp +2 -1
  183. package/src/duckdb/src/include/duckdb/storage/table/struct_column_data.hpp +2 -1
  184. package/src/duckdb/src/include/duckdb/storage/table_storage_info.hpp +0 -2
  185. package/src/duckdb/src/main/attached_database.cpp +8 -0
  186. package/src/duckdb/src/main/capi/arrow-c.cpp +4 -4
  187. package/src/duckdb/src/main/capi/config-c.cpp +2 -5
  188. package/src/duckdb/src/main/client_context.cpp +4 -3
  189. package/src/duckdb/src/main/config.cpp +2 -0
  190. package/src/duckdb/src/main/database.cpp +1 -0
  191. package/src/duckdb/src/main/database_manager.cpp +21 -0
  192. package/src/duckdb/src/main/query_result.cpp +6 -2
  193. package/src/duckdb/src/main/settings/settings.cpp +41 -6
  194. package/src/duckdb/src/optimizer/unnest_rewriter.cpp +27 -16
  195. package/src/duckdb/src/parallel/executor.cpp +38 -14
  196. package/src/duckdb/src/parallel/meta_pipeline.cpp +17 -3
  197. package/src/duckdb/src/parser/column_definition.cpp +5 -8
  198. package/src/duckdb/src/parser/parsed_data/create_info.cpp +0 -3
  199. package/src/duckdb/src/parser/parser.cpp +95 -35
  200. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +1 -0
  201. package/src/duckdb/src/parser/transform/expression/transform_operator.cpp +3 -0
  202. package/src/duckdb/src/parser/transform/helpers/nodetype_to_string.cpp +0 -2
  203. package/src/duckdb/src/parser/transform/statement/transform_drop.cpp +0 -3
  204. package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +3 -0
  205. package/src/duckdb/src/parser/transformer.cpp +0 -2
  206. package/src/duckdb/src/planner/bind_context.cpp +3 -4
  207. package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +0 -2
  208. package/src/duckdb/src/planner/binder/expression/bind_positional_reference_expression.cpp +8 -3
  209. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +31 -15
  210. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +0 -27
  211. package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +18 -1
  212. package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +0 -25
  213. package/src/duckdb/src/planner/binder/statement/bind_update.cpp +2 -114
  214. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +6 -1
  215. package/src/duckdb/src/planner/binder/tableref/bind_table_function.cpp +5 -0
  216. package/src/duckdb/src/planner/bound_result_modifier.cpp +14 -0
  217. package/src/duckdb/src/planner/expression/bound_aggregate_expression.cpp +6 -5
  218. package/src/duckdb/src/planner/expression/bound_default_expression.cpp +7 -1
  219. package/src/duckdb/src/planner/expression.cpp +3 -0
  220. package/src/duckdb/src/planner/expression_binder.cpp +3 -2
  221. package/src/duckdb/src/planner/operator/logical_distinct.cpp +5 -4
  222. package/src/duckdb/src/planner/operator/logical_pivot.cpp +14 -2
  223. package/src/duckdb/src/planner/planner.cpp +5 -15
  224. package/src/duckdb/src/storage/data_table.cpp +10 -8
  225. package/src/duckdb/src/storage/index.cpp +13 -0
  226. package/src/duckdb/src/storage/storage_manager.cpp +6 -0
  227. package/src/duckdb/src/storage/table/column_data.cpp +7 -3
  228. package/src/duckdb/src/storage/table/list_column_data.cpp +5 -4
  229. package/src/duckdb/src/storage/table/row_group.cpp +4 -3
  230. package/src/duckdb/src/storage/table/row_group_collection.cpp +6 -3
  231. package/src/duckdb/src/storage/table/standard_column_data.cpp +4 -3
  232. package/src/duckdb/src/storage/table/struct_column_data.cpp +4 -3
  233. package/src/duckdb/src/storage/wal_replay.cpp +4 -5
  234. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +0 -1
  235. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +0 -14
  236. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +12828 -12956
  237. package/src/duckdb/third_party/zstd/compress/zstd_compress.cpp +3 -0
  238. package/src/duckdb/third_party/zstd/include/zstd/compress/zstd_cwksp.h +4 -0
  239. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +5 -5
  240. package/src/duckdb/ub_src_parser_transform_statement.cpp +0 -2
  241. package/test/extension.test.ts +11 -0
  242. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -46
  243. package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -27
@@ -244,14 +244,13 @@ unique_ptr<GlobalTableFunctionState> JSONGlobalTableFunctionState::Init(ClientCo
244
244
 
245
245
  idx_t JSONGlobalTableFunctionState::MaxThreads() const {
246
246
  auto &bind_data = state.bind_data;
247
- if (bind_data.options.format == JSONFormat::NEWLINE_DELIMITED &&
248
- bind_data.options.compression == FileCompressionType::UNCOMPRESSED) {
247
+ if (bind_data.options.format == JSONFormat::NEWLINE_DELIMITED) {
249
248
  return state.system_threads;
250
249
  }
251
250
 
252
251
  if (!state.json_readers.empty() && state.json_readers[0]->IsOpen()) {
253
252
  auto &reader = *state.json_readers[0];
254
- if (reader.IsParallel()) { // Auto-detected parallel scan
253
+ if (reader.GetFormat() == JSONFormat::NEWLINE_DELIMITED) { // Auto-detected NDJSON
255
254
  return state.system_threads;
256
255
  }
257
256
  }
@@ -298,6 +297,7 @@ idx_t JSONScanLocalState::ReadNext(JSONScanGlobalState &gstate) {
298
297
  if (!ReadNextBuffer(gstate)) {
299
298
  return scan_count;
300
299
  }
300
+ D_ASSERT(buffer_size != 0);
301
301
  if (current_buffer_handle->buffer_index != 0 && current_reader->GetFormat() == JSONFormat::NEWLINE_DELIMITED) {
302
302
  ReconstructFirstObject(gstate);
303
303
  scan_count++;
@@ -308,8 +308,8 @@ idx_t JSONScanLocalState::ReadNext(JSONScanGlobalState &gstate) {
308
308
  return scan_count;
309
309
  }
310
310
 
311
- static inline const char *NextNewline(const char *ptr, idx_t size) {
312
- return (const char *)memchr(ptr, '\n', size);
311
+ static inline const char *NextNewline(char *ptr, idx_t size) {
312
+ return char_ptr_cast(memchr(ptr, '\n', size));
313
313
  }
314
314
 
315
315
  static inline const char *PreviousNewline(const char *ptr) {
@@ -455,7 +455,21 @@ void JSONScanLocalState::ThrowInvalidAtEndError() {
455
455
  throw InvalidInputException("Invalid JSON detected at the end of file \"%s\".", current_reader->GetFileName());
456
456
  }
457
457
 
458
- static pair<JSONFormat, JSONRecordType> DetectFormatAndRecordType(const char *const buffer_ptr, const idx_t buffer_size,
458
+ bool JSONScanLocalState::IsParallel(JSONScanGlobalState &gstate) const {
459
+ if (bind_data.files.size() >= gstate.system_threads) {
460
+ // More files than threads, just parallelize over the files
461
+ return false;
462
+ }
463
+
464
+ if (current_reader->GetFormat() == JSONFormat::NEWLINE_DELIMITED) {
465
+ // NDJSON can be read in parallel
466
+ return true;
467
+ }
468
+
469
+ return false;
470
+ }
471
+
472
+ static pair<JSONFormat, JSONRecordType> DetectFormatAndRecordType(char *const buffer_ptr, const idx_t buffer_size,
459
473
  yyjson_alc *alc) {
460
474
  // First we do the easy check whether it's NEWLINE_DELIMITED
461
475
  auto line_end = NextNewline(buffer_ptr, buffer_size);
@@ -464,7 +478,7 @@ static pair<JSONFormat, JSONRecordType> DetectFormatAndRecordType(const char *co
464
478
  SkipWhitespace(buffer_ptr, line_size, buffer_size);
465
479
 
466
480
  yyjson_read_err error;
467
- auto doc = JSONCommon::ReadDocumentUnsafe((char *)buffer_ptr, line_size, JSONCommon::READ_FLAG, alc, &error);
481
+ auto doc = JSONCommon::ReadDocumentUnsafe(buffer_ptr, line_size, JSONCommon::READ_FLAG, alc, &error);
468
482
  if (error.code == YYJSON_READ_SUCCESS) { // We successfully read the line
469
483
  if (yyjson_is_arr(doc->root) && line_size == buffer_size) {
470
484
  // It's just one array, let's actually assume ARRAY, not NEWLINE_DELIMITED
@@ -500,8 +514,8 @@ static pair<JSONFormat, JSONRecordType> DetectFormatAndRecordType(const char *co
500
514
 
501
515
  // It's definitely an ARRAY, but now we have to figure out if there's more than one top-level array
502
516
  yyjson_read_err error;
503
- auto doc = JSONCommon::ReadDocumentUnsafe((char *)buffer_ptr + buffer_offset, remaining, JSONCommon::READ_STOP_FLAG,
504
- alc, &error);
517
+ auto doc =
518
+ JSONCommon::ReadDocumentUnsafe(buffer_ptr + buffer_offset, remaining, JSONCommon::READ_STOP_FLAG, alc, &error);
505
519
  if (error.code == YYJSON_READ_SUCCESS) {
506
520
  D_ASSERT(yyjson_is_arr(doc->root));
507
521
 
@@ -563,7 +577,7 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
563
577
  } else {
564
578
  buffer = gstate.allocator.Allocate(gstate.buffer_capacity);
565
579
  }
566
- buffer_ptr = (const char *)buffer.get();
580
+ buffer_ptr = char_ptr_cast(buffer.get());
567
581
 
568
582
  idx_t buffer_index;
569
583
  while (true) {
@@ -573,7 +587,7 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
573
587
  if (is_last && gstate.bind_data.type != JSONScanType::SAMPLE) {
574
588
  current_reader->CloseJSONFile();
575
589
  }
576
- if (current_reader->IsParallel()) {
590
+ if (IsParallel(gstate)) {
577
591
  // If this threads' current reader is still the one at gstate.file_index,
578
592
  // this thread can end the parallel scan
579
593
  lock_guard<mutex> guard(gstate.lock);
@@ -599,7 +613,7 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
599
613
  current_reader = gstate.json_readers[gstate.file_index].get();
600
614
  if (current_reader->IsOpen()) {
601
615
  // Can only be open from auto detection, so these should be known
602
- if (!current_reader->IsParallel()) {
616
+ if (!IsParallel(gstate)) {
603
617
  batch_index = gstate.batch_index++;
604
618
  gstate.file_index++;
605
619
  }
@@ -609,15 +623,15 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
609
623
  current_reader->OpenJSONFile();
610
624
  batch_index = gstate.batch_index++;
611
625
  if (current_reader->GetFormat() != JSONFormat::AUTO_DETECT) {
612
- if (!current_reader->IsParallel()) {
626
+ if (!IsParallel(gstate)) {
613
627
  gstate.file_index++;
614
628
  }
615
629
  continue;
616
630
  }
617
631
 
618
- // If we have a low amount of files, we auto-detect within the lock,
632
+ // If we have less files than threads, we auto-detect within the lock,
619
633
  // so other threads may join a parallel NDJSON scan
620
- if (gstate.json_readers.size() < 100) {
634
+ if (gstate.json_readers.size() < gstate.system_threads) {
621
635
  if (ReadAndAutoDetect(gstate, buffer_index, false)) {
622
636
  continue;
623
637
  }
@@ -637,7 +651,7 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
637
651
  D_ASSERT(buffer_size != 0); // We should have read something if we got here
638
652
 
639
653
  idx_t readers = 1;
640
- if (current_reader->IsParallel()) {
654
+ if (current_reader->GetFormat() == JSONFormat::NEWLINE_DELIMITED) {
641
655
  readers = is_last ? 1 : 2;
642
656
  }
643
657
 
@@ -650,7 +664,7 @@ bool JSONScanLocalState::ReadNextBuffer(JSONScanGlobalState &gstate) {
650
664
  lines_or_objects_in_buffer = 0;
651
665
 
652
666
  // YYJSON needs this
653
- memset((void *)(buffer_ptr + buffer_size), 0, YYJSON_PADDING_SIZE);
667
+ memset(buffer_ptr + buffer_size, 0, YYJSON_PADDING_SIZE);
654
668
 
655
669
  return true;
656
670
  }
@@ -680,7 +694,7 @@ bool JSONScanLocalState::ReadAndAutoDetect(JSONScanGlobalState &gstate, idx_t &b
680
694
  throw InvalidInputException("Expected file \"%s\" to contain records, detected non-record JSON instead.",
681
695
  current_reader->GetFileName());
682
696
  }
683
- if (!already_incremented_file_idx && !current_reader->IsParallel()) {
697
+ if (!already_incremented_file_idx && !IsParallel(gstate)) {
684
698
  gstate.file_index++;
685
699
  }
686
700
  return false;
@@ -739,13 +753,14 @@ void JSONScanLocalState::ReadNextBufferNoSeek(JSONScanGlobalState &gstate, idx_t
739
753
  lock_guard<mutex> reader_guard(current_reader->lock);
740
754
  buffer_index = current_reader->GetBufferIndex();
741
755
 
742
- if (current_reader->IsOpen()) {
756
+ if (current_reader->IsOpen() && !current_reader->IsDone()) {
743
757
  read_size = current_reader->GetFileHandle().Read(buffer_ptr + prev_buffer_remainder, request_size,
744
758
  gstate.bind_data.type == JSONScanType::SAMPLE);
759
+ is_last = read_size < request_size;
745
760
  } else {
746
761
  read_size = 0;
762
+ is_last = false;
747
763
  }
748
- is_last = read_size < request_size;
749
764
 
750
765
  if (!gstate.bind_data.ignore_errors && read_size == 0 && prev_buffer_remainder != 0) {
751
766
  ThrowInvalidAtEndError();
@@ -796,13 +811,13 @@ void JSONScanLocalState::ReconstructFirstObject(JSONScanGlobalState &gstate) {
796
811
  D_ASSERT(current_reader->GetFormat() == JSONFormat::NEWLINE_DELIMITED);
797
812
 
798
813
  // Spinlock until the previous batch index has also read its buffer
799
- JSONBufferHandle *previous_buffer_handle = nullptr;
814
+ optional_ptr<JSONBufferHandle> previous_buffer_handle;
800
815
  while (!previous_buffer_handle) {
801
816
  previous_buffer_handle = current_reader->GetBuffer(current_buffer_handle->buffer_index - 1);
802
817
  }
803
818
 
804
819
  // First we find the newline in the previous block
805
- auto prev_buffer_ptr = (const char *)previous_buffer_handle->buffer.get() + previous_buffer_handle->buffer_size;
820
+ auto prev_buffer_ptr = char_ptr_cast(previous_buffer_handle->buffer.get()) + previous_buffer_handle->buffer_size;
806
821
  auto part1_ptr = PreviousNewline(prev_buffer_ptr);
807
822
  auto part1_size = prev_buffer_ptr - part1_ptr;
808
823
 
@@ -825,7 +840,7 @@ void JSONScanLocalState::ReconstructFirstObject(JSONScanGlobalState &gstate) {
825
840
 
826
841
  // And copy the remainder of the line to the reconstruct buffer
827
842
  memcpy(reconstruct_ptr + part1_size, buffer_ptr, part2_size);
828
- memset((void *)(reconstruct_ptr + line_size), 0, YYJSON_PADDING_SIZE);
843
+ memset(reconstruct_ptr + line_size, 0, YYJSON_PADDING_SIZE);
829
844
  buffer_offset += part2_size;
830
845
 
831
846
  // We copied the object, so we are no longer reading the previous buffer
@@ -833,7 +848,7 @@ void JSONScanLocalState::ReconstructFirstObject(JSONScanGlobalState &gstate) {
833
848
  current_reader->RemoveBuffer(current_buffer_handle->buffer_index - 1);
834
849
  }
835
850
 
836
- ParseJSON((char *)reconstruct_ptr, line_size, line_size);
851
+ ParseJSON(char_ptr_cast(reconstruct_ptr), line_size, line_size);
837
852
  }
838
853
 
839
854
  void JSONScanLocalState::ParseNextChunk() {
@@ -867,7 +882,7 @@ void JSONScanLocalState::ParseNextChunk() {
867
882
  }
868
883
 
869
884
  idx_t json_size = json_end - json_start;
870
- ParseJSON((char *)json_start, json_size, remaining);
885
+ ParseJSON(json_start, json_size, remaining);
871
886
  buffer_offset += json_size;
872
887
 
873
888
  if (format == JSONFormat::ARRAY) {
@@ -947,9 +962,10 @@ void JSONScan::Serialize(FieldWriter &writer, const FunctionData *bind_data_p, c
947
962
  bind_data.Serialize(writer);
948
963
  }
949
964
 
950
- unique_ptr<FunctionData> JSONScan::Deserialize(ClientContext &context, FieldReader &reader, TableFunction &function) {
965
+ unique_ptr<FunctionData> JSONScan::Deserialize(PlanDeserializationState &state, FieldReader &reader,
966
+ TableFunction &function) {
951
967
  auto result = make_uniq<JSONScanData>();
952
- result->Deserialize(context, reader);
968
+ result->Deserialize(state.context, reader);
953
969
  return std::move(result);
954
970
  }
955
971
 
@@ -95,7 +95,11 @@ const uint64_t ParquetDecodeUtils::BITPACK_MASKS[] = {0,
95
95
  576460752303423487,
96
96
  1152921504606846975,
97
97
  2305843009213693951,
98
- 4611686018427387903};
98
+ 4611686018427387903,
99
+ 9223372036854775807,
100
+ 18446744073709551615ULL};
101
+
102
+ const uint64_t ParquetDecodeUtils::BITPACK_MASKS_SIZE = sizeof(ParquetDecodeUtils::BITPACK_MASKS) / sizeof(uint64_t);
99
103
 
100
104
  const uint8_t ParquetDecodeUtils::BITPACK_DLEN = 8;
101
105
 
@@ -12,10 +12,16 @@ public:
12
12
  }
13
13
 
14
14
  static const uint64_t BITPACK_MASKS[];
15
+ static const uint64_t BITPACK_MASKS_SIZE;
15
16
  static const uint8_t BITPACK_DLEN;
16
17
 
17
18
  template <typename T>
18
19
  static uint32_t BitUnpack(ByteBuffer &buffer, uint8_t &bitpack_pos, T *dest, uint32_t count, uint8_t width) {
20
+ if (width >= ParquetDecodeUtils::BITPACK_MASKS_SIZE) {
21
+ throw InvalidInputException("The width (%d) of the bitpacked data exceeds the supported max width (%d), "
22
+ "the file might be corrupted.",
23
+ width, ParquetDecodeUtils::BITPACK_MASKS_SIZE);
24
+ }
19
25
  auto mask = BITPACK_MASKS[width];
20
26
 
21
27
  for (uint32_t i = 0; i < count; i++) {
@@ -411,8 +411,9 @@ public:
411
411
  bind_data.parquet_options.Serialize(writer);
412
412
  }
413
413
 
414
- static unique_ptr<FunctionData> ParquetScanDeserialize(ClientContext &context, FieldReader &reader,
414
+ static unique_ptr<FunctionData> ParquetScanDeserialize(PlanDeserializationState &state, FieldReader &reader,
415
415
  TableFunction &function) {
416
+ auto &context = state.context;
416
417
  auto files = reader.ReadRequiredList<string>();
417
418
  auto types = reader.ReadRequiredSerializableList<LogicalType, LogicalType>();
418
419
  auto names = reader.ReadRequiredList<string>();
@@ -665,6 +666,28 @@ unique_ptr<LocalFunctionData> ParquetWriteInitializeLocal(ExecutionContext &cont
665
666
  return make_uniq<ParquetWriteLocalState>(context.client, bind_data.sql_types);
666
667
  }
667
668
 
669
+ // LCOV_EXCL_START
670
+ static void ParquetCopySerialize(FieldWriter &writer, const FunctionData &bind_data_p, const CopyFunction &function) {
671
+ auto &bind_data = bind_data_p.Cast<ParquetWriteBindData>();
672
+ writer.WriteRegularSerializableList<LogicalType>(bind_data.sql_types);
673
+ writer.WriteList<string>(bind_data.column_names);
674
+ writer.WriteField<duckdb_parquet::format::CompressionCodec::type>(bind_data.codec);
675
+ writer.WriteField<idx_t>(bind_data.row_group_size);
676
+ }
677
+
678
+ static unique_ptr<FunctionData> ParquetCopyDeserialize(ClientContext &context, FieldReader &reader,
679
+ CopyFunction &function) {
680
+ unique_ptr<ParquetWriteBindData> data = make_uniq<ParquetWriteBindData>();
681
+
682
+ data->sql_types = reader.ReadRequiredSerializableList<LogicalType, LogicalType>();
683
+ data->column_names = reader.ReadRequiredList<string>();
684
+ data->codec = reader.ReadRequired<duckdb_parquet::format::CompressionCodec::type>();
685
+ data->row_group_size = reader.ReadRequired<idx_t>();
686
+
687
+ return std::move(data);
688
+ }
689
+ // LCOV_EXCL_STOP
690
+
668
691
  //===--------------------------------------------------------------------===//
669
692
  // Execution Mode
670
693
  //===--------------------------------------------------------------------===//
@@ -764,6 +787,8 @@ void ParquetExtension::Load(DuckDB &db) {
764
787
  function.prepare_batch = ParquetWritePrepareBatch;
765
788
  function.flush_batch = ParquetWriteFlushBatch;
766
789
  function.desired_batch_size = ParquetWriteDesiredBatchSize;
790
+ function.serialize = ParquetCopySerialize;
791
+ function.deserialize = ParquetCopyDeserialize;
767
792
 
768
793
  function.extension = "parquet";
769
794
  ExtensionUtil::RegisterFunction(db_instance, function);
@@ -674,31 +674,19 @@ vector<reference<SchemaCatalogEntry>> Catalog::GetSchemas(ClientContext &context
674
674
  return schemas;
675
675
  }
676
676
 
677
- bool Catalog::TypeExists(ClientContext &context, const string &catalog_name, const string &schema, const string &name) {
678
- optional_ptr<CatalogEntry> entry;
679
- entry = GetEntry(context, CatalogType::TYPE_ENTRY, catalog_name, schema, name, OnEntryNotFound::RETURN_NULL);
680
- if (!entry) {
681
- // look in the system catalog
682
- entry = GetEntry(context, CatalogType::TYPE_ENTRY, SYSTEM_CATALOG, schema, name, OnEntryNotFound::RETURN_NULL);
683
- if (!entry) {
684
- return false;
685
- }
686
- }
687
- return true;
688
- }
689
-
690
677
  vector<reference<SchemaCatalogEntry>> Catalog::GetSchemas(ClientContext &context, const string &catalog_name) {
691
678
  vector<reference<Catalog>> catalogs;
692
679
  if (IsInvalidCatalog(catalog_name)) {
693
- unordered_set<string> name;
680
+ reference_set_t<Catalog> inserted_catalogs;
694
681
 
695
682
  auto &search_path = *context.client_data->catalog_search_path;
696
683
  for (auto &entry : search_path.Get()) {
697
- if (name.find(entry.catalog) != name.end()) {
684
+ auto &catalog = Catalog::GetCatalog(context, entry.catalog);
685
+ if (inserted_catalogs.find(catalog) != inserted_catalogs.end()) {
698
686
  continue;
699
687
  }
700
- name.insert(entry.catalog);
701
- catalogs.push_back(Catalog::GetCatalog(context, entry.catalog));
688
+ inserted_catalogs.insert(catalog);
689
+ catalogs.push_back(catalog);
702
690
  }
703
691
  } else {
704
692
  catalogs.push_back(Catalog::GetCatalog(context, catalog_name));
@@ -16,6 +16,9 @@
16
16
  #include "duckdb/parser/constraints/list.hpp"
17
17
  #include "duckdb/function/table/table_scan.hpp"
18
18
  #include "duckdb/storage/table_storage_info.hpp"
19
+ #include "duckdb/planner/operator/logical_get.hpp"
20
+ #include "duckdb/planner/operator/logical_projection.hpp"
21
+ #include "duckdb/planner/operator/logical_update.hpp"
19
22
 
20
23
  namespace duckdb {
21
24
 
@@ -714,10 +717,13 @@ TableFunction DuckTableEntry::GetScanFunction(ClientContext &context, unique_ptr
714
717
  return TableScanFunction::GetFunction();
715
718
  }
716
719
 
720
+ vector<ColumnSegmentInfo> DuckTableEntry::GetColumnSegmentInfo() {
721
+ return storage->GetColumnSegmentInfo();
722
+ }
723
+
717
724
  TableStorageInfo DuckTableEntry::GetStorageInfo(ClientContext &context) {
718
725
  TableStorageInfo result;
719
726
  result.cardinality = storage->info->cardinality.load();
720
- storage->GetStorageInfo(result);
721
727
  storage->info->indexes.Scan([&](Index &index) {
722
728
  IndexInfo info;
723
729
  info.is_primary = index.IsPrimary();
@@ -9,6 +9,11 @@
9
9
  #include "duckdb/main/database.hpp"
10
10
  #include "duckdb/parser/constraints/list.hpp"
11
11
  #include "duckdb/parser/parsed_data/create_table_info.hpp"
12
+ #include "duckdb/storage/table_storage_info.hpp"
13
+ #include "duckdb/planner/operator/logical_update.hpp"
14
+ #include "duckdb/planner/operator/logical_get.hpp"
15
+ #include "duckdb/planner/constraints/bound_check_constraint.hpp"
16
+ #include "duckdb/planner/operator/logical_projection.hpp"
12
17
 
13
18
  #include <sstream>
14
19
 
@@ -214,6 +219,122 @@ DataTable &TableCatalogEntry::GetStorage() {
214
219
  const vector<unique_ptr<BoundConstraint>> &TableCatalogEntry::GetBoundConstraints() {
215
220
  throw InternalException("Calling GetBoundConstraints on a TableCatalogEntry that is not a DuckTableEntry");
216
221
  }
222
+
217
223
  // LCOV_EXCL_STOP
218
224
 
225
+ static void BindExtraColumns(TableCatalogEntry &table, LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update,
226
+ physical_index_set_t &bound_columns) {
227
+ if (bound_columns.size() <= 1) {
228
+ return;
229
+ }
230
+ idx_t found_column_count = 0;
231
+ physical_index_set_t found_columns;
232
+ for (idx_t i = 0; i < update.columns.size(); i++) {
233
+ if (bound_columns.find(update.columns[i]) != bound_columns.end()) {
234
+ // this column is referenced in the CHECK constraint
235
+ found_column_count++;
236
+ found_columns.insert(update.columns[i]);
237
+ }
238
+ }
239
+ if (found_column_count > 0 && found_column_count != bound_columns.size()) {
240
+ // columns in this CHECK constraint were referenced, but not all were part of the UPDATE
241
+ // add them to the scan and update set
242
+ for (auto &check_column_id : bound_columns) {
243
+ if (found_columns.find(check_column_id) != found_columns.end()) {
244
+ // column is already projected
245
+ continue;
246
+ }
247
+ // column is not projected yet: project it by adding the clause "i=i" to the set of updated columns
248
+ auto &column = table.GetColumns().GetColumn(check_column_id);
249
+ update.expressions.push_back(make_uniq<BoundColumnRefExpression>(
250
+ column.Type(), ColumnBinding(proj.table_index, proj.expressions.size())));
251
+ proj.expressions.push_back(make_uniq<BoundColumnRefExpression>(
252
+ column.Type(), ColumnBinding(get.table_index, get.column_ids.size())));
253
+ get.column_ids.push_back(check_column_id.index);
254
+ update.columns.push_back(check_column_id);
255
+ }
256
+ }
257
+ }
258
+
259
+ static bool TypeSupportsRegularUpdate(const LogicalType &type) {
260
+ switch (type.id()) {
261
+ case LogicalTypeId::LIST:
262
+ case LogicalTypeId::MAP:
263
+ case LogicalTypeId::UNION:
264
+ // lists and maps and unions don't support updates directly
265
+ return false;
266
+ case LogicalTypeId::STRUCT: {
267
+ auto &child_types = StructType::GetChildTypes(type);
268
+ for (auto &entry : child_types) {
269
+ if (!TypeSupportsRegularUpdate(entry.second)) {
270
+ return false;
271
+ }
272
+ }
273
+ return true;
274
+ }
275
+ default:
276
+ return true;
277
+ }
278
+ }
279
+
280
+ vector<ColumnSegmentInfo> TableCatalogEntry::GetColumnSegmentInfo() {
281
+ return {};
282
+ }
283
+
284
+ void TableCatalogEntry::BindUpdateConstraints(LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update,
285
+ ClientContext &context) {
286
+ // check the constraints and indexes of the table to see if we need to project any additional columns
287
+ // we do this for indexes with multiple columns and CHECK constraints in the UPDATE clause
288
+ // suppose we have a constraint CHECK(i + j < 10); now we need both i and j to check the constraint
289
+ // if we are only updating one of the two columns we add the other one to the UPDATE set
290
+ // with a "useless" update (i.e. i=i) so we can verify that the CHECK constraint is not violated
291
+ for (auto &constraint : GetBoundConstraints()) {
292
+ if (constraint->type == ConstraintType::CHECK) {
293
+ auto &check = constraint->Cast<BoundCheckConstraint>();
294
+ // check constraint! check if we need to add any extra columns to the UPDATE clause
295
+ BindExtraColumns(*this, get, proj, update, check.bound_columns);
296
+ }
297
+ }
298
+ if (update.return_chunk) {
299
+ physical_index_set_t all_columns;
300
+ for (auto &column : GetColumns().Physical()) {
301
+ all_columns.insert(column.Physical());
302
+ }
303
+ BindExtraColumns(*this, get, proj, update, all_columns);
304
+ }
305
+ // for index updates we always turn any update into an insert and a delete
306
+ // we thus need all the columns to be available, hence we check if the update touches any index columns
307
+ // If the returning keyword is used, we need access to the whole row in case the user requests it.
308
+ // Therefore switch the update to a delete and insert.
309
+ update.update_is_del_and_insert = false;
310
+ TableStorageInfo table_storage_info = GetStorageInfo(context);
311
+ for (auto index : table_storage_info.index_info) {
312
+ for (auto &column : update.columns) {
313
+ if (index.column_set.find(column.index) != index.column_set.end()) {
314
+ update.update_is_del_and_insert = true;
315
+ break;
316
+ }
317
+ }
318
+ };
319
+
320
+ // we also convert any updates on LIST columns into delete + insert
321
+ for (auto &col_index : update.columns) {
322
+ auto &column = GetColumns().GetColumn(col_index);
323
+ if (!TypeSupportsRegularUpdate(column.Type())) {
324
+ update.update_is_del_and_insert = true;
325
+ break;
326
+ }
327
+ }
328
+
329
+ if (update.update_is_del_and_insert) {
330
+ // the update updates a column required by an index or requires returning the updated rows,
331
+ // push projections for all columns
332
+ physical_index_set_t all_columns;
333
+ for (auto &column : GetColumns().Physical()) {
334
+ all_columns.insert(column.Physical());
335
+ }
336
+ BindExtraColumns(*this, get, proj, update, all_columns);
337
+ }
338
+ }
339
+
219
340
  } // namespace duckdb
@@ -5,6 +5,7 @@
5
5
  #include "duckdb/common/string_util.hpp"
6
6
  #include "duckdb/main/client_context.hpp"
7
7
  #include "duckdb/catalog/catalog.hpp"
8
+ #include "duckdb/main/database_manager.hpp"
8
9
 
9
10
  namespace duckdb {
10
11
 
@@ -126,37 +127,57 @@ void CatalogSearchPath::Reset() {
126
127
  SetPaths(empty);
127
128
  }
128
129
 
129
- void CatalogSearchPath::Set(vector<CatalogSearchEntry> new_paths, bool is_set_schema) {
130
- if (is_set_schema && new_paths.size() != 1) {
131
- throw CatalogException("SET schema can set only 1 schema. This has %d", new_paths.size());
130
+ string CatalogSearchPath::GetSetName(CatalogSetPathType set_type) {
131
+ switch (set_type) {
132
+ case CatalogSetPathType::SET_SCHEMA:
133
+ return "SET schema";
134
+ case CatalogSetPathType::SET_SCHEMAS:
135
+ return "SET search_path";
136
+ default:
137
+ throw InternalException("Unrecognized CatalogSetPathType");
138
+ }
139
+ }
140
+
141
+ void CatalogSearchPath::Set(vector<CatalogSearchEntry> new_paths, CatalogSetPathType set_type) {
142
+ if (set_type != CatalogSetPathType::SET_SCHEMAS && new_paths.size() != 1) {
143
+ throw CatalogException("%s can set only 1 schema. This has %d", GetSetName(set_type), new_paths.size());
132
144
  }
133
145
  for (auto &path : new_paths) {
134
- if (!Catalog::GetSchema(context, path.catalog, path.schema, OnEntryNotFound::RETURN_NULL)) {
146
+ auto schema_entry = Catalog::GetSchema(context, path.catalog, path.schema, OnEntryNotFound::RETURN_NULL);
147
+ if (schema_entry) {
148
+ // we are setting a schema - update the catalog and schema
135
149
  if (path.catalog.empty()) {
136
- // only schema supplied - check if this is a database instead
137
- auto schema = Catalog::GetSchema(context, path.schema, DEFAULT_SCHEMA, OnEntryNotFound::RETURN_NULL);
150
+ path.catalog = GetDefault().catalog;
151
+ }
152
+ continue;
153
+ }
154
+ // only schema supplied - check if this is a catalog instead
155
+ if (path.catalog.empty()) {
156
+ auto catalog = Catalog::GetCatalogEntry(context, path.schema);
157
+ if (catalog) {
158
+ auto schema = catalog->GetSchema(context, DEFAULT_SCHEMA, OnEntryNotFound::RETURN_NULL);
138
159
  if (schema) {
139
160
  path.catalog = std::move(path.schema);
140
161
  path.schema = schema->name;
141
162
  continue;
142
163
  }
143
164
  }
144
- throw CatalogException("SET %s: No catalog + schema named %s found.",
145
- is_set_schema ? "schema" : "search_path", path.ToString());
146
165
  }
166
+ throw CatalogException("%s: No catalog + schema named \"%s\" found.", GetSetName(set_type), path.ToString());
147
167
  }
148
- if (is_set_schema) {
168
+ if (set_type == CatalogSetPathType::SET_SCHEMA) {
149
169
  if (new_paths[0].catalog == TEMP_CATALOG || new_paths[0].catalog == SYSTEM_CATALOG) {
150
- throw CatalogException("SET schema cannot be set to internal schema \"%s\"", new_paths[0].catalog);
170
+ throw CatalogException("%s cannot be set to internal schema \"%s\"", GetSetName(set_type),
171
+ new_paths[0].catalog);
151
172
  }
152
173
  }
153
174
  this->set_paths = std::move(new_paths);
154
175
  SetPaths(set_paths);
155
176
  }
156
177
 
157
- void CatalogSearchPath::Set(CatalogSearchEntry new_value, bool is_set_schema) {
178
+ void CatalogSearchPath::Set(CatalogSearchEntry new_value, CatalogSetPathType set_type) {
158
179
  vector<CatalogSearchEntry> new_paths {std::move(new_value)};
159
- Set(std::move(new_paths), is_set_schema);
180
+ Set(std::move(new_paths), set_type);
160
181
  }
161
182
 
162
183
  const vector<CatalogSearchEntry> &CatalogSearchPath::Get() {
@@ -225,4 +246,20 @@ void CatalogSearchPath::SetPaths(vector<CatalogSearchEntry> new_paths) {
225
246
  paths.emplace_back(SYSTEM_CATALOG, "pg_catalog");
226
247
  }
227
248
 
249
+ bool CatalogSearchPath::SchemaInSearchPath(ClientContext &context, const string &catalog_name,
250
+ const string &schema_name) {
251
+ for (auto &path : paths) {
252
+ if (path.schema != schema_name) {
253
+ continue;
254
+ }
255
+ if (path.catalog == catalog_name) {
256
+ return true;
257
+ }
258
+ if (IsInvalidCatalog(path.catalog) && catalog_name == DatabaseManager::GetDefaultDatabase(context)) {
259
+ return true;
260
+ }
261
+ }
262
+ return false;
263
+ }
264
+
228
265
  } // namespace duckdb