1#include "duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp"
2#include "duckdb/main/client_context.hpp"
3#include "duckdb/parser/expression/function_expression.hpp"
4#include "duckdb/planner/expression/bound_aggregate_expression.hpp"
5#include "duckdb/planner/expression/bound_columnref_expression.hpp"
6#include "duckdb/planner/expression_binder/aggregate_binder.hpp"
7#include "duckdb/planner/expression_binder/select_binder.hpp"
8#include "duckdb/planner/query_node/bound_select_node.hpp"
9#include "duckdb/planner/expression/bound_unnest_expression.hpp"
10
11using namespace duckdb;
12using namespace std;
13
14BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) {
15 // bind the children of the function expression
16 string error;
17 if (function.children.size() != 1) {
18 return BindResult("Unnest() needs exactly one child expressions");
19 }
20 BindChild(function.children[0], depth, error);
21 if (!error.empty()) {
22 return BindResult(error);
23 }
24 auto &child = (BoundExpression &)*function.children[0];
25 if (child.sql_type.id != SQLTypeId::LIST) {
26 return BindResult("Unnest() can only be applied to lists");
27 }
28 SQLType return_type = SQLType::ANY;
29 assert(child.sql_type.child_type.size() <= 1);
30 if (child.sql_type.child_type.size() == 1) {
31 return_type = child.sql_type.child_type[0].second;
32 }
33
34 auto result = make_unique<BoundUnnestExpression>(return_type);
35 result->child = move(child.expr);
36
37 auto unnest_index = node.unnests.size();
38 node.unnests.push_back(move(result));
39
40 // TODO what if we have multiple unnests in the same projection list? ignore for now
41
42 // now create a column reference referring to the aggregate
43 auto colref = make_unique<BoundColumnRefExpression>(
44 function.alias.empty() ? node.unnests[unnest_index]->ToString() : function.alias,
45 node.unnests[unnest_index]->return_type, ColumnBinding(node.unnest_index, unnest_index), depth);
46 // move the aggregate expression into the set of bound aggregates
47 return BindResult(move(colref), return_type);
48}
49