duckdb 0.8.2-dev11.0 → 0.8.2-dev1212.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 (396) hide show
  1. package/binding.gyp +14 -12
  2. package/binding.gyp.in +1 -1
  3. package/configure.py +1 -1
  4. package/duckdb_extension_config.cmake +10 -0
  5. package/lib/duckdb.d.ts +59 -0
  6. package/lib/duckdb.js +21 -0
  7. package/package.json +1 -1
  8. package/src/duckdb/extension/icu/icu-dateadd.cpp +2 -2
  9. package/src/duckdb/extension/icu/icu-datefunc.cpp +1 -1
  10. package/src/duckdb/extension/icu/icu-datepart.cpp +2 -2
  11. package/src/duckdb/extension/icu/icu-datesub.cpp +2 -2
  12. package/src/duckdb/extension/icu/icu-datetrunc.cpp +1 -1
  13. package/src/duckdb/extension/icu/icu-list-range.cpp +1 -1
  14. package/src/duckdb/extension/icu/icu-makedate.cpp +7 -0
  15. package/src/duckdb/extension/icu/icu-strptime.cpp +4 -4
  16. package/src/duckdb/extension/icu/icu-table-range.cpp +5 -5
  17. package/src/duckdb/extension/icu/icu-timebucket.cpp +16 -16
  18. package/src/duckdb/extension/icu/icu-timezone.cpp +8 -8
  19. package/src/duckdb/extension/icu/icu_extension.cpp +5 -7
  20. package/src/duckdb/extension/json/include/json_common.hpp +47 -231
  21. package/src/duckdb/extension/json/include/json_executors.hpp +49 -13
  22. package/src/duckdb/extension/json/include/json_functions.hpp +2 -1
  23. package/src/duckdb/extension/json/json_common.cpp +272 -40
  24. package/src/duckdb/extension/json/json_functions/json_structure.cpp +1 -1
  25. package/src/duckdb/extension/json/json_functions/json_transform.cpp +17 -37
  26. package/src/duckdb/extension/json/json_functions/json_type.cpp +1 -1
  27. package/src/duckdb/extension/json/json_functions.cpp +24 -24
  28. package/src/duckdb/extension/json/json_scan.cpp +3 -6
  29. package/src/duckdb/extension/parquet/column_reader.cpp +19 -21
  30. package/src/duckdb/extension/parquet/column_writer.cpp +77 -61
  31. package/src/duckdb/extension/parquet/include/cast_column_reader.hpp +2 -2
  32. package/src/duckdb/extension/parquet/include/column_reader.hpp +14 -16
  33. package/src/duckdb/extension/parquet/include/column_writer.hpp +9 -7
  34. package/src/duckdb/extension/parquet/include/list_column_reader.hpp +2 -2
  35. package/src/duckdb/extension/parquet/include/parquet_dbp_decoder.hpp +3 -3
  36. package/src/duckdb/extension/parquet/include/parquet_decimal_utils.hpp +3 -3
  37. package/src/duckdb/extension/parquet/include/parquet_file_metadata_cache.hpp +2 -2
  38. package/src/duckdb/extension/parquet/include/parquet_statistics.hpp +2 -2
  39. package/src/duckdb/extension/parquet/include/parquet_support.hpp +9 -11
  40. package/src/duckdb/extension/parquet/include/parquet_writer.hpp +24 -5
  41. package/src/duckdb/extension/parquet/include/string_column_reader.hpp +1 -1
  42. package/src/duckdb/extension/parquet/include/struct_column_reader.hpp +2 -3
  43. package/src/duckdb/extension/parquet/include/zstd_file_system.hpp +2 -2
  44. package/src/duckdb/extension/parquet/parquet_extension.cpp +191 -19
  45. package/src/duckdb/extension/parquet/parquet_reader.cpp +6 -6
  46. package/src/duckdb/extension/parquet/parquet_statistics.cpp +7 -6
  47. package/src/duckdb/extension/parquet/parquet_writer.cpp +79 -16
  48. package/src/duckdb/extension/parquet/zstd_file_system.cpp +2 -2
  49. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +1 -1
  50. package/src/duckdb/src/catalog/default/default_functions.cpp +16 -0
  51. package/src/duckdb/src/common/adbc/adbc.cpp +75 -10
  52. package/src/duckdb/src/common/adbc/driver_manager.cpp +6 -11
  53. package/src/duckdb/src/common/allocator.cpp +14 -2
  54. package/src/duckdb/src/common/arrow/arrow_appender.cpp +5 -11
  55. package/src/duckdb/src/common/arrow/arrow_wrapper.cpp +0 -12
  56. package/src/duckdb/src/common/assert.cpp +3 -0
  57. package/src/duckdb/src/common/enum_util.cpp +42 -5
  58. package/src/duckdb/src/common/enums/logical_operator_type.cpp +4 -0
  59. package/src/duckdb/src/common/enums/optimizer_type.cpp +2 -0
  60. package/src/duckdb/src/common/enums/physical_operator_type.cpp +4 -0
  61. package/src/duckdb/src/common/exception.cpp +2 -2
  62. package/src/duckdb/src/common/file_system.cpp +15 -0
  63. package/src/duckdb/src/common/local_file_system.cpp +2 -2
  64. package/src/duckdb/src/common/multi_file_reader.cpp +181 -18
  65. package/src/duckdb/src/common/radix_partitioning.cpp +27 -9
  66. package/src/duckdb/src/common/re2_regex.cpp +1 -1
  67. package/src/duckdb/src/common/row_operations/row_external.cpp +1 -1
  68. package/src/duckdb/src/common/sort/merge_sorter.cpp +9 -16
  69. package/src/duckdb/src/common/sort/partition_state.cpp +44 -11
  70. package/src/duckdb/src/common/types/batched_data_collection.cpp +7 -2
  71. package/src/duckdb/src/common/types/column/column_data_allocator.cpp +9 -6
  72. package/src/duckdb/src/common/types/column/column_data_collection.cpp +17 -2
  73. package/src/duckdb/src/common/types/column/column_data_collection_segment.cpp +15 -6
  74. package/src/duckdb/src/common/types/column/partitioned_column_data.cpp +2 -2
  75. package/src/duckdb/src/common/types/data_chunk.cpp +2 -2
  76. package/src/duckdb/src/common/types/date.cpp +9 -0
  77. package/src/duckdb/src/common/types/list_segment.cpp +24 -74
  78. package/src/duckdb/src/common/types/row/partitioned_tuple_data.cpp +3 -9
  79. package/src/duckdb/src/common/types/row/tuple_data_collection.cpp +2 -0
  80. package/src/duckdb/src/common/types/row/tuple_data_scatter_gather.cpp +2 -2
  81. package/src/duckdb/src/common/types/uuid.cpp +2 -2
  82. package/src/duckdb/src/common/types/validity_mask.cpp +33 -0
  83. package/src/duckdb/src/common/types/vector.cpp +15 -14
  84. package/src/duckdb/src/common/vector_operations/is_distinct_from.cpp +6 -4
  85. package/src/duckdb/src/core_functions/aggregate/holistic/reservoir_quantile.cpp +2 -0
  86. package/src/duckdb/src/core_functions/aggregate/nested/list.cpp +2 -2
  87. package/src/duckdb/src/core_functions/aggregate/regression/regr_avg.cpp +4 -4
  88. package/src/duckdb/src/core_functions/aggregate/regression/regr_intercept.cpp +4 -4
  89. package/src/duckdb/src/core_functions/aggregate/regression/regr_r2.cpp +5 -4
  90. package/src/duckdb/src/core_functions/aggregate/regression/regr_sxx_syy.cpp +8 -8
  91. package/src/duckdb/src/core_functions/aggregate/regression/regr_sxy.cpp +4 -3
  92. package/src/duckdb/src/core_functions/function_list.cpp +4 -2
  93. package/src/duckdb/src/core_functions/scalar/date/date_part.cpp +208 -42
  94. package/src/duckdb/src/core_functions/scalar/date/epoch.cpp +0 -17
  95. package/src/duckdb/src/core_functions/scalar/date/make_date.cpp +19 -4
  96. package/src/duckdb/src/core_functions/scalar/list/list_aggregates.cpp +4 -2
  97. package/src/duckdb/src/execution/aggregate_hashtable.cpp +34 -18
  98. package/src/duckdb/src/execution/expression_executor.cpp +1 -1
  99. package/src/duckdb/src/execution/index/art/art.cpp +149 -139
  100. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +1 -1
  101. package/src/duckdb/src/execution/index/art/iterator.cpp +129 -207
  102. package/src/duckdb/src/execution/index/art/leaf.cpp +8 -37
  103. package/src/duckdb/src/execution/index/art/node.cpp +113 -120
  104. package/src/duckdb/src/execution/index/art/node16.cpp +1 -10
  105. package/src/duckdb/src/execution/index/art/node256.cpp +1 -9
  106. package/src/duckdb/src/execution/index/art/node4.cpp +12 -13
  107. package/src/duckdb/src/execution/index/art/node48.cpp +1 -11
  108. package/src/duckdb/src/execution/index/art/prefix.cpp +228 -350
  109. package/src/duckdb/src/execution/join_hashtable.cpp +4 -4
  110. package/src/duckdb/src/execution/operator/aggregate/aggregate_object.cpp +1 -0
  111. package/src/duckdb/src/execution/operator/aggregate/physical_streaming_window.cpp +8 -3
  112. package/src/duckdb/src/execution/operator/aggregate/physical_ungrouped_aggregate.cpp +32 -22
  113. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +512 -300
  114. package/src/duckdb/src/execution/operator/helper/physical_batch_collector.cpp +4 -3
  115. package/src/duckdb/src/execution/operator/helper/physical_limit.cpp +5 -5
  116. package/src/duckdb/src/execution/operator/join/physical_asof_join.cpp +414 -283
  117. package/src/duckdb/src/execution/operator/join/physical_comparison_join.cpp +1 -1
  118. package/src/duckdb/src/execution/operator/join/physical_hash_join.cpp +21 -10
  119. package/src/duckdb/src/execution/operator/join/physical_join.cpp +1 -1
  120. package/src/duckdb/src/execution/operator/join/physical_piecewise_merge_join.cpp +22 -3
  121. package/src/duckdb/src/execution/operator/join/physical_range_join.cpp +2 -2
  122. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +100 -13
  123. package/src/duckdb/src/execution/operator/persistent/csv_file_handle.cpp +1 -1
  124. package/src/duckdb/src/execution/operator/persistent/csv_reader_options.cpp +20 -0
  125. package/src/duckdb/src/execution/operator/persistent/csv_rejects_table.cpp +48 -0
  126. package/src/duckdb/src/execution/operator/persistent/parallel_csv_reader.cpp +2 -3
  127. package/src/duckdb/src/execution/operator/persistent/physical_batch_copy_to_file.cpp +6 -4
  128. package/src/duckdb/src/execution/operator/persistent/physical_batch_insert.cpp +3 -2
  129. package/src/duckdb/src/execution/operator/persistent/physical_fixed_batch_copy.cpp +3 -3
  130. package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +1 -1
  131. package/src/duckdb/src/execution/operator/projection/physical_pivot.cpp +2 -1
  132. package/src/duckdb/src/execution/operator/scan/physical_column_data_scan.cpp +19 -0
  133. package/src/duckdb/src/execution/operator/set/physical_cte.cpp +160 -0
  134. package/src/duckdb/src/execution/operator/set/physical_recursive_cte.cpp +15 -5
  135. package/src/duckdb/src/execution/partitionable_hashtable.cpp +41 -6
  136. package/src/duckdb/src/execution/perfect_aggregate_hashtable.cpp +30 -5
  137. package/src/duckdb/src/execution/physical_operator.cpp +17 -14
  138. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +43 -10
  139. package/src/duckdb/src/execution/physical_plan/plan_cte.cpp +33 -0
  140. package/src/duckdb/src/execution/physical_plan/plan_recursive_cte.cpp +25 -4
  141. package/src/duckdb/src/execution/physical_plan_generator.cpp +4 -0
  142. package/src/duckdb/src/execution/radix_partitioned_hashtable.cpp +290 -43
  143. package/src/duckdb/src/execution/window_segment_tree.cpp +286 -129
  144. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +2 -1
  145. package/src/duckdb/src/function/function.cpp +3 -1
  146. package/src/duckdb/src/function/scalar/compressed_materialization/compress_integral.cpp +212 -0
  147. package/src/duckdb/src/function/scalar/compressed_materialization/compress_string.cpp +249 -0
  148. package/src/duckdb/src/function/scalar/compressed_materialization_functions.cpp +29 -0
  149. package/src/duckdb/src/function/scalar/list/list_resize.cpp +162 -0
  150. package/src/duckdb/src/function/scalar/nested_functions.cpp +1 -0
  151. package/src/duckdb/src/function/scalar/string/like.cpp +12 -4
  152. package/src/duckdb/src/function/scalar/system/aggregate_export.cpp +12 -5
  153. package/src/duckdb/src/function/table/copy_csv.cpp +8 -1
  154. package/src/duckdb/src/function/table/read_csv.cpp +100 -17
  155. package/src/duckdb/src/function/table/system/test_all_types.cpp +38 -18
  156. package/src/duckdb/src/function/table/table_scan.cpp +9 -0
  157. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  158. package/src/duckdb/src/include/duckdb/common/adbc/adbc.hpp +1 -0
  159. package/src/duckdb/src/include/duckdb/common/allocator.hpp +2 -0
  160. package/src/duckdb/src/include/duckdb/common/bswap.hpp +42 -0
  161. package/src/duckdb/src/include/duckdb/common/enum_util.hpp +8 -0
  162. package/src/duckdb/src/include/duckdb/common/enums/cte_materialize.hpp +21 -0
  163. package/src/duckdb/src/include/duckdb/common/enums/joinref_type.hpp +2 -1
  164. package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +2 -0
  165. package/src/duckdb/src/include/duckdb/common/enums/optimizer_type.hpp +2 -0
  166. package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +2 -0
  167. package/src/duckdb/src/include/duckdb/common/multi_file_reader.hpp +6 -4
  168. package/src/duckdb/src/include/duckdb/common/multi_file_reader_options.hpp +10 -42
  169. package/src/duckdb/src/include/duckdb/common/mutex.hpp +3 -0
  170. package/src/duckdb/src/include/duckdb/common/radix.hpp +9 -20
  171. package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +6 -21
  172. package/src/duckdb/src/include/duckdb/common/row_operations/row_operations.hpp +3 -3
  173. package/src/duckdb/src/include/duckdb/common/sort/partition_state.hpp +13 -0
  174. package/src/duckdb/src/include/duckdb/common/types/batched_data_collection.hpp +3 -1
  175. package/src/duckdb/src/include/duckdb/common/types/column/column_data_allocator.hpp +1 -1
  176. package/src/duckdb/src/include/duckdb/common/types/column/column_data_collection.hpp +6 -1
  177. package/src/duckdb/src/include/duckdb/common/types/column/column_data_collection_segment.hpp +1 -1
  178. package/src/duckdb/src/include/duckdb/common/types/column/column_data_scan_states.hpp +3 -1
  179. package/src/duckdb/src/include/duckdb/common/types/data_chunk.hpp +1 -1
  180. package/src/duckdb/src/include/duckdb/common/types/date.hpp +7 -5
  181. package/src/duckdb/src/include/duckdb/common/types/list_segment.hpp +6 -8
  182. package/src/duckdb/src/include/duckdb/common/types/row/partitioned_tuple_data.hpp +0 -1
  183. package/src/duckdb/src/include/duckdb/common/types/row/tuple_data_collection.hpp +1 -0
  184. package/src/duckdb/src/include/duckdb/common/types/row/tuple_data_states.hpp +3 -0
  185. package/src/duckdb/src/include/duckdb/common/types/string_type.hpp +9 -0
  186. package/src/duckdb/src/include/duckdb/core_functions/aggregate/algebraic/corr.hpp +4 -4
  187. package/src/duckdb/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp +3 -1
  188. package/src/duckdb/src/include/duckdb/core_functions/aggregate/regression/regr_count.hpp +1 -0
  189. package/src/duckdb/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp +3 -3
  190. package/src/duckdb/src/include/duckdb/core_functions/scalar/date_functions.hpp +24 -6
  191. package/src/duckdb/src/include/duckdb/execution/aggregate_hashtable.hpp +21 -3
  192. package/src/duckdb/src/include/duckdb/execution/executor.hpp +3 -0
  193. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +4 -5
  194. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +31 -27
  195. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +6 -14
  196. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +4 -10
  197. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +3 -6
  198. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +3 -6
  199. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +5 -8
  200. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +3 -6
  201. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +63 -52
  202. package/src/duckdb/src/include/duckdb/execution/operator/join/physical_asof_join.hpp +2 -10
  203. package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +2 -2
  204. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_line_info.hpp +4 -3
  205. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +8 -1
  206. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_rejects_table.hpp +36 -0
  207. package/src/duckdb/src/include/duckdb/execution/operator/persistent/parallel_csv_reader.hpp +1 -1
  208. package/src/duckdb/src/include/duckdb/execution/operator/scan/physical_column_data_scan.hpp +10 -0
  209. package/src/duckdb/src/include/duckdb/execution/operator/set/physical_cte.hpp +62 -0
  210. package/src/duckdb/src/include/duckdb/execution/operator/set/physical_recursive_cte.hpp +8 -2
  211. package/src/duckdb/src/include/duckdb/execution/partitionable_hashtable.hpp +5 -1
  212. package/src/duckdb/src/include/duckdb/execution/physical_operator.hpp +3 -0
  213. package/src/duckdb/src/include/duckdb/execution/physical_plan_generator.hpp +3 -0
  214. package/src/duckdb/src/include/duckdb/execution/radix_partitioned_hashtable.hpp +10 -3
  215. package/src/duckdb/src/include/duckdb/execution/window_segment_tree.hpp +51 -40
  216. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +1 -1
  217. package/src/duckdb/src/include/duckdb/function/aggregate_state.hpp +2 -2
  218. package/src/duckdb/src/include/duckdb/function/built_in_functions.hpp +1 -0
  219. package/src/duckdb/src/include/duckdb/function/scalar/compressed_materialization_functions.hpp +49 -0
  220. package/src/duckdb/src/include/duckdb/function/scalar/list/contains_or_position.hpp +1 -1
  221. package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +5 -0
  222. package/src/duckdb/src/include/duckdb/function/scalar/string_functions.hpp +2 -0
  223. package/src/duckdb/src/include/duckdb/function/table/system_functions.hpp +1 -1
  224. package/src/duckdb/src/include/duckdb/main/client_config.hpp +3 -0
  225. package/src/duckdb/src/include/duckdb/main/config.hpp +2 -0
  226. package/src/duckdb/src/include/duckdb/main/connection.hpp +1 -2
  227. package/src/duckdb/src/include/duckdb/main/settings.hpp +21 -1
  228. package/src/duckdb/src/include/duckdb/optimizer/column_binding_replacer.hpp +47 -0
  229. package/src/duckdb/src/include/duckdb/optimizer/compressed_materialization.hpp +132 -0
  230. package/src/duckdb/src/include/duckdb/optimizer/deliminator.hpp +13 -16
  231. package/src/duckdb/src/include/duckdb/optimizer/filter_pushdown.hpp +3 -0
  232. package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +1 -1
  233. package/src/duckdb/src/include/duckdb/optimizer/join_order/estimated_properties.hpp +10 -1
  234. package/src/duckdb/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp +1 -1
  235. package/src/duckdb/src/include/duckdb/optimizer/join_order/join_relation.hpp +1 -1
  236. package/src/duckdb/src/include/duckdb/optimizer/join_order/query_graph.hpp +3 -0
  237. package/src/duckdb/src/include/duckdb/optimizer/matcher/set_matcher.hpp +13 -0
  238. package/src/duckdb/src/include/duckdb/optimizer/optimizer.hpp +3 -0
  239. package/src/duckdb/src/include/duckdb/optimizer/remove_duplicate_groups.hpp +40 -0
  240. package/src/duckdb/src/include/duckdb/optimizer/statistics_propagator.hpp +11 -3
  241. package/src/duckdb/src/include/duckdb/optimizer/topn_optimizer.hpp +2 -0
  242. package/src/duckdb/src/include/duckdb/parallel/pipeline.hpp +2 -0
  243. package/src/duckdb/src/include/duckdb/parallel/task_scheduler.hpp +5 -0
  244. package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
  245. package/src/duckdb/src/include/duckdb/parser/query_node/cte_node.hpp +54 -0
  246. package/src/duckdb/src/include/duckdb/parser/query_node/list.hpp +1 -0
  247. package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
  248. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
  249. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +15 -8
  250. package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -5
  251. package/src/duckdb/src/include/duckdb/planner/bound_tokens.hpp +1 -0
  252. package/src/duckdb/src/include/duckdb/planner/column_binding.hpp +4 -0
  253. package/src/duckdb/src/include/duckdb/planner/constraints/bound_unique_constraint.hpp +3 -3
  254. package/src/duckdb/src/include/duckdb/planner/expression_binder/lateral_binder.hpp +0 -2
  255. package/src/duckdb/src/include/duckdb/planner/logical_tokens.hpp +1 -0
  256. package/src/duckdb/src/include/duckdb/planner/operator/list.hpp +2 -1
  257. package/src/duckdb/src/include/duckdb/planner/operator/logical_comparison_join.hpp +5 -5
  258. package/src/duckdb/src/include/duckdb/planner/operator/logical_cteref.hpp +7 -2
  259. package/src/duckdb/src/include/duckdb/planner/operator/logical_dependent_join.hpp +43 -0
  260. package/src/duckdb/src/include/duckdb/planner/operator/logical_materialized_cte.hpp +49 -0
  261. package/src/duckdb/src/include/duckdb/planner/operator/logical_recursive_cte.hpp +5 -4
  262. package/src/duckdb/src/include/duckdb/planner/query_node/bound_cte_node.hpp +44 -0
  263. package/src/duckdb/src/include/duckdb/planner/query_node/list.hpp +1 -0
  264. package/src/duckdb/src/include/duckdb/planner/subquery/flatten_dependent_join.hpp +2 -2
  265. package/src/duckdb/src/include/duckdb/planner/subquery/has_correlated_expressions.hpp +4 -1
  266. package/src/duckdb/src/include/duckdb/planner/subquery/recursive_dependent_join_planner.hpp +31 -0
  267. package/src/duckdb/src/include/duckdb/planner/subquery/rewrite_correlated_expressions.hpp +8 -2
  268. package/src/duckdb/src/include/duckdb/planner/tableref/bound_cteref.hpp +5 -2
  269. package/src/duckdb/src/include/duckdb/storage/arena_allocator.hpp +1 -1
  270. package/src/duckdb/src/include/duckdb/storage/block_manager.hpp +3 -3
  271. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
  272. package/src/duckdb/src/include/duckdb/storage/object_cache.hpp +22 -0
  273. package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +2 -0
  274. package/src/duckdb/src/include/duckdb/storage/statistics/string_stats.hpp +4 -0
  275. package/src/duckdb/src/include/duckdb/storage/table/chunk_info.hpp +3 -0
  276. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +3 -2
  277. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +1 -3
  278. package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +2 -3
  279. package/src/duckdb/src/include/duckdb.h +28 -0
  280. package/src/duckdb/src/main/capi/arrow-c.cpp +155 -1
  281. package/src/duckdb/src/main/capi/duckdb_value-c.cpp +1 -1
  282. package/src/duckdb/src/main/config.cpp +2 -0
  283. package/src/duckdb/src/main/database.cpp +1 -1
  284. package/src/duckdb/src/main/extension/extension_helper.cpp +96 -89
  285. package/src/duckdb/src/main/settings/settings.cpp +40 -18
  286. package/src/duckdb/src/optimizer/column_binding_replacer.cpp +43 -0
  287. package/src/duckdb/src/optimizer/column_lifetime_analyzer.cpp +1 -2
  288. package/src/duckdb/src/optimizer/compressed_materialization/compress_aggregate.cpp +140 -0
  289. package/src/duckdb/src/optimizer/compressed_materialization/compress_distinct.cpp +42 -0
  290. package/src/duckdb/src/optimizer/compressed_materialization/compress_order.cpp +65 -0
  291. package/src/duckdb/src/optimizer/compressed_materialization.cpp +478 -0
  292. package/src/duckdb/src/optimizer/deliminator.cpp +176 -321
  293. package/src/duckdb/src/optimizer/filter_pushdown.cpp +9 -0
  294. package/src/duckdb/src/optimizer/join_order/estimated_properties.cpp +7 -0
  295. package/src/duckdb/src/optimizer/join_order/join_node.cpp +2 -2
  296. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +113 -82
  297. package/src/duckdb/src/optimizer/join_order/join_relation_set.cpp +2 -6
  298. package/src/duckdb/src/optimizer/join_order/query_graph.cpp +22 -14
  299. package/src/duckdb/src/optimizer/optimizer.cpp +51 -14
  300. package/src/duckdb/src/optimizer/pushdown/pushdown_cross_product.cpp +5 -5
  301. package/src/duckdb/src/optimizer/pushdown/pushdown_get.cpp +0 -1
  302. package/src/duckdb/src/optimizer/remove_duplicate_groups.cpp +127 -0
  303. package/src/duckdb/src/optimizer/remove_unused_columns.cpp +4 -0
  304. package/src/duckdb/src/optimizer/rule/regex_optimizations.cpp +154 -15
  305. package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +65 -8
  306. package/src/duckdb/src/optimizer/statistics/operator/propagate_order.cpp +1 -1
  307. package/src/duckdb/src/optimizer/statistics_propagator.cpp +7 -5
  308. package/src/duckdb/src/optimizer/topn_optimizer.cpp +20 -10
  309. package/src/duckdb/src/parallel/executor.cpp +15 -0
  310. package/src/duckdb/src/parallel/pipeline_executor.cpp +7 -6
  311. package/src/duckdb/src/parallel/task_scheduler.cpp +11 -2
  312. package/src/duckdb/src/parser/common_table_expression_info.cpp +2 -0
  313. package/src/duckdb/src/parser/expression/lambda_expression.cpp +1 -1
  314. package/src/duckdb/src/parser/parsed_expression_iterator.cpp +7 -0
  315. package/src/duckdb/src/parser/query_node/cte_node.cpp +75 -0
  316. package/src/duckdb/src/parser/query_node.cpp +18 -1
  317. package/src/duckdb/src/parser/tableref/joinref.cpp +3 -0
  318. package/src/duckdb/src/parser/transform/expression/transform_constant.cpp +55 -3
  319. package/src/duckdb/src/parser/transform/expression/transform_expression.cpp +2 -0
  320. package/src/duckdb/src/parser/transform/expression/transform_multi_assign_reference.cpp +44 -0
  321. package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +19 -1
  322. package/src/duckdb/src/parser/transform/statement/transform_copy.cpp +13 -0
  323. package/src/duckdb/src/parser/transform/statement/transform_delete.cpp +6 -1
  324. package/src/duckdb/src/parser/transform/statement/transform_insert.cpp +6 -1
  325. package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +7 -2
  326. package/src/duckdb/src/parser/transform/statement/transform_pragma.cpp +14 -11
  327. package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +11 -2
  328. package/src/duckdb/src/parser/transform/statement/transform_update.cpp +6 -1
  329. package/src/duckdb/src/parser/transformer.cpp +15 -0
  330. package/src/duckdb/src/planner/binder/query_node/bind_cte_node.cpp +64 -0
  331. package/src/duckdb/src/planner/binder/query_node/plan_cte_node.cpp +26 -0
  332. package/src/duckdb/src/planner/binder/query_node/plan_recursive_cte_node.cpp +5 -5
  333. package/src/duckdb/src/planner/binder/query_node/plan_setop.cpp +4 -4
  334. package/src/duckdb/src/planner/binder/query_node/plan_subquery.cpp +32 -29
  335. package/src/duckdb/src/planner/binder/tableref/bind_basetableref.cpp +11 -2
  336. package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +32 -5
  337. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +116 -50
  338. package/src/duckdb/src/planner/binder/tableref/plan_cteref.cpp +1 -1
  339. package/src/duckdb/src/planner/binder/tableref/plan_joinref.cpp +61 -26
  340. package/src/duckdb/src/planner/binder/tableref/plan_subqueryref.cpp +3 -3
  341. package/src/duckdb/src/planner/binder.cpp +5 -0
  342. package/src/duckdb/src/planner/expression/bound_aggregate_expression.cpp +1 -1
  343. package/src/duckdb/src/planner/expression_binder/lateral_binder.cpp +4 -31
  344. package/src/duckdb/src/planner/expression_binder.cpp +3 -0
  345. package/src/duckdb/src/planner/expression_iterator.cpp +6 -0
  346. package/src/duckdb/src/planner/logical_operator.cpp +5 -0
  347. package/src/duckdb/src/planner/logical_operator_visitor.cpp +2 -0
  348. package/src/duckdb/src/planner/operator/logical_cteref.cpp +3 -1
  349. package/src/duckdb/src/planner/operator/logical_dependent_join.cpp +26 -0
  350. package/src/duckdb/src/planner/operator/logical_materialized_cte.cpp +21 -0
  351. package/src/duckdb/src/planner/subquery/flatten_dependent_join.cpp +90 -38
  352. package/src/duckdb/src/planner/subquery/has_correlated_expressions.cpp +22 -7
  353. package/src/duckdb/src/planner/subquery/rewrite_correlated_expressions.cpp +65 -7
  354. package/src/duckdb/src/storage/arena_allocator.cpp +1 -2
  355. package/src/duckdb/src/storage/buffer/block_manager.cpp +3 -0
  356. package/src/duckdb/src/storage/checkpoint_manager.cpp +3 -0
  357. package/src/duckdb/src/storage/compression/rle.cpp +0 -1
  358. package/src/duckdb/src/storage/data_table.cpp +1 -1
  359. package/src/duckdb/src/storage/local_storage.cpp +3 -3
  360. package/src/duckdb/src/storage/single_file_block_manager.cpp +23 -0
  361. package/src/duckdb/src/storage/statistics/string_stats.cpp +21 -2
  362. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  363. package/src/duckdb/src/storage/storage_manager.cpp +7 -2
  364. package/src/duckdb/src/storage/table/chunk_info.cpp +17 -0
  365. package/src/duckdb/src/storage/table/row_group.cpp +25 -9
  366. package/src/duckdb/src/storage/table/row_group_collection.cpp +19 -18
  367. package/src/duckdb/third_party/concurrentqueue/concurrentqueue.h +2 -2
  368. package/src/duckdb/third_party/concurrentqueue/lightweightsemaphore.h +76 -0
  369. package/src/duckdb/third_party/fast_float/fast_float/fast_float.h +2 -0
  370. package/src/duckdb/third_party/httplib/httplib.hpp +10 -1
  371. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +9 -0
  372. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +2 -1
  373. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +12487 -12331
  374. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +6 -6
  375. package/src/duckdb/ub_src_execution_index_art.cpp +0 -2
  376. package/src/duckdb/ub_src_execution_operator_persistent.cpp +2 -0
  377. package/src/duckdb/ub_src_execution_operator_set.cpp +2 -0
  378. package/src/duckdb/ub_src_execution_physical_plan.cpp +2 -0
  379. package/src/duckdb/ub_src_function_scalar.cpp +2 -0
  380. package/src/duckdb/ub_src_function_scalar_compressed_materialization.cpp +4 -0
  381. package/src/duckdb/ub_src_function_scalar_list.cpp +2 -0
  382. package/src/duckdb/ub_src_optimizer.cpp +6 -0
  383. package/src/duckdb/ub_src_optimizer_compressed_materialization.cpp +6 -0
  384. package/src/duckdb/ub_src_optimizer_statistics_expression.cpp +0 -2
  385. package/src/duckdb/ub_src_parser_query_node.cpp +2 -0
  386. package/src/duckdb/ub_src_parser_transform_expression.cpp +2 -0
  387. package/src/duckdb/ub_src_planner_binder_query_node.cpp +4 -0
  388. package/src/duckdb/ub_src_planner_operator.cpp +4 -0
  389. package/src/duckdb_node.hpp +1 -0
  390. package/src/statement.cpp +104 -4
  391. package/test/columns.test.ts +243 -0
  392. package/test/test_all_types.test.ts +233 -0
  393. package/tsconfig.json +1 -0
  394. package/src/duckdb/src/execution/index/art/prefix_segment.cpp +0 -42
  395. package/src/duckdb/src/include/duckdb/execution/index/art/prefix_segment.hpp +0 -40
  396. package/src/duckdb/src/optimizer/statistics/expression/propagate_and_compress.cpp +0 -118
@@ -14,6 +14,10 @@
14
14
  #include "duckdb/planner/operator/logical_window.hpp"
15
15
  #include "duckdb/function/function_binder.hpp"
16
16
  #include "duckdb/planner/subquery/flatten_dependent_join.hpp"
17
+ #include "duckdb/common/enums/logical_operator_type.hpp"
18
+ #include "duckdb/planner/operator/logical_dependent_join.hpp"
19
+ #include "duckdb/planner/expression_binder/lateral_binder.hpp"
20
+ #include "duckdb/planner/subquery/recursive_dependent_join_planner.hpp"
17
21
 
18
22
  namespace duckdb {
19
23
 
@@ -327,43 +331,43 @@ static unique_ptr<Expression> PlanCorrelatedSubquery(Binder &binder, BoundSubque
327
331
  }
328
332
  }
329
333
 
330
- class RecursiveSubqueryPlanner : public LogicalOperatorVisitor {
331
- public:
332
- explicit RecursiveSubqueryPlanner(Binder &binder) : binder(binder) {
333
- }
334
- void VisitOperator(LogicalOperator &op) override {
335
- if (!op.children.empty()) {
336
- root = std::move(op.children[0]);
337
- D_ASSERT(root);
338
- VisitOperatorExpressions(op);
339
- op.children[0] = std::move(root);
340
- for (idx_t i = 0; i < op.children.size(); i++) {
341
- D_ASSERT(op.children[i]);
342
- VisitOperator(*op.children[i]);
343
- }
334
+ void RecursiveDependentJoinPlanner::VisitOperator(LogicalOperator &op) {
335
+ if (!op.children.empty()) {
336
+ root = std::move(op.children[0]);
337
+ D_ASSERT(root);
338
+ if (root->type == LogicalOperatorType::LOGICAL_DEPENDENT_JOIN) {
339
+ // Found a dependent join, flatten it
340
+ auto &new_root = root->Cast<LogicalDependentJoin>();
341
+ root = binder.PlanLateralJoin(std::move(new_root.children[0]), std::move(new_root.children[1]),
342
+ new_root.correlated_columns, new_root.join_type,
343
+ std::move(new_root.join_condition));
344
+ }
345
+ VisitOperatorExpressions(op);
346
+ op.children[0] = std::move(root);
347
+ for (idx_t i = 0; i < op.children.size(); i++) {
348
+ D_ASSERT(op.children[i]);
349
+ VisitOperator(*op.children[i]);
344
350
  }
345
351
  }
352
+ }
346
353
 
347
- unique_ptr<Expression> VisitReplace(BoundSubqueryExpression &expr, unique_ptr<Expression> *expr_ptr) override {
348
- return binder.PlanSubquery(expr, root);
349
- }
350
-
351
- private:
352
- unique_ptr<LogicalOperator> root;
353
- Binder &binder;
354
- };
354
+ unique_ptr<Expression> RecursiveDependentJoinPlanner::VisitReplace(BoundSubqueryExpression &expr,
355
+ unique_ptr<Expression> *expr_ptr) {
356
+ return binder.PlanSubquery(expr, root);
357
+ }
355
358
 
356
359
  unique_ptr<Expression> Binder::PlanSubquery(BoundSubqueryExpression &expr, unique_ptr<LogicalOperator> &root) {
357
360
  D_ASSERT(root);
358
361
  // first we translate the QueryNode of the subquery into a logical plan
359
362
  // note that we do not plan nested subqueries yet
360
363
  auto sub_binder = Binder::CreateBinder(context, this);
361
- sub_binder->plan_subquery = false;
364
+ sub_binder->is_outside_flattened = false;
362
365
  auto subquery_root = sub_binder->CreatePlan(*expr.subquery);
363
366
  D_ASSERT(subquery_root);
364
367
 
365
368
  // now we actually flatten the subquery
366
369
  auto plan = std::move(subquery_root);
370
+
367
371
  unique_ptr<Expression> result_expression;
368
372
  if (!expr.IsCorrelated()) {
369
373
  result_expression = PlanUncorrelatedSubquery(*this, expr, root, std::move(plan));
@@ -371,8 +375,8 @@ unique_ptr<Expression> Binder::PlanSubquery(BoundSubqueryExpression &expr, uniqu
371
375
  result_expression = PlanCorrelatedSubquery(*this, expr, root, std::move(plan));
372
376
  }
373
377
  // finally, we recursively plan the nested subqueries (if there are any)
374
- if (sub_binder->has_unplanned_subqueries) {
375
- RecursiveSubqueryPlanner plan(*this);
378
+ if (sub_binder->has_unplanned_dependent_joins) {
379
+ RecursiveDependentJoinPlanner plan(*this);
376
380
  plan.VisitOperator(*root);
377
381
  }
378
382
  return result_expression;
@@ -383,7 +387,6 @@ void Binder::PlanSubqueries(unique_ptr<Expression> &expr_ptr, unique_ptr<Logical
383
387
  return;
384
388
  }
385
389
  auto &expr = *expr_ptr;
386
-
387
390
  // first visit the children of the node, if any
388
391
  ExpressionIterator::EnumerateChildren(expr, [&](unique_ptr<Expression> &expr) { PlanSubqueries(expr, root); });
389
392
 
@@ -391,11 +394,11 @@ void Binder::PlanSubqueries(unique_ptr<Expression> &expr_ptr, unique_ptr<Logical
391
394
  if (expr.expression_class == ExpressionClass::BOUND_SUBQUERY) {
392
395
  auto &subquery = expr.Cast<BoundSubqueryExpression>();
393
396
  // subquery node! plan it
394
- if (subquery.IsCorrelated() && !plan_subquery) {
397
+ if (subquery.IsCorrelated() && !is_outside_flattened) {
395
398
  // detected a nested correlated subquery
396
399
  // we don't plan it yet here, we are currently planning a subquery
397
400
  // nested subqueries will only be planned AFTER the current subquery has been flattened entirely
398
- has_unplanned_subqueries = true;
401
+ has_unplanned_dependent_joins = true;
399
402
  return;
400
403
  }
401
404
  expr_ptr = PlanSubquery(subquery, root);
@@ -411,7 +414,7 @@ unique_ptr<LogicalOperator> Binder::PlanLateralJoin(unique_ptr<LogicalOperator>
411
414
  vector<unique_ptr<Expression>> arbitrary_expressions;
412
415
  if (condition) {
413
416
  // extract join conditions, if there are any
414
- LogicalComparisonJoin::ExtractJoinConditions(join_type, left, right, std::move(condition), conditions,
417
+ LogicalComparisonJoin::ExtractJoinConditions(context, join_type, left, right, std::move(condition), conditions,
415
418
  arbitrary_expressions);
416
419
  }
417
420
 
@@ -45,9 +45,18 @@ unique_ptr<BoundTableRef> Binder::Bind(BaseTableRef &ref) {
45
45
  return Bind(subquery, found_cte);
46
46
  } else {
47
47
  // There is a CTE binding in the BindContext.
48
- // This can only be the case if there is a recursive CTE present.
48
+ // This can only be the case if there is a recursive CTE,
49
+ // or a materialized CTE present.
49
50
  auto index = GenerateTableIndex();
50
- auto result = make_uniq<BoundCTERef>(index, ctebinding->index);
51
+ auto materialized = cte.materialized;
52
+ if (materialized == CTEMaterialize::CTE_MATERIALIZE_DEFAULT) {
53
+ #ifdef DUCKDB_ALTERNATIVE_VERIFY
54
+ materialized = CTEMaterialize::CTE_MATERIALIZE_ALWAYS;
55
+ #else
56
+ materialized = CTEMaterialize::CTE_MATERIALIZE_NEVER;
57
+ #endif
58
+ }
59
+ auto result = make_uniq<BoundCTERef>(index, ctebinding->index, materialized);
51
60
  auto b = ctebinding;
52
61
  auto alias = ref.alias.empty() ? ref.table_name : ref.alias;
53
62
  auto names = BindContext::AliasColumnNames(alias, b->names, ref.column_name_alias);
@@ -130,9 +130,19 @@ unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) {
130
130
  {
131
131
  LateralBinder binder(left_binder, context);
132
132
  result->right = right_binder.Bind(*ref.right);
133
- result->correlated_columns = binder.ExtractCorrelatedColumns(right_binder);
134
-
135
- result->lateral = binder.HasCorrelatedColumns();
133
+ bool is_lateral = false;
134
+ // Store the correlated columns in the right binder in bound ref for planning of LATERALs
135
+ // Ignore the correlated columns in the left binder, flattening handles those correlations
136
+ result->correlated_columns = right_binder.correlated_columns;
137
+ // Find correlations for the current join
138
+ for (auto &cor_col : result->correlated_columns) {
139
+ if (cor_col.depth == 1) {
140
+ // Depth 1 indicates columns binding from the left indicating a lateral join
141
+ is_lateral = true;
142
+ break;
143
+ }
144
+ }
145
+ result->lateral = is_lateral;
136
146
  if (result->lateral) {
137
147
  // lateral join: can only be an INNER or LEFT join
138
148
  if (ref.type != JoinType::INNER && ref.type != JoinType::LEFT) {
@@ -210,6 +220,7 @@ unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) {
210
220
 
211
221
  case JoinRefType::CROSS:
212
222
  case JoinRefType::POSITIONAL:
223
+ case JoinRefType::DEPENDENT:
213
224
  break;
214
225
  }
215
226
  extra_using_columns = RemoveDuplicateUsingColumns(extra_using_columns);
@@ -268,8 +279,24 @@ unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) {
268
279
 
269
280
  bind_context.AddContext(std::move(left_binder.bind_context));
270
281
  bind_context.AddContext(std::move(right_binder.bind_context));
271
- MoveCorrelatedExpressions(left_binder);
272
- MoveCorrelatedExpressions(right_binder);
282
+
283
+ // Update the correlated columns for the parent binder
284
+ // For the left binder, depth >= 1 indicates correlations from the parent binder
285
+ for (const auto &col : left_binder.correlated_columns) {
286
+ if (col.depth >= 1) {
287
+ AddCorrelatedColumn(col);
288
+ }
289
+ }
290
+ // For the right binder, depth > 1 indicates correlations from the parent binder
291
+ // (depth = 1 indicates correlations from the left side of the join)
292
+ for (auto col : right_binder.correlated_columns) {
293
+ if (col.depth > 1) {
294
+ // Decrement the depth to account for the effect of the lateral binder
295
+ col.depth--;
296
+ AddCorrelatedColumn(col);
297
+ }
298
+ }
299
+
273
300
  for (auto &condition : extra_conditions) {
274
301
  if (ref.condition) {
275
302
  ref.condition = make_uniq<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND, std::move(ref.condition),
@@ -18,6 +18,7 @@
18
18
  #include "duckdb/planner/tableref/bound_pivotref.hpp"
19
19
  #include "duckdb/planner/expression/bound_aggregate_expression.hpp"
20
20
  #include "duckdb/main/client_config.hpp"
21
+ #include "duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp"
21
22
 
22
23
  namespace duckdb {
23
24
 
@@ -66,18 +67,10 @@ static void ExtractPivotExpressions(ParsedExpression &expr, case_insensitive_set
66
67
  expr, [&](ParsedExpression &child) { ExtractPivotExpressions(child, handled_columns); });
67
68
  }
68
69
 
69
- struct PivotBindState {
70
- vector<string> internal_group_names;
71
- vector<string> group_names;
72
- vector<string> aggregate_names;
73
- vector<string> internal_aggregate_names;
74
- };
75
-
76
- static unique_ptr<SelectNode> PivotInitialAggregate(PivotBindState &bind_state, PivotRef &ref,
77
- vector<unique_ptr<ParsedExpression>> all_columns,
78
- const case_insensitive_set_t &handled_columns) {
79
- auto subquery_stage1 = make_uniq<SelectNode>();
80
- subquery_stage1->from_table = std::move(ref.source);
70
+ static unique_ptr<SelectNode> ConstructInitialGrouping(PivotRef &ref, vector<unique_ptr<ParsedExpression>> all_columns,
71
+ const case_insensitive_set_t &handled_columns) {
72
+ auto subquery = make_uniq<SelectNode>();
73
+ subquery->from_table = std::move(ref.source);
81
74
  if (ref.groups.empty()) {
82
75
  // if rows are not specified any columns that are not pivoted/aggregated on are added to the GROUP BY clause
83
76
  for (auto &entry : all_columns) {
@@ -87,19 +80,74 @@ static unique_ptr<SelectNode> PivotInitialAggregate(PivotBindState &bind_state,
87
80
  auto &columnref = entry->Cast<ColumnRefExpression>();
88
81
  if (handled_columns.find(columnref.GetColumnName()) == handled_columns.end()) {
89
82
  // not handled - add to grouping set
90
- subquery_stage1->groups.group_expressions.push_back(
91
- make_uniq<ConstantExpression>(Value::INTEGER(subquery_stage1->select_list.size() + 1)));
92
- subquery_stage1->select_list.push_back(make_uniq<ColumnRefExpression>(columnref.GetColumnName()));
83
+ subquery->groups.group_expressions.push_back(
84
+ make_uniq<ConstantExpression>(Value::INTEGER(subquery->select_list.size() + 1)));
85
+ subquery->select_list.push_back(make_uniq<ColumnRefExpression>(columnref.GetColumnName()));
93
86
  }
94
87
  }
95
88
  } else {
96
89
  // if rows are specified only the columns mentioned in rows are added as groups
97
90
  for (auto &row : ref.groups) {
98
- subquery_stage1->groups.group_expressions.push_back(
99
- make_uniq<ConstantExpression>(Value::INTEGER(subquery_stage1->select_list.size() + 1)));
100
- subquery_stage1->select_list.push_back(make_uniq<ColumnRefExpression>(row));
91
+ subquery->groups.group_expressions.push_back(
92
+ make_uniq<ConstantExpression>(Value::INTEGER(subquery->select_list.size() + 1)));
93
+ subquery->select_list.push_back(make_uniq<ColumnRefExpression>(row));
101
94
  }
102
95
  }
96
+ return subquery;
97
+ }
98
+
99
+ static unique_ptr<SelectNode> PivotFilteredAggregate(PivotRef &ref, vector<unique_ptr<ParsedExpression>> all_columns,
100
+ const case_insensitive_set_t &handled_columns,
101
+ vector<PivotValueElement> pivot_values) {
102
+ auto subquery = ConstructInitialGrouping(ref, std::move(all_columns), handled_columns);
103
+
104
+ // push the filtered aggregates
105
+ for (auto &pivot_value : pivot_values) {
106
+ unique_ptr<ParsedExpression> filter;
107
+ idx_t pivot_value_idx = 0;
108
+ for (auto &pivot_column : ref.pivots) {
109
+ for (auto &pivot_expr : pivot_column.pivot_expressions) {
110
+ auto column_ref = make_uniq<CastExpression>(LogicalType::VARCHAR, pivot_expr->Copy());
111
+ auto constant_value = make_uniq<ConstantExpression>(pivot_value.values[pivot_value_idx++]);
112
+ auto comp_expr = make_uniq<ComparisonExpression>(ExpressionType::COMPARE_NOT_DISTINCT_FROM,
113
+ std::move(column_ref), std::move(constant_value));
114
+ if (filter) {
115
+ filter = make_uniq<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND, std::move(filter),
116
+ std::move(comp_expr));
117
+ } else {
118
+ filter = std::move(comp_expr);
119
+ }
120
+ }
121
+ }
122
+ for (auto &aggregate : ref.aggregates) {
123
+ auto copied_aggr = aggregate->Copy();
124
+ auto &aggr = copied_aggr->Cast<FunctionExpression>();
125
+ aggr.filter = filter->Copy();
126
+ auto &aggr_name = aggregate->alias;
127
+ auto name = pivot_value.name;
128
+ if (ref.aggregates.size() > 1 || !aggr_name.empty()) {
129
+ // if there are multiple aggregates specified we add the name of the aggregate as well
130
+ name += "_" + (aggr_name.empty() ? aggregate->GetName() : aggr_name);
131
+ }
132
+ aggr.alias = name;
133
+ subquery->select_list.push_back(std::move(copied_aggr));
134
+ }
135
+ }
136
+ return subquery;
137
+ }
138
+
139
+ struct PivotBindState {
140
+ vector<string> internal_group_names;
141
+ vector<string> group_names;
142
+ vector<string> aggregate_names;
143
+ vector<string> internal_aggregate_names;
144
+ };
145
+
146
+ static unique_ptr<SelectNode> PivotInitialAggregate(PivotBindState &bind_state, PivotRef &ref,
147
+ vector<unique_ptr<ParsedExpression>> all_columns,
148
+ const case_insensitive_set_t &handled_columns) {
149
+ auto subquery_stage1 = ConstructInitialGrouping(ref, std::move(all_columns), handled_columns);
150
+
103
151
  idx_t group_count = 0;
104
152
  for (auto &expr : subquery_stage1->select_list) {
105
153
  bind_state.group_names.push_back(expr->GetName());
@@ -134,6 +182,15 @@ static unique_ptr<SelectNode> PivotInitialAggregate(PivotBindState &bind_state,
134
182
  return subquery_stage1;
135
183
  }
136
184
 
185
+ unique_ptr<ParsedExpression> ConstructPivotExpression(unique_ptr<ParsedExpression> pivot_expr) {
186
+ auto cast = make_uniq<CastExpression>(LogicalType::VARCHAR, std::move(pivot_expr));
187
+ vector<unique_ptr<ParsedExpression>> coalesce_children;
188
+ coalesce_children.push_back(std::move(cast));
189
+ coalesce_children.push_back(make_uniq<ConstantExpression>(Value("NULL")));
190
+ auto coalesce = make_uniq<OperatorExpression>(ExpressionType::OPERATOR_COALESCE, std::move(coalesce_children));
191
+ return std::move(coalesce);
192
+ }
193
+
137
194
  static unique_ptr<SelectNode> PivotListAggregate(PivotBindState &bind_state, PivotRef &ref,
138
195
  unique_ptr<SelectNode> subquery_stage1) {
139
196
  auto subquery_stage2 = make_uniq<SelectNode>();
@@ -166,13 +223,7 @@ static unique_ptr<SelectNode> PivotListAggregate(PivotBindState &bind_state, Piv
166
223
  for (auto &pivot : ref.pivots) {
167
224
  for (auto &pivot_expr : pivot.pivot_expressions) {
168
225
  // coalesce(pivot::VARCHAR, 'NULL')
169
- auto cast = make_uniq<CastExpression>(LogicalType::VARCHAR, std::move(pivot_expr));
170
- vector<unique_ptr<ParsedExpression>> coalesce_children;
171
- coalesce_children.push_back(std::move(cast));
172
- coalesce_children.push_back(make_uniq<ConstantExpression>(Value("NULL")));
173
- auto coalesce =
174
- make_uniq<OperatorExpression>(ExpressionType::OPERATOR_COALESCE, std::move(coalesce_children));
175
-
226
+ auto coalesce = ConstructPivotExpression(std::move(pivot_expr));
176
227
  if (!expr) {
177
228
  expr = std::move(coalesce);
178
229
  } else {
@@ -250,9 +301,8 @@ unique_ptr<BoundTableRef> Binder::BindBoundPivot(PivotRef &ref) {
250
301
  auto &aggregates = result->bound_pivot.aggregates;
251
302
  ExtractPivotAggregates(*result->child, aggregates);
252
303
  if (aggregates.size() != ref.bound_aggregate_names.size()) {
253
- throw BinderException("Pivot aggregate count mismatch. Expected %llu aggregates but found %llu. Are all pivot "
254
- "expressions aggregate functions?",
255
- ref.bound_aggregate_names.size(), aggregates.size());
304
+ throw InternalException("Pivot aggregate count mismatch (expected %llu, found %llu)",
305
+ ref.bound_aggregate_names.size(), aggregates.size());
256
306
  }
257
307
 
258
308
  vector<string> child_names;
@@ -313,9 +363,12 @@ unique_ptr<SelectNode> Binder::BindPivot(PivotRef &ref, vector<unique_ptr<Parsed
313
363
  if (aggr->IsWindow()) {
314
364
  throw BinderException(FormatError(*aggr, "Pivot expression cannot contain window functions"));
315
365
  }
366
+ // bind the function as an aggregate to ensure it is an aggregate and not a scalar function
367
+ auto &aggr_function = aggr->Cast<FunctionExpression>();
368
+ (void)Catalog::GetEntry<AggregateFunctionCatalogEntry>(context, aggr_function.catalog, aggr_function.schema,
369
+ aggr_function.function_name);
316
370
  ExtractPivotExpressions(*aggr, handled_columns);
317
371
  }
318
- value_set_t pivots;
319
372
 
320
373
  // first add all pivots to the set of handled columns, and check for duplicates
321
374
  idx_t total_pivots = 1;
@@ -362,40 +415,53 @@ unique_ptr<SelectNode> Binder::BindPivot(PivotRef &ref, vector<unique_ptr<Parsed
362
415
  pivots.insert(val);
363
416
  }
364
417
  }
365
- auto pivot_limit = ClientConfig::GetConfig(context).pivot_limit;
418
+ auto &client_config = ClientConfig::GetConfig(context);
419
+ auto pivot_limit = client_config.pivot_limit;
366
420
  if (total_pivots >= pivot_limit) {
367
421
  throw BinderException("Pivot column limit of %llu exceeded. Use SET pivot_limit=X to increase the limit.",
368
- ClientConfig::GetConfig(context).pivot_limit);
422
+ client_config.pivot_limit);
369
423
  }
370
424
 
371
425
  // construct the required pivot values recursively
372
426
  vector<PivotValueElement> pivot_values;
373
427
  ConstructPivots(ref, pivot_values);
374
428
 
429
+ unique_ptr<SelectNode> pivot_node;
375
430
  // pivots have three components
376
431
  // - the pivots (i.e. future column names)
377
432
  // - the groups (i.e. the future row names
378
433
  // - the aggregates (i.e. the values of the pivot columns)
379
434
 
380
- // executing a pivot statement happens in three stages
381
- // 1) execute the query "SELECT {groups}, {pivots}, {aggregates} FROM {from_clause} GROUP BY {groups}, {pivots}
382
- // this computes all values that are required in the final result, but not yet in the correct orientation
383
- // 2) execute the query "SELECT {groups}, LIST({pivots}), LIST({aggregates}) FROM [Q1] GROUP BY {groups}
384
- // this pushes all pivots and aggregates that belong to a specific group together in an aligned manner
385
- // 3) push a PIVOT operator, that performs the actual pivoting of the values into the different columns
386
-
387
- PivotBindState bind_state;
388
- // Pivot Stage 1
389
- // SELECT {groups}, {pivots}, {aggregates} FROM {from_clause} GROUP BY {groups}, {pivots}
390
- auto subquery_stage1 = PivotInitialAggregate(bind_state, ref, std::move(all_columns), handled_columns);
391
-
392
- // Pivot stage 2
393
- // SELECT {groups}, LIST({pivots}), LIST({aggregates}) FROM [Q1] GROUP BY {groups}
394
- auto subquery_stage2 = PivotListAggregate(bind_state, ref, std::move(subquery_stage1));
395
-
396
- // Pivot stage 3
397
- // construct the final pivot operator
398
- auto pivot_node = PivotFinalOperator(bind_state, ref, std::move(subquery_stage2), std::move(pivot_values));
435
+ // we have two ways of executing a pivot statement
436
+ // (1) the straightforward manner of filtered aggregates SUM(..) FILTER (pivot_value=X)
437
+ // (2) computing the aggregates once, then using LIST to group the aggregates together with the PIVOT operator
438
+ // -> filtered aggregates are faster when there are FEW pivot values
439
+ // -> LIST is faster when there are MANY pivot values
440
+ // we switch dynamically based on the number of pivots to compute
441
+ if (pivot_values.size() <= client_config.pivot_filter_threshold) {
442
+ // use a set of filtered aggregates
443
+ pivot_node = PivotFilteredAggregate(ref, std::move(all_columns), handled_columns, std::move(pivot_values));
444
+ } else {
445
+ // executing a pivot statement happens in three stages
446
+ // 1) execute the query "SELECT {groups}, {pivots}, {aggregates} FROM {from_clause} GROUP BY {groups}, {pivots}
447
+ // this computes all values that are required in the final result, but not yet in the correct orientation
448
+ // 2) execute the query "SELECT {groups}, LIST({pivots}), LIST({aggregates}) FROM [Q1] GROUP BY {groups}
449
+ // this pushes all pivots and aggregates that belong to a specific group together in an aligned manner
450
+ // 3) push a PIVOT operator, that performs the actual pivoting of the values into the different columns
451
+
452
+ PivotBindState bind_state;
453
+ // Pivot Stage 1
454
+ // SELECT {groups}, {pivots}, {aggregates} FROM {from_clause} GROUP BY {groups}, {pivots}
455
+ auto subquery_stage1 = PivotInitialAggregate(bind_state, ref, std::move(all_columns), handled_columns);
456
+
457
+ // Pivot stage 2
458
+ // SELECT {groups}, LIST({pivots}), LIST({aggregates}) FROM [Q1] GROUP BY {groups}
459
+ auto subquery_stage2 = PivotListAggregate(bind_state, ref, std::move(subquery_stage1));
460
+
461
+ // Pivot stage 3
462
+ // construct the final pivot operator
463
+ pivot_node = PivotFinalOperator(bind_state, ref, std::move(subquery_stage2), std::move(pivot_values));
464
+ }
399
465
  return pivot_node;
400
466
  }
401
467
 
@@ -13,7 +13,7 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundCTERef &ref) {
13
13
  types.push_back(type);
14
14
  }
15
15
 
16
- return make_uniq<LogicalCTERef>(index, ref.cte_index, types, ref.bound_columns);
16
+ return make_uniq<LogicalCTERef>(index, ref.cte_index, types, ref.bound_columns, ref.materialized_cte);
17
17
  }
18
18
 
19
19
  } // namespace duckdb
@@ -10,11 +10,14 @@
10
10
  #include "duckdb/planner/operator/logical_asof_join.hpp"
11
11
  #include "duckdb/planner/operator/logical_comparison_join.hpp"
12
12
  #include "duckdb/planner/operator/logical_cross_product.hpp"
13
+ #include "duckdb/planner/operator/logical_dependent_join.hpp"
13
14
  #include "duckdb/planner/operator/logical_filter.hpp"
14
15
  #include "duckdb/planner/operator/logical_positional_join.hpp"
15
16
  #include "duckdb/planner/tableref/bound_joinref.hpp"
16
17
  #include "duckdb/main/client_context.hpp"
17
18
  #include "duckdb/planner/expression_binder/lateral_binder.hpp"
19
+ #include "duckdb/planner/subquery/recursive_dependent_join_planner.hpp"
20
+ #include "duckdb/execution/expression_executor.hpp"
18
21
 
19
22
  namespace duckdb {
20
23
 
@@ -44,13 +47,11 @@ static bool CreateJoinCondition(Expression &expr, const unordered_set<idx_t> &le
44
47
  return false;
45
48
  }
46
49
 
47
- void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<LogicalOperator> &left_child,
48
- unique_ptr<LogicalOperator> &right_child,
49
- const unordered_set<idx_t> &left_bindings,
50
- const unordered_set<idx_t> &right_bindings,
51
- vector<unique_ptr<Expression>> &expressions,
52
- vector<JoinCondition> &conditions,
53
- vector<unique_ptr<Expression>> &arbitrary_expressions) {
50
+ void LogicalComparisonJoin::ExtractJoinConditions(
51
+ ClientContext &context, JoinType type, unique_ptr<LogicalOperator> &left_child,
52
+ unique_ptr<LogicalOperator> &right_child, const unordered_set<idx_t> &left_bindings,
53
+ const unordered_set<idx_t> &right_bindings, vector<unique_ptr<Expression>> &expressions,
54
+ vector<JoinCondition> &conditions, vector<unique_ptr<Expression>> &arbitrary_expressions) {
54
55
  for (auto &expr : expressions) {
55
56
  auto total_side = JoinSide::GetJoinSide(*expr, left_bindings, right_bindings);
56
57
  if (total_side != JoinSide::BOTH) {
@@ -68,6 +69,15 @@ void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<Logi
68
69
  filter.expressions.push_back(std::move(expr));
69
70
  continue;
70
71
  }
72
+ // if the join is a LEFT JOIN and the join expression constantly evaluates to TRUE,
73
+ // then we do not add it to the arbitrary expressions
74
+ if (type == JoinType::LEFT && expr->IsFoldable()) {
75
+ Value result;
76
+ ExpressionExecutor::TryEvaluateScalar(context, *expr, result);
77
+ if (!result.IsNull() && result == Value(true)) {
78
+ continue;
79
+ }
80
+ }
71
81
  } else if ((expr->type >= ExpressionType::COMPARE_EQUAL &&
72
82
  expr->type <= ExpressionType::COMPARE_GREATERTHANOREQUALTO) ||
73
83
  expr->type == ExpressionType::COMPARE_DISTINCT_FROM ||
@@ -82,7 +92,8 @@ void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<Logi
82
92
  }
83
93
  }
84
94
 
85
- void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<LogicalOperator> &left_child,
95
+ void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type,
96
+ unique_ptr<LogicalOperator> &left_child,
86
97
  unique_ptr<LogicalOperator> &right_child,
87
98
  vector<unique_ptr<Expression>> &expressions,
88
99
  vector<JoinCondition> &conditions,
@@ -90,11 +101,12 @@ void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<Logi
90
101
  unordered_set<idx_t> left_bindings, right_bindings;
91
102
  LogicalJoin::GetTableReferences(*left_child, left_bindings);
92
103
  LogicalJoin::GetTableReferences(*right_child, right_bindings);
93
- return ExtractJoinConditions(type, left_child, right_child, left_bindings, right_bindings, expressions, conditions,
94
- arbitrary_expressions);
104
+ return ExtractJoinConditions(context, type, left_child, right_child, left_bindings, right_bindings, expressions,
105
+ conditions, arbitrary_expressions);
95
106
  }
96
107
 
97
- void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<LogicalOperator> &left_child,
108
+ void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type,
109
+ unique_ptr<LogicalOperator> &left_child,
98
110
  unique_ptr<LogicalOperator> &right_child,
99
111
  unique_ptr<Expression> condition, vector<JoinCondition> &conditions,
100
112
  vector<unique_ptr<Expression>> &arbitrary_expressions) {
@@ -102,10 +114,12 @@ void LogicalComparisonJoin::ExtractJoinConditions(JoinType type, unique_ptr<Logi
102
114
  vector<unique_ptr<Expression>> expressions;
103
115
  expressions.push_back(std::move(condition));
104
116
  LogicalFilter::SplitPredicates(expressions);
105
- return ExtractJoinConditions(type, left_child, right_child, expressions, conditions, arbitrary_expressions);
117
+ return ExtractJoinConditions(context, type, left_child, right_child, expressions, conditions,
118
+ arbitrary_expressions);
106
119
  }
107
120
 
108
- unique_ptr<LogicalOperator> LogicalComparisonJoin::CreateJoin(JoinType type, JoinRefType reftype,
121
+ unique_ptr<LogicalOperator> LogicalComparisonJoin::CreateJoin(ClientContext &context, JoinType type,
122
+ JoinRefType reftype,
109
123
  unique_ptr<LogicalOperator> left_child,
110
124
  unique_ptr<LogicalOperator> right_child,
111
125
  vector<JoinCondition> conditions,
@@ -216,29 +230,37 @@ static bool HasCorrelatedColumns(Expression &expression) {
216
230
  return has_correlated_columns;
217
231
  }
218
232
 
219
- unique_ptr<LogicalOperator> LogicalComparisonJoin::CreateJoin(JoinType type, JoinRefType reftype,
233
+ unique_ptr<LogicalOperator> LogicalComparisonJoin::CreateJoin(ClientContext &context, JoinType type,
234
+ JoinRefType reftype,
220
235
  unique_ptr<LogicalOperator> left_child,
221
236
  unique_ptr<LogicalOperator> right_child,
222
237
  unique_ptr<Expression> condition) {
223
238
  vector<JoinCondition> conditions;
224
239
  vector<unique_ptr<Expression>> arbitrary_expressions;
225
- LogicalComparisonJoin::ExtractJoinConditions(type, left_child, right_child, std::move(condition), conditions,
226
- arbitrary_expressions);
227
- return LogicalComparisonJoin::CreateJoin(type, reftype, std::move(left_child), std::move(right_child),
240
+ LogicalComparisonJoin::ExtractJoinConditions(context, type, left_child, right_child, std::move(condition),
241
+ conditions, arbitrary_expressions);
242
+ return LogicalComparisonJoin::CreateJoin(context, type, reftype, std::move(left_child), std::move(right_child),
228
243
  std::move(conditions), std::move(arbitrary_expressions));
229
244
  }
230
245
 
231
246
  unique_ptr<LogicalOperator> Binder::CreatePlan(BoundJoinRef &ref) {
247
+ auto old_is_outside_flattened = is_outside_flattened;
248
+ // Plan laterals from outermost to innermost
249
+ if (ref.lateral) {
250
+ // Set the flag to ensure that children do not flatten before the root
251
+ is_outside_flattened = false;
252
+ }
232
253
  auto left = CreatePlan(*ref.left);
233
254
  auto right = CreatePlan(*ref.right);
255
+ is_outside_flattened = old_is_outside_flattened;
256
+
257
+ // For joins, depth of the bindings will be one higher on the right because of the lateral binder
258
+ // If the current join does not have correlations between left and right, then the right bindings
259
+ // have depth 1 too high and can be reduced by 1 throughout
234
260
  if (!ref.lateral && !ref.correlated_columns.empty()) {
235
- // non-lateral join with correlated columns
236
- // this happens if there is a join (or cross product) in a correlated subquery
237
- // due to the lateral binder the expression depth of all correlated columns in the "ref.correlated_columns" set
238
- // is 1 too high
239
- // we reduce expression depth of all columns in the "ref.correlated_columns" set by 1
240
261
  LateralBinder::ReduceExpressionDepth(*right, ref.correlated_columns);
241
262
  }
263
+
242
264
  if (ref.type == JoinType::RIGHT && ref.ref_type != JoinRefType::ASOF &&
243
265
  ClientConfig::GetConfig(context).enable_optimizer) {
244
266
  // we turn any right outer joins into left outer joins for optimization purposes
@@ -247,9 +269,22 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundJoinRef &ref) {
247
269
  std::swap(left, right);
248
270
  }
249
271
  if (ref.lateral) {
250
- // lateral join
251
- return PlanLateralJoin(std::move(left), std::move(right), ref.correlated_columns, ref.type,
252
- std::move(ref.condition));
272
+ if (!is_outside_flattened) {
273
+ // If outer dependent joins is yet to be flattened, only plan the lateral
274
+ has_unplanned_dependent_joins = true;
275
+ return LogicalDependentJoin::Create(std::move(left), std::move(right), ref.correlated_columns, ref.type,
276
+ std::move(ref.condition));
277
+ } else {
278
+ // All outer dependent joins have been planned and flattened, so plan and flatten lateral and recursively
279
+ // plan the children
280
+ auto new_plan = PlanLateralJoin(std::move(left), std::move(right), ref.correlated_columns, ref.type,
281
+ std::move(ref.condition));
282
+ if (has_unplanned_dependent_joins) {
283
+ RecursiveDependentJoinPlanner plan(*this);
284
+ plan.VisitOperator(*new_plan);
285
+ }
286
+ return new_plan;
287
+ }
253
288
  }
254
289
  switch (ref.ref_type) {
255
290
  case JoinRefType::CROSS:
@@ -275,7 +310,7 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundJoinRef &ref) {
275
310
  }
276
311
 
277
312
  // now create the join operator from the join condition
278
- auto result = LogicalComparisonJoin::CreateJoin(ref.type, ref.ref_type, std::move(left), std::move(right),
313
+ auto result = LogicalComparisonJoin::CreateJoin(context, ref.type, ref.ref_type, std::move(left), std::move(right),
279
314
  std::move(ref.condition));
280
315
 
281
316
  optional_ptr<LogicalOperator> join;
@@ -6,10 +6,10 @@ namespace duckdb {
6
6
  unique_ptr<LogicalOperator> Binder::CreatePlan(BoundSubqueryRef &ref) {
7
7
  // generate the logical plan for the subquery
8
8
  // this happens separately from the current LogicalPlan generation
9
- ref.binder->plan_subquery = plan_subquery;
9
+ ref.binder->is_outside_flattened = is_outside_flattened;
10
10
  auto subquery = ref.binder->CreatePlan(*ref.subquery);
11
- if (ref.binder->has_unplanned_subqueries) {
12
- has_unplanned_subqueries = true;
11
+ if (ref.binder->has_unplanned_dependent_joins) {
12
+ has_unplanned_dependent_joins = true;
13
13
  }
14
14
  return subquery;
15
15
  }