duckdb 0.7.2-dev16.0 → 0.7.2-dev314.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/binding.gyp +2 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/icu/icu-extension.cpp +2 -0
  4. package/src/duckdb/extension/icu/icu-table-range.cpp +194 -0
  5. package/src/duckdb/extension/icu/include/icu-table-range.hpp +17 -0
  6. package/src/duckdb/extension/parquet/column_reader.cpp +5 -6
  7. package/src/duckdb/extension/parquet/column_writer.cpp +0 -1
  8. package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -2
  9. package/src/duckdb/extension/parquet/include/generated_column_reader.hpp +1 -11
  10. package/src/duckdb/extension/parquet/parquet-extension.cpp +11 -2
  11. package/src/duckdb/extension/parquet/parquet_statistics.cpp +26 -32
  12. package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +4 -0
  13. package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +7 -6
  14. package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +20 -1
  15. package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
  16. package/src/duckdb/src/common/sort/sort_state.cpp +5 -7
  17. package/src/duckdb/src/common/types/bit.cpp +95 -58
  18. package/src/duckdb/src/common/types/value.cpp +149 -53
  19. package/src/duckdb/src/common/types/vector.cpp +13 -10
  20. package/src/duckdb/src/execution/column_binding_resolver.cpp +6 -0
  21. package/src/duckdb/src/execution/operator/aggregate/physical_perfecthash_aggregate.cpp +4 -5
  22. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +1 -1
  23. package/src/duckdb/src/execution/operator/helper/physical_vacuum.cpp +2 -3
  24. package/src/duckdb/src/execution/operator/join/physical_blockwise_nl_join.cpp +32 -6
  25. package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +1 -1
  26. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +15 -15
  27. package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +18 -12
  28. package/src/duckdb/src/function/aggregate/algebraic/avg.cpp +0 -6
  29. package/src/duckdb/src/function/aggregate/distributive/bitagg.cpp +99 -95
  30. package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +254 -0
  31. package/src/duckdb/src/function/aggregate/distributive/count.cpp +2 -4
  32. package/src/duckdb/src/function/aggregate/distributive/sum.cpp +11 -16
  33. package/src/duckdb/src/function/aggregate/distributive_functions.cpp +1 -0
  34. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +16 -5
  35. package/src/duckdb/src/function/cast/bit_cast.cpp +0 -2
  36. package/src/duckdb/src/function/cast/blob_cast.cpp +0 -1
  37. package/src/duckdb/src/function/scalar/bit/bitstring.cpp +99 -0
  38. package/src/duckdb/src/function/scalar/date/date_diff.cpp +0 -1
  39. package/src/duckdb/src/function/scalar/date/date_part.cpp +17 -25
  40. package/src/duckdb/src/function/scalar/date/date_sub.cpp +0 -1
  41. package/src/duckdb/src/function/scalar/date/date_trunc.cpp +10 -14
  42. package/src/duckdb/src/function/scalar/generic/stats.cpp +2 -4
  43. package/src/duckdb/src/function/scalar/list/flatten.cpp +5 -12
  44. package/src/duckdb/src/function/scalar/list/list_concat.cpp +3 -8
  45. package/src/duckdb/src/function/scalar/list/list_extract.cpp +5 -12
  46. package/src/duckdb/src/function/scalar/list/list_value.cpp +5 -9
  47. package/src/duckdb/src/function/scalar/map/map_entries.cpp +61 -0
  48. package/src/duckdb/src/function/scalar/map/map_keys_values.cpp +97 -0
  49. package/src/duckdb/src/function/scalar/math/numeric.cpp +14 -17
  50. package/src/duckdb/src/function/scalar/nested_functions.cpp +3 -0
  51. package/src/duckdb/src/function/scalar/operators/add.cpp +0 -9
  52. package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +29 -48
  53. package/src/duckdb/src/function/scalar/operators/bitwise.cpp +0 -63
  54. package/src/duckdb/src/function/scalar/operators/multiply.cpp +0 -6
  55. package/src/duckdb/src/function/scalar/operators/subtract.cpp +0 -6
  56. package/src/duckdb/src/function/scalar/string/caseconvert.cpp +2 -6
  57. package/src/duckdb/src/function/scalar/string/instr.cpp +2 -6
  58. package/src/duckdb/src/function/scalar/string/length.cpp +2 -6
  59. package/src/duckdb/src/function/scalar/string/like.cpp +2 -6
  60. package/src/duckdb/src/function/scalar/string/substring.cpp +2 -6
  61. package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
  62. package/src/duckdb/src/function/scalar/struct/struct_extract.cpp +4 -9
  63. package/src/duckdb/src/function/scalar/struct/struct_insert.cpp +10 -13
  64. package/src/duckdb/src/function/scalar/struct/struct_pack.cpp +5 -6
  65. package/src/duckdb/src/function/table/read_csv.cpp +9 -0
  66. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  67. package/src/duckdb/src/function/table_function.cpp +19 -0
  68. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +6 -8
  69. package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -19
  70. package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
  71. package/src/duckdb/src/include/duckdb/common/enums/tableref_type.hpp +2 -1
  72. package/src/duckdb/src/include/duckdb/common/types/bit.hpp +5 -1
  73. package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -8
  74. package/src/duckdb/src/include/duckdb/common/types.hpp +1 -2
  75. package/src/duckdb/src/include/duckdb/execution/operator/aggregate/physical_perfecthash_aggregate.hpp +1 -1
  76. package/src/duckdb/src/include/duckdb/function/aggregate/distributive_functions.hpp +5 -0
  77. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +12 -3
  78. package/src/duckdb/src/include/duckdb/function/scalar/bit_functions.hpp +4 -0
  79. package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +12 -0
  80. package/src/duckdb/src/include/duckdb/function/scalar_function.hpp +2 -2
  81. package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
  82. package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +2 -0
  83. package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
  84. package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
  85. package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +2 -2
  86. package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
  87. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +2 -1
  88. package/src/duckdb/src/include/duckdb/parser/parsed_data/{alter_function_info.hpp → alter_scalar_function_info.hpp} +13 -13
  89. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +47 -0
  90. package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_function_info.hpp +2 -1
  91. package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
  92. package/src/duckdb/src/include/duckdb/parser/statement/multi_statement.hpp +28 -0
  93. package/src/duckdb/src/include/duckdb/parser/tableref/list.hpp +1 -0
  94. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +76 -0
  95. package/src/duckdb/src/include/duckdb/parser/tokens.hpp +2 -0
  96. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +28 -0
  97. package/src/duckdb/src/include/duckdb/planner/bind_context.hpp +2 -0
  98. package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -0
  99. package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +2 -0
  100. package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +76 -44
  101. package/src/duckdb/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +3 -2
  102. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_compress.hpp +2 -2
  103. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_fetch.hpp +1 -1
  104. package/src/duckdb/src/include/duckdb/storage/compression/chimp/chimp_scan.hpp +1 -1
  105. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_compress.hpp +2 -2
  106. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_fetch.hpp +1 -1
  107. package/src/duckdb/src/include/duckdb/storage/compression/patas/patas_scan.hpp +1 -1
  108. package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +5 -2
  109. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +1 -1
  110. package/src/duckdb/src/include/duckdb/storage/statistics/base_statistics.hpp +93 -29
  111. package/src/duckdb/src/include/duckdb/storage/statistics/column_statistics.hpp +22 -3
  112. package/src/duckdb/src/include/duckdb/storage/statistics/distinct_statistics.hpp +6 -6
  113. package/src/duckdb/src/include/duckdb/storage/statistics/list_stats.hpp +41 -0
  114. package/src/duckdb/src/include/duckdb/storage/statistics/node_statistics.hpp +26 -0
  115. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_stats.hpp +157 -0
  116. package/src/duckdb/src/include/duckdb/storage/statistics/segment_statistics.hpp +2 -7
  117. package/src/duckdb/src/include/duckdb/storage/statistics/string_stats.hpp +74 -0
  118. package/src/duckdb/src/include/duckdb/storage/statistics/struct_stats.hpp +42 -0
  119. package/src/duckdb/src/include/duckdb/storage/string_uncompressed.hpp +2 -3
  120. package/src/duckdb/src/include/duckdb/storage/table/column_segment.hpp +2 -2
  121. package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +1 -1
  122. package/src/duckdb/src/include/duckdb/storage/table/persistent_table_data.hpp +2 -1
  123. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +4 -3
  124. package/src/duckdb/src/include/duckdb/storage/table/row_group_collection.hpp +3 -2
  125. package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +2 -0
  126. package/src/duckdb/src/include/duckdb/storage/table/table_statistics.hpp +5 -0
  127. package/src/duckdb/src/include/duckdb.h +49 -1
  128. package/src/duckdb/src/include/duckdb.hpp +0 -1
  129. package/src/duckdb/src/main/capi/pending-c.cpp +16 -3
  130. package/src/duckdb/src/main/capi/result-c.cpp +27 -1
  131. package/src/duckdb/src/main/capi/stream-c.cpp +25 -0
  132. package/src/duckdb/src/main/client_context.cpp +8 -1
  133. package/src/duckdb/src/main/config.cpp +66 -1
  134. package/src/duckdb/src/main/database.cpp +10 -2
  135. package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +98 -67
  136. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +16 -3
  137. package/src/duckdb/src/optimizer/statistics/expression/propagate_aggregate.cpp +9 -3
  138. package/src/duckdb/src/optimizer/statistics/expression/propagate_and_compress.cpp +6 -7
  139. package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +14 -11
  140. package/src/duckdb/src/optimizer/statistics/expression/propagate_columnref.cpp +1 -1
  141. package/src/duckdb/src/optimizer/statistics/expression/propagate_comparison.cpp +13 -15
  142. package/src/duckdb/src/optimizer/statistics/expression/propagate_conjunction.cpp +0 -1
  143. package/src/duckdb/src/optimizer/statistics/expression/propagate_constant.cpp +3 -75
  144. package/src/duckdb/src/optimizer/statistics/expression/propagate_function.cpp +7 -2
  145. package/src/duckdb/src/optimizer/statistics/expression/propagate_operator.cpp +10 -0
  146. package/src/duckdb/src/optimizer/statistics/operator/propagate_aggregate.cpp +2 -3
  147. package/src/duckdb/src/optimizer/statistics/operator/propagate_filter.cpp +28 -31
  148. package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +4 -5
  149. package/src/duckdb/src/optimizer/statistics/operator/propagate_set_operation.cpp +3 -3
  150. package/src/duckdb/src/optimizer/statistics_propagator.cpp +1 -1
  151. package/src/duckdb/src/parser/parsed_data/alter_info.cpp +7 -3
  152. package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +56 -0
  153. package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +51 -0
  154. package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +3 -2
  155. package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +6 -0
  156. package/src/duckdb/src/parser/parsed_expression_iterator.cpp +8 -0
  157. package/src/duckdb/src/parser/query_node.cpp +1 -1
  158. package/src/duckdb/src/parser/statement/multi_statement.cpp +18 -0
  159. package/src/duckdb/src/parser/tableref/pivotref.cpp +296 -0
  160. package/src/duckdb/src/parser/tableref.cpp +3 -0
  161. package/src/duckdb/src/parser/transform/helpers/transform_alias.cpp +12 -6
  162. package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +24 -0
  163. package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +4 -0
  164. package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +4 -0
  165. package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +150 -0
  166. package/src/duckdb/src/parser/transform/statement/transform_select.cpp +8 -0
  167. package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -1
  168. package/src/duckdb/src/parser/transform/tableref/transform_join.cpp +4 -0
  169. package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +105 -0
  170. package/src/duckdb/src/parser/transform/tableref/transform_tableref.cpp +2 -0
  171. package/src/duckdb/src/parser/transformer.cpp +15 -3
  172. package/src/duckdb/src/planner/bind_context.cpp +16 -0
  173. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +11 -3
  174. package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +0 -1
  175. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +1 -1
  176. package/src/duckdb/src/planner/binder/statement/bind_logical_plan.cpp +17 -0
  177. package/src/duckdb/src/planner/binder/tableref/bind_joinref.cpp +9 -0
  178. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +365 -0
  179. package/src/duckdb/src/planner/binder.cpp +7 -1
  180. package/src/duckdb/src/planner/bound_result_modifier.cpp +1 -1
  181. package/src/duckdb/src/planner/expression/bound_window_expression.cpp +1 -1
  182. package/src/duckdb/src/planner/filter/constant_filter.cpp +4 -6
  183. package/src/duckdb/src/planner/pragma_handler.cpp +10 -2
  184. package/src/duckdb/src/storage/buffer_manager.cpp +44 -46
  185. package/src/duckdb/src/storage/checkpoint/row_group_writer.cpp +1 -1
  186. package/src/duckdb/src/storage/checkpoint/table_data_reader.cpp +1 -4
  187. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +4 -4
  188. package/src/duckdb/src/storage/compression/bitpacking.cpp +28 -24
  189. package/src/duckdb/src/storage/compression/fixed_size_uncompressed.cpp +43 -45
  190. package/src/duckdb/src/storage/compression/numeric_constant.cpp +9 -10
  191. package/src/duckdb/src/storage/compression/patas.cpp +1 -1
  192. package/src/duckdb/src/storage/compression/rle.cpp +19 -15
  193. package/src/duckdb/src/storage/compression/validity_uncompressed.cpp +5 -5
  194. package/src/duckdb/src/storage/data_table.cpp +4 -6
  195. package/src/duckdb/src/storage/statistics/base_statistics.cpp +373 -128
  196. package/src/duckdb/src/storage/statistics/column_statistics.cpp +58 -3
  197. package/src/duckdb/src/storage/statistics/distinct_statistics.cpp +4 -9
  198. package/src/duckdb/src/storage/statistics/list_stats.cpp +117 -0
  199. package/src/duckdb/src/storage/statistics/numeric_stats.cpp +529 -0
  200. package/src/duckdb/src/storage/statistics/segment_statistics.cpp +2 -11
  201. package/src/duckdb/src/storage/statistics/string_stats.cpp +273 -0
  202. package/src/duckdb/src/storage/statistics/struct_stats.cpp +131 -0
  203. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  204. package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +3 -4
  205. package/src/duckdb/src/storage/table/column_data.cpp +16 -11
  206. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +2 -3
  207. package/src/duckdb/src/storage/table/column_segment.cpp +6 -8
  208. package/src/duckdb/src/storage/table/list_column_data.cpp +39 -58
  209. package/src/duckdb/src/storage/table/row_group.cpp +24 -23
  210. package/src/duckdb/src/storage/table/row_group_collection.cpp +12 -12
  211. package/src/duckdb/src/storage/table/standard_column_data.cpp +6 -6
  212. package/src/duckdb/src/storage/table/struct_column_data.cpp +15 -16
  213. package/src/duckdb/src/storage/table/table_statistics.cpp +27 -7
  214. package/src/duckdb/src/storage/table/update_segment.cpp +10 -12
  215. package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +3 -0
  216. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +34 -1
  217. package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +1020 -530
  218. package/src/duckdb/third_party/libpg_query/include/parser/kwlist.hpp +7 -0
  219. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +23560 -22737
  220. package/src/duckdb/ub_src_function_aggregate_distributive.cpp +2 -0
  221. package/src/duckdb/ub_src_function_scalar_bit.cpp +2 -0
  222. package/src/duckdb/ub_src_function_scalar_map.cpp +4 -0
  223. package/src/duckdb/ub_src_main_capi.cpp +2 -0
  224. package/src/duckdb/ub_src_parser_parsed_data.cpp +4 -2
  225. package/src/duckdb/ub_src_parser_statement.cpp +2 -0
  226. package/src/duckdb/ub_src_parser_tableref.cpp +2 -0
  227. package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
  228. package/src/duckdb/ub_src_parser_transform_tableref.cpp +2 -0
  229. package/src/duckdb/ub_src_planner_binder_tableref.cpp +2 -0
  230. package/src/duckdb/ub_src_storage_statistics.cpp +4 -6
  231. package/src/duckdb/src/include/duckdb/main/loadable_extension.hpp +0 -59
  232. package/src/duckdb/src/include/duckdb/storage/statistics/list_statistics.hpp +0 -36
  233. package/src/duckdb/src/include/duckdb/storage/statistics/numeric_statistics.hpp +0 -75
  234. package/src/duckdb/src/include/duckdb/storage/statistics/string_statistics.hpp +0 -49
  235. package/src/duckdb/src/include/duckdb/storage/statistics/struct_statistics.hpp +0 -36
  236. package/src/duckdb/src/include/duckdb/storage/statistics/validity_statistics.hpp +0 -45
  237. package/src/duckdb/src/parser/parsed_data/alter_function_info.cpp +0 -55
  238. package/src/duckdb/src/storage/statistics/list_statistics.cpp +0 -94
  239. package/src/duckdb/src/storage/statistics/numeric_statistics.cpp +0 -307
  240. package/src/duckdb/src/storage/statistics/string_statistics.cpp +0 -220
  241. package/src/duckdb/src/storage/statistics/struct_statistics.cpp +0 -108
  242. package/src/duckdb/src/storage/statistics/validity_statistics.cpp +0 -91
@@ -0,0 +1,105 @@
1
+ #include "duckdb/common/exception.hpp"
2
+ #include "duckdb/parser/tableref/pivotref.hpp"
3
+ #include "duckdb/parser/transformer.hpp"
4
+ #include "duckdb/parser/expression/columnref_expression.hpp"
5
+ #include "duckdb/parser/expression/constant_expression.hpp"
6
+ #include "duckdb/parser/expression/function_expression.hpp"
7
+
8
+ namespace duckdb {
9
+
10
+ static void TransformPivotInList(unique_ptr<ParsedExpression> &expr, PivotColumnEntry &entry, bool root_entry = true) {
11
+ if (expr->type == ExpressionType::COLUMN_REF) {
12
+ auto &colref = (ColumnRefExpression &)*expr;
13
+ if (colref.IsQualified()) {
14
+ throw ParserException("PIVOT IN list cannot contain qualified column references");
15
+ }
16
+ entry.values.emplace_back(colref.GetColumnName());
17
+ } else if (expr->type == ExpressionType::VALUE_CONSTANT) {
18
+ auto &constant_expr = (ConstantExpression &)*expr;
19
+ entry.values.push_back(std::move(constant_expr.value));
20
+ } else if (root_entry && expr->type == ExpressionType::FUNCTION) {
21
+ auto &function = (FunctionExpression &)*expr;
22
+ if (function.function_name != "row") {
23
+ throw ParserException("PIVOT IN list must contain columns or lists of columns");
24
+ }
25
+ for (auto &child : function.children) {
26
+ TransformPivotInList(child, entry, false);
27
+ }
28
+ } else if (root_entry && expr->type == ExpressionType::STAR) {
29
+ entry.star_expr = std::move(expr);
30
+ } else {
31
+ throw ParserException("PIVOT IN list must contain columns or lists of columns");
32
+ }
33
+ }
34
+
35
+ PivotColumn Transformer::TransformPivotColumn(duckdb_libpgquery::PGPivot *pivot) {
36
+ PivotColumn col;
37
+ col.names = TransformStringList(pivot->pivot_columns);
38
+ if (pivot->pivot_value) {
39
+ for (auto node = pivot->pivot_value->head; node != nullptr; node = node->next) {
40
+ auto n = (duckdb_libpgquery::PGNode *)node->data.ptr_value;
41
+ auto expr = TransformExpression(n);
42
+ PivotColumnEntry entry;
43
+ entry.alias = expr->alias;
44
+ TransformPivotInList(expr, entry);
45
+ col.entries.push_back(std::move(entry));
46
+ }
47
+ }
48
+ if (pivot->pivot_enum) {
49
+ col.pivot_enum = pivot->pivot_enum;
50
+ }
51
+ return col;
52
+ }
53
+
54
+ vector<PivotColumn> Transformer::TransformPivotList(duckdb_libpgquery::PGList *list) {
55
+ vector<PivotColumn> result;
56
+ for (auto node = list->head; node != nullptr; node = node->next) {
57
+ auto pivot = (duckdb_libpgquery::PGPivot *)node->data.ptr_value;
58
+ result.push_back(TransformPivotColumn(pivot));
59
+ }
60
+ return result;
61
+ }
62
+
63
+ unique_ptr<TableRef> Transformer::TransformPivot(duckdb_libpgquery::PGPivotExpr *root) {
64
+ auto result = make_unique<PivotRef>();
65
+ result->source = TransformTableRefNode(root->source);
66
+ if (root->aggrs) {
67
+ TransformExpressionList(*root->aggrs, result->aggregates);
68
+ }
69
+ if (root->unpivots) {
70
+ result->unpivot_names = TransformStringList(root->unpivots);
71
+ }
72
+ result->pivots = TransformPivotList(root->pivots);
73
+ if (root->groups) {
74
+ result->groups = TransformStringList(root->groups);
75
+ }
76
+ for (auto &pivot : result->pivots) {
77
+ idx_t expected_size;
78
+ bool is_pivot = result->unpivot_names.empty();
79
+ if (!result->unpivot_names.empty()) {
80
+ // unpivot
81
+ if (pivot.names.size() != 1) {
82
+ throw ParserException("UNPIVOT requires a single column name for the PIVOT IN clause");
83
+ }
84
+ expected_size = pivot.entries[0].values.size();
85
+ } else {
86
+ // pivot
87
+ expected_size = pivot.names.size();
88
+ }
89
+ for (auto &entry : pivot.entries) {
90
+ if (entry.star_expr && is_pivot) {
91
+ throw ParserException("PIVOT IN list must contain columns or lists of columns - star expressions are "
92
+ "only supported for UNPIVOT");
93
+ }
94
+ if (entry.values.size() != expected_size) {
95
+ throw ParserException("PIVOT IN list - inconsistent amount of rows - expected %d but got %d",
96
+ expected_size, entry.values.size());
97
+ }
98
+ }
99
+ }
100
+ result->include_nulls = root->include_nulls;
101
+ result->alias = TransformAlias(root->alias, result->column_name_alias);
102
+ return std::move(result);
103
+ }
104
+
105
+ } // namespace duckdb
@@ -16,6 +16,8 @@ unique_ptr<TableRef> Transformer::TransformTableRefNode(duckdb_libpgquery::PGNod
16
16
  return TransformRangeSubselect(reinterpret_cast<duckdb_libpgquery::PGRangeSubselect *>(n));
17
17
  case duckdb_libpgquery::T_PGRangeFunction:
18
18
  return TransformRangeFunction(reinterpret_cast<duckdb_libpgquery::PGRangeFunction *>(n));
19
+ case duckdb_libpgquery::T_PGPivotExpr:
20
+ return TransformPivot(reinterpret_cast<duckdb_libpgquery::PGPivotExpr *>(n));
19
21
  default:
20
22
  throw NotImplementedException("From Type %d not supported", n->type);
21
23
  }
@@ -3,6 +3,7 @@
3
3
  #include "duckdb/parser/expression/list.hpp"
4
4
  #include "duckdb/parser/statement/list.hpp"
5
5
  #include "duckdb/parser/tableref/emptytableref.hpp"
6
+ #include "duckdb/parser/query_node/select_node.hpp"
6
7
 
7
8
  namespace duckdb {
8
9
 
@@ -28,12 +29,24 @@ Transformer::Transformer(Transformer *parent)
28
29
  : parent(parent), max_expression_depth(parent->max_expression_depth), stack_depth(DConstants::INVALID_INDEX) {
29
30
  }
30
31
 
32
+ Transformer::~Transformer() {
33
+ }
34
+
35
+ void Transformer::Clear() {
36
+ SetParamCount(0);
37
+ pivot_entries.clear();
38
+ }
39
+
31
40
  bool Transformer::TransformParseTree(duckdb_libpgquery::PGList *tree, vector<unique_ptr<SQLStatement>> &statements) {
32
41
  InitializeStackCheck();
33
42
  for (auto entry = tree->head; entry != nullptr; entry = entry->next) {
34
- SetParamCount(0);
35
- auto stmt = TransformStatement((duckdb_libpgquery::PGNode *)entry->data.ptr_value);
43
+ Clear();
44
+ auto n = (duckdb_libpgquery::PGNode *)entry->data.ptr_value;
45
+ auto stmt = TransformStatement(n);
36
46
  D_ASSERT(stmt);
47
+ if (HasPivotEntries()) {
48
+ stmt = CreatePivotStatement(std::move(stmt));
49
+ }
37
50
  stmt->n_param = ParamCount();
38
51
  statements.push_back(std::move(stmt));
39
52
  }
@@ -154,7 +167,6 @@ unique_ptr<SQLStatement> Transformer::TransformStatementInternal(duckdb_libpgque
154
167
  default:
155
168
  throw NotImplementedException(NodetypeToString(stmt->type));
156
169
  }
157
- return nullptr;
158
170
  }
159
171
 
160
172
  } // namespace duckdb
@@ -555,4 +555,20 @@ void BindContext::AddContext(BindContext other) {
555
555
  }
556
556
  }
557
557
 
558
+ void BindContext::RemoveContext(vector<std::pair<string, duckdb::Binding *>> &other_bindings_list) {
559
+ for (auto &other_binding : other_bindings_list) {
560
+ if (bindings.find(other_binding.first) != bindings.end()) {
561
+ bindings.erase(other_binding.first);
562
+ }
563
+ }
564
+
565
+ vector<idx_t> delete_list_indexes;
566
+ for (auto &other_binding : other_bindings_list) {
567
+ auto it =
568
+ std::remove_if(bindings_list.begin(), bindings_list.end(),
569
+ [other_binding](std::pair<string, Binding *> &x) { return x.first == other_binding.first; });
570
+ bindings_list.erase(it, bindings_list.end());
571
+ }
572
+ }
573
+
558
574
  } // namespace duckdb
@@ -328,6 +328,16 @@ void Binder::ExpandStarExpressions(vector<unique_ptr<ParsedExpression>> &select_
328
328
  }
329
329
 
330
330
  unique_ptr<BoundQueryNode> Binder::BindNode(SelectNode &statement) {
331
+ D_ASSERT(statement.from_table);
332
+ // first bind the FROM table statement
333
+ auto from = std::move(statement.from_table);
334
+ auto from_table = Bind(*from);
335
+ return BindSelectNode(statement, std::move(from_table));
336
+ }
337
+
338
+ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_ptr<BoundTableRef> from_table) {
339
+ D_ASSERT(from_table);
340
+ D_ASSERT(!statement.from_table);
331
341
  auto result = make_unique<BoundSelectNode>();
332
342
  result->projection_index = GenerateTableIndex();
333
343
  result->group_index = GenerateTableIndex();
@@ -337,9 +347,7 @@ unique_ptr<BoundQueryNode> Binder::BindNode(SelectNode &statement) {
337
347
  result->unnest_index = GenerateTableIndex();
338
348
  result->prune_index = GenerateTableIndex();
339
349
 
340
- // first bind the FROM table statement
341
- result->from_table = Bind(*statement.from_table);
342
-
350
+ result->from_table = std::move(from_table);
343
351
  // bind the sample clause
344
352
  if (statement.sample) {
345
353
  result->sample_options = std::move(statement.sample);
@@ -104,7 +104,6 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundSelectNode &statement) {
104
104
  PlanSubqueries(&expr, &root);
105
105
  }
106
106
 
107
- // create the projection
108
107
  auto proj = make_unique<LogicalProjection>(statement.projection_index, std::move(statement.select_list));
109
108
  auto &projection = *proj;
110
109
  proj->AddChild(std::move(root));
@@ -467,7 +467,6 @@ BoundStatement Binder::Bind(CreateStatement &stmt) {
467
467
  BoundStatement result;
468
468
  result.names = {"Count"};
469
469
  result.types = {LogicalType::BIGINT};
470
- properties.return_type = StatementReturnType::NOTHING;
471
470
 
472
471
  auto catalog_type = stmt.info->type;
473
472
  switch (catalog_type) {
@@ -675,6 +674,7 @@ BoundStatement Binder::Bind(CreateStatement &stmt) {
675
674
  default:
676
675
  throw Exception("Unrecognized type!");
677
676
  }
677
+ properties.return_type = StatementReturnType::NOTHING;
678
678
  properties.allow_stream_result = false;
679
679
  return result;
680
680
  }
@@ -4,6 +4,19 @@
4
4
 
5
5
  namespace duckdb {
6
6
 
7
+ idx_t GetMaxTableIndex(LogicalOperator &op) {
8
+ idx_t result = 0;
9
+ for (auto &child : op.children) {
10
+ auto max_child_index = GetMaxTableIndex(*child);
11
+ result = MaxValue<idx_t>(result, max_child_index);
12
+ }
13
+ auto indexes = op.GetTableIndex();
14
+ for (auto &index : indexes) {
15
+ result = MaxValue<idx_t>(result, index);
16
+ }
17
+ return result;
18
+ }
19
+
7
20
  BoundStatement Binder::Bind(LogicalPlanStatement &stmt) {
8
21
  BoundStatement result;
9
22
  result.types = stmt.plan->types;
@@ -14,6 +27,10 @@ BoundStatement Binder::Bind(LogicalPlanStatement &stmt) {
14
27
  properties.allow_stream_result = true;
15
28
  properties.return_type = StatementReturnType::QUERY_RESULT; // TODO could also be something else
16
29
 
30
+ if (parent) {
31
+ throw InternalException("LogicalPlanStatement should be bound in root binder");
32
+ }
33
+ bound_tables = GetMaxTableIndex(*result.plan) + 1;
17
34
  return result;
18
35
  }
19
36
 
@@ -7,9 +7,11 @@
7
7
  #include "duckdb/parser/expression/constant_expression.hpp"
8
8
  #include "duckdb/parser/expression/conjunction_expression.hpp"
9
9
  #include "duckdb/parser/expression/bound_expression.hpp"
10
+ #include "duckdb/parser/expression/star_expression.hpp"
10
11
  #include "duckdb/common/string_util.hpp"
11
12
  #include "duckdb/common/case_insensitive_map.hpp"
12
13
  #include "duckdb/planner/expression_binder/lateral_binder.hpp"
14
+ #include "duckdb/planner/query_node/bound_select_node.hpp"
13
15
 
14
16
  namespace duckdb {
15
17
 
@@ -253,6 +255,8 @@ unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) {
253
255
  }
254
256
  }
255
257
 
258
+ auto right_bindings_list_copy = right_binder.bind_context.GetBindingsList();
259
+
256
260
  bind_context.AddContext(std::move(left_binder.bind_context));
257
261
  bind_context.AddContext(std::move(right_binder.bind_context));
258
262
  MoveCorrelatedExpressions(left_binder);
@@ -269,6 +273,11 @@ unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) {
269
273
  WhereBinder binder(*this, context);
270
274
  result->condition = binder.Bind(ref.condition);
271
275
  }
276
+
277
+ if (result->type == JoinType::SEMI || result->type == JoinType::ANTI) {
278
+ bind_context.RemoveContext(right_bindings_list_copy);
279
+ }
280
+
272
281
  return std::move(result);
273
282
  }
274
283
 
@@ -0,0 +1,365 @@
1
+ #include "duckdb/planner/binder.hpp"
2
+ #include "duckdb/parser/tableref/pivotref.hpp"
3
+ #include "duckdb/parser/tableref/subqueryref.hpp"
4
+ #include "duckdb/parser/query_node/select_node.hpp"
5
+ #include "duckdb/parser/expression/case_expression.hpp"
6
+ #include "duckdb/parser/expression/columnref_expression.hpp"
7
+ #include "duckdb/parser/expression/comparison_expression.hpp"
8
+ #include "duckdb/parser/expression/conjunction_expression.hpp"
9
+ #include "duckdb/parser/expression/constant_expression.hpp"
10
+ #include "duckdb/parser/expression/function_expression.hpp"
11
+ #include "duckdb/planner/query_node/bound_select_node.hpp"
12
+ #include "duckdb/parser/expression/star_expression.hpp"
13
+ #include "duckdb/common/types/value_map.hpp"
14
+ #include "duckdb/parser/parsed_expression_iterator.hpp"
15
+ #include "duckdb/parser/expression/operator_expression.hpp"
16
+ #include "duckdb/planner/tableref/bound_subqueryref.hpp"
17
+
18
+ namespace duckdb {
19
+
20
+ static void ConstructPivots(PivotRef &ref, idx_t pivot_idx, vector<unique_ptr<ParsedExpression>> &pivot_expressions,
21
+ unique_ptr<ParsedExpression> current_expr = nullptr,
22
+ const string &current_name = string()) {
23
+ auto &pivot = ref.pivots[pivot_idx];
24
+ bool last_pivot = pivot_idx + 1 == ref.pivots.size();
25
+ for (auto &entry : pivot.entries) {
26
+ unique_ptr<ParsedExpression> expr = current_expr ? current_expr->Copy() : nullptr;
27
+ string name = entry.alias;
28
+ D_ASSERT(entry.values.size() == pivot.names.size());
29
+ for (idx_t v = 0; v < entry.values.size(); v++) {
30
+ auto &value = entry.values[v];
31
+ auto column_ref = make_unique<ColumnRefExpression>(pivot.names[v]);
32
+ auto constant_value = make_unique<ConstantExpression>(value);
33
+ auto comp_expr = make_unique<ComparisonExpression>(ExpressionType::COMPARE_NOT_DISTINCT_FROM,
34
+ std::move(column_ref), std::move(constant_value));
35
+ if (expr) {
36
+ expr = make_unique<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND, std::move(expr),
37
+ std::move(comp_expr));
38
+ } else {
39
+ expr = std::move(comp_expr);
40
+ }
41
+ if (entry.alias.empty()) {
42
+ if (name.empty()) {
43
+ name = value.ToString();
44
+ } else {
45
+ name += "_" + value.ToString();
46
+ }
47
+ }
48
+ }
49
+ if (!current_name.empty()) {
50
+ name = current_name + "_" + name;
51
+ }
52
+ if (last_pivot) {
53
+ // construct the aggregates
54
+ for (auto &aggr : ref.aggregates) {
55
+ auto copy = aggr->Copy();
56
+ auto &function = (FunctionExpression &)*copy;
57
+ // add the filter and alias to the aggregate function
58
+ function.filter = expr->Copy();
59
+ if (ref.aggregates.size() > 1) {
60
+ // if there are multiple aggregates specified we add the name of the aggregate as well
61
+ function.alias = name + "_" + function.GetName();
62
+ } else {
63
+ function.alias = name;
64
+ }
65
+ pivot_expressions.push_back(std::move(copy));
66
+ }
67
+ } else {
68
+ // need to recurse
69
+ ConstructPivots(ref, pivot_idx + 1, pivot_expressions, std::move(expr), name);
70
+ }
71
+ }
72
+ }
73
+
74
+ static void ExtractPivotExpressions(ParsedExpression &expr, case_insensitive_set_t &handled_columns) {
75
+ if (expr.type == ExpressionType::COLUMN_REF) {
76
+ auto &child_colref = (ColumnRefExpression &)expr;
77
+ if (child_colref.IsQualified()) {
78
+ throw BinderException("PIVOT expression cannot contain qualified columns");
79
+ }
80
+ handled_columns.insert(child_colref.GetColumnName());
81
+ }
82
+ ParsedExpressionIterator::EnumerateChildren(
83
+ expr, [&](ParsedExpression &child) { ExtractPivotExpressions(child, handled_columns); });
84
+ }
85
+
86
+ unique_ptr<SelectNode> Binder::BindPivot(PivotRef &ref, vector<unique_ptr<ParsedExpression>> all_columns) {
87
+ const static idx_t PIVOT_EXPRESSION_LIMIT = 10000;
88
+ // keep track of the columns by which we pivot/aggregate
89
+ // any columns which are not pivoted/aggregated on are added to the GROUP BY clause
90
+ case_insensitive_set_t handled_columns;
91
+ // parse the aggregate, and extract the referenced columns from the aggregate
92
+ for (auto &aggr : ref.aggregates) {
93
+ if (aggr->type != ExpressionType::FUNCTION) {
94
+ throw BinderException(FormatError(*aggr, "Pivot expression must be an aggregate"));
95
+ }
96
+ if (aggr->HasSubquery()) {
97
+ throw BinderException(FormatError(*aggr, "Pivot expression cannot contain subqueries"));
98
+ }
99
+ if (aggr->IsWindow()) {
100
+ throw BinderException(FormatError(*aggr, "Pivot expression cannot contain window functions"));
101
+ }
102
+ ExtractPivotExpressions(*aggr, handled_columns);
103
+ }
104
+ value_set_t pivots;
105
+
106
+ // now handle the pivots
107
+ auto select_node = make_unique<SelectNode>();
108
+ // first add all pivots to the set of handled columns, and check for duplicates
109
+ idx_t total_pivots = 1;
110
+ for (auto &pivot : ref.pivots) {
111
+ if (!pivot.pivot_enum.empty()) {
112
+ auto type = Catalog::GetType(context, INVALID_CATALOG, INVALID_SCHEMA, pivot.pivot_enum);
113
+ if (type.id() != LogicalTypeId::ENUM) {
114
+ throw BinderException(
115
+ FormatError(ref, StringUtil::Format("Pivot must reference an ENUM type: \"%s\" is of type \"%s\"",
116
+ pivot.pivot_enum, type.ToString())));
117
+ }
118
+ auto enum_size = EnumType::GetSize(type);
119
+ for (idx_t i = 0; i < enum_size; i++) {
120
+ auto enum_value = EnumType::GetValue(Value::ENUM(i, type));
121
+ PivotColumnEntry entry;
122
+ entry.values.emplace_back(enum_value);
123
+ entry.alias = std::move(enum_value);
124
+ pivot.entries.push_back(std::move(entry));
125
+ }
126
+ }
127
+ total_pivots *= pivot.entries.size();
128
+ // add the pivoted column to the columns that have been handled
129
+ for (auto &pivot_name : pivot.names) {
130
+ handled_columns.insert(pivot_name);
131
+ }
132
+ value_set_t pivots;
133
+ for (auto &entry : pivot.entries) {
134
+ D_ASSERT(!entry.star_expr);
135
+ Value val;
136
+ if (entry.values.size() == 1) {
137
+ val = entry.values[0];
138
+ } else {
139
+ val = Value::LIST(LogicalType::VARCHAR, entry.values);
140
+ }
141
+ if (pivots.find(val) != pivots.end()) {
142
+ throw BinderException(FormatError(
143
+ ref, StringUtil::Format("The value \"%s\" was specified multiple times in the IN clause",
144
+ val.ToString())));
145
+ }
146
+ if (entry.values.size() != pivot.names.size()) {
147
+ throw ParserException("PIVOT IN list - inconsistent amount of rows - expected %d but got %d",
148
+ pivot.names.size(), entry.values.size());
149
+ }
150
+ pivots.insert(val);
151
+ }
152
+ }
153
+ if (total_pivots >= PIVOT_EXPRESSION_LIMIT) {
154
+ throw BinderException("Pivot column limit of %llu exceeded", PIVOT_EXPRESSION_LIMIT);
155
+ }
156
+ // now construct the actual aggregates
157
+ // note that we construct a cross-product of all pivots
158
+ // we do this recursively
159
+ vector<unique_ptr<ParsedExpression>> pivot_expressions;
160
+ ConstructPivots(ref, 0, pivot_expressions);
161
+
162
+ if (ref.groups.empty()) {
163
+ // if rows are not specified any columns that are not pivoted/aggregated on are added to the GROUP BY clause
164
+ for (auto &entry : all_columns) {
165
+ if (entry->type != ExpressionType::COLUMN_REF) {
166
+ throw InternalException("Unexpected child of pivot source - not a ColumnRef");
167
+ }
168
+ auto &columnref = (ColumnRefExpression &)*entry;
169
+ if (handled_columns.find(columnref.GetColumnName()) == handled_columns.end()) {
170
+ // not handled - add to grouping set
171
+ select_node->groups.group_expressions.push_back(
172
+ make_unique<ConstantExpression>(Value::INTEGER(select_node->select_list.size() + 1)));
173
+ select_node->select_list.push_back(std::move(entry));
174
+ }
175
+ }
176
+ } else {
177
+ // if rows are specified only the columns mentioned in rows are added as groups
178
+ for (auto &row : ref.groups) {
179
+ select_node->groups.group_expressions.push_back(
180
+ make_unique<ConstantExpression>(Value::INTEGER(select_node->select_list.size() + 1)));
181
+ select_node->select_list.push_back(make_unique<ColumnRefExpression>(row));
182
+ }
183
+ }
184
+ // add the pivot expressions to the select list
185
+ for (auto &pivot_expr : pivot_expressions) {
186
+ select_node->select_list.push_back(std::move(pivot_expr));
187
+ }
188
+ return select_node;
189
+ }
190
+
191
+ unique_ptr<SelectNode> Binder::BindUnpivot(Binder &child_binder, PivotRef &ref,
192
+ vector<unique_ptr<ParsedExpression>> all_columns,
193
+ unique_ptr<ParsedExpression> &where_clause) {
194
+ D_ASSERT(ref.groups.empty());
195
+ D_ASSERT(ref.pivots.size() == 1);
196
+
197
+ unique_ptr<ParsedExpression> expr;
198
+ auto select_node = make_unique<SelectNode>();
199
+
200
+ // handle the pivot
201
+ auto &unpivot = ref.pivots[0];
202
+
203
+ // handle star expressions in any entries
204
+ vector<PivotColumnEntry> new_entries;
205
+ for (auto &entry : unpivot.entries) {
206
+ if (entry.star_expr) {
207
+ D_ASSERT(entry.values.empty());
208
+ vector<unique_ptr<ParsedExpression>> star_columns;
209
+ child_binder.ExpandStarExpression(std::move(entry.star_expr), star_columns);
210
+
211
+ for (auto &col : star_columns) {
212
+ if (col->type != ExpressionType::COLUMN_REF) {
213
+ throw InternalException("Unexpected child of unpivot star - not a ColumnRef");
214
+ }
215
+ auto &columnref = (ColumnRefExpression &)*col;
216
+ PivotColumnEntry new_entry;
217
+ new_entry.values.emplace_back(columnref.GetColumnName());
218
+ new_entry.alias = columnref.GetColumnName();
219
+ new_entries.push_back(std::move(new_entry));
220
+ }
221
+ } else {
222
+ new_entries.push_back(std::move(entry));
223
+ }
224
+ }
225
+ unpivot.entries = std::move(new_entries);
226
+
227
+ case_insensitive_set_t handled_columns;
228
+ case_insensitive_map_t<string> name_map;
229
+ for (auto &entry : unpivot.entries) {
230
+ for (auto &value : entry.values) {
231
+ handled_columns.insert(value.ToString());
232
+ }
233
+ }
234
+
235
+ for (auto &col_expr : all_columns) {
236
+ if (col_expr->type != ExpressionType::COLUMN_REF) {
237
+ throw InternalException("Unexpected child of pivot source - not a ColumnRef");
238
+ }
239
+ auto &columnref = (ColumnRefExpression &)*col_expr;
240
+ auto &column_name = columnref.GetColumnName();
241
+ auto entry = handled_columns.find(column_name);
242
+ if (entry == handled_columns.end()) {
243
+ // not handled - add to the set of regularly selected columns
244
+ select_node->select_list.push_back(std::move(col_expr));
245
+ } else {
246
+ name_map[column_name] = column_name;
247
+ handled_columns.erase(entry);
248
+ }
249
+ }
250
+ if (!handled_columns.empty()) {
251
+ for (auto &entry : handled_columns) {
252
+ throw BinderException("Column \"%s\" referenced in UNPIVOT but no matching entry was found in the table",
253
+ entry);
254
+ }
255
+ }
256
+ vector<Value> unpivot_names;
257
+ for (auto &entry : unpivot.entries) {
258
+ string generated_name;
259
+ for (auto &val : entry.values) {
260
+ auto name_entry = name_map.find(val.ToString());
261
+ if (name_entry == name_map.end()) {
262
+ throw InternalException("Unpivot - could not find column name in name map");
263
+ }
264
+ if (!generated_name.empty()) {
265
+ generated_name += "_";
266
+ }
267
+ generated_name += name_entry->second;
268
+ }
269
+ unpivot_names.emplace_back(!entry.alias.empty() ? entry.alias : generated_name);
270
+ }
271
+ vector<vector<unique_ptr<ParsedExpression>>> unpivot_expressions;
272
+ for (idx_t v_idx = 0; v_idx < unpivot.entries[0].values.size(); v_idx++) {
273
+ vector<unique_ptr<ParsedExpression>> expressions;
274
+ for (auto &entry : unpivot.entries) {
275
+ expressions.push_back(make_unique<ColumnRefExpression>(entry.values[v_idx].ToString()));
276
+ }
277
+ unpivot_expressions.push_back(std::move(expressions));
278
+ }
279
+
280
+ // construct the UNNEST expression for the set of names (constant)
281
+ auto unpivot_list = Value::LIST(LogicalType::VARCHAR, std::move(unpivot_names));
282
+ auto unpivot_name_expr = make_unique<ConstantExpression>(std::move(unpivot_list));
283
+ vector<unique_ptr<ParsedExpression>> unnest_name_children;
284
+ unnest_name_children.push_back(std::move(unpivot_name_expr));
285
+ auto unnest_name_expr = make_unique<FunctionExpression>("unnest", std::move(unnest_name_children));
286
+ unnest_name_expr->alias = unpivot.names[0];
287
+ select_node->select_list.push_back(std::move(unnest_name_expr));
288
+
289
+ // construct the UNNEST expression for the set of unpivoted columns
290
+ if (ref.unpivot_names.size() != unpivot_expressions.size()) {
291
+ throw BinderException("UNPIVOT name count mismatch - got %d names but %d expressions", ref.unpivot_names.size(),
292
+ unpivot_expressions.size());
293
+ }
294
+ for (idx_t i = 0; i < unpivot_expressions.size(); i++) {
295
+ auto list_expr = make_unique<FunctionExpression>("list_value", std::move(unpivot_expressions[i]));
296
+ vector<unique_ptr<ParsedExpression>> unnest_val_children;
297
+ unnest_val_children.push_back(std::move(list_expr));
298
+ auto unnest_val_expr = make_unique<FunctionExpression>("unnest", std::move(unnest_val_children));
299
+ auto unnest_name = i < ref.column_name_alias.size() ? ref.column_name_alias[i] : ref.unpivot_names[i];
300
+ unnest_val_expr->alias = unnest_name;
301
+ select_node->select_list.push_back(std::move(unnest_val_expr));
302
+ if (!ref.include_nulls) {
303
+ // if we are running with EXCLUDE NULLS we need to add an IS NOT NULL filter
304
+ auto colref = make_unique<ColumnRefExpression>(unnest_name);
305
+ auto filter = make_unique<OperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, std::move(colref));
306
+ if (where_clause) {
307
+ where_clause = make_unique<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND,
308
+ std::move(where_clause), std::move(filter));
309
+ } else {
310
+ where_clause = std::move(filter);
311
+ }
312
+ }
313
+ }
314
+ return select_node;
315
+ }
316
+
317
+ unique_ptr<BoundTableRef> Binder::Bind(PivotRef &ref) {
318
+ if (!ref.source) {
319
+ throw InternalException("Pivot without a source!?");
320
+ }
321
+
322
+ // bind the source of the pivot
323
+ auto child_binder = Binder::CreateBinder(context, this);
324
+ auto from_table = child_binder->Bind(*ref.source);
325
+
326
+ // figure out the set of column names that are in the source of the pivot
327
+ vector<unique_ptr<ParsedExpression>> all_columns;
328
+ child_binder->ExpandStarExpression(make_unique<StarExpression>(), all_columns);
329
+
330
+ unique_ptr<SelectNode> select_node;
331
+ unique_ptr<ParsedExpression> where_clause;
332
+ if (!ref.aggregates.empty()) {
333
+ select_node = BindPivot(ref, std::move(all_columns));
334
+ } else {
335
+ select_node = BindUnpivot(*child_binder, ref, std::move(all_columns), where_clause);
336
+ }
337
+ // bind the generated select node
338
+ auto bound_select_node = child_binder->BindSelectNode(*select_node, std::move(from_table));
339
+ auto root_index = bound_select_node->GetRootIndex();
340
+ BoundQueryNode *bound_select_ptr = bound_select_node.get();
341
+
342
+ unique_ptr<BoundTableRef> result;
343
+ MoveCorrelatedExpressions(*child_binder);
344
+ result = make_unique<BoundSubqueryRef>(std::move(child_binder), std::move(bound_select_node));
345
+ auto alias = ref.alias.empty() ? "__unnamed_pivot" : ref.alias;
346
+ SubqueryRef subquery_ref(nullptr, alias);
347
+ subquery_ref.column_name_alias = std::move(ref.column_name_alias);
348
+ if (where_clause) {
349
+ // if a WHERE clause was provided - bind a subquery holding the WHERE clause
350
+ // we need to bind a new subquery here because the WHERE clause has to be applied AFTER the unnest
351
+ child_binder = Binder::CreateBinder(context, this);
352
+ child_binder->bind_context.AddSubquery(root_index, subquery_ref.alias, subquery_ref, *bound_select_ptr);
353
+ auto where_query = make_unique<SelectNode>();
354
+ where_query->select_list.push_back(make_unique<StarExpression>());
355
+ where_query->where_clause = std::move(where_clause);
356
+ bound_select_node = child_binder->BindSelectNode(*where_query, std::move(result));
357
+ bound_select_ptr = bound_select_node.get();
358
+ root_index = bound_select_node->GetRootIndex();
359
+ result = make_unique<BoundSubqueryRef>(std::move(child_binder), std::move(bound_select_node));
360
+ }
361
+ bind_context.AddSubquery(root_index, subquery_ref.alias, subquery_ref, *bound_select_ptr);
362
+ return result;
363
+ }
364
+
365
+ } // namespace duckdb