1#include "duckdb/planner/expression_binder/select_binder.hpp"
2
3#include "duckdb/parser/expression/columnref_expression.hpp"
4#include "duckdb/parser/expression/window_expression.hpp"
5#include "duckdb/parser/parsed_expression_iterator.hpp"
6#include "duckdb/planner/expression/bound_columnref_expression.hpp"
7#include "duckdb/planner/expression/bound_window_expression.hpp"
8#include "duckdb/planner/expression_binder/aggregate_binder.hpp"
9#include "duckdb/planner/query_node/bound_select_node.hpp"
10
11using namespace duckdb;
12using namespace std;
13
14SelectBinder::SelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info)
15 : ExpressionBinder(binder, context), inside_window(false), node(node), info(info) {
16}
17
18BindResult SelectBinder::BindExpression(ParsedExpression &expr, idx_t depth, bool root_expression) {
19 // check if the expression binds to one of the groups
20 auto group_index = TryBindGroup(expr, depth);
21 if (group_index != INVALID_INDEX) {
22 return BindGroup(expr, depth, group_index);
23 }
24 switch (expr.expression_class) {
25 case ExpressionClass::DEFAULT:
26 return BindResult("SELECT clause cannot contain DEFAULT clause");
27 case ExpressionClass::WINDOW:
28 return BindWindow((WindowExpression &)expr, depth);
29 default:
30 return ExpressionBinder::BindExpression(expr, depth);
31 }
32}
33
34idx_t SelectBinder::TryBindGroup(ParsedExpression &expr, idx_t depth) {
35 // first check the group alias map, if expr is a ColumnRefExpression
36 if (expr.type == ExpressionType::COLUMN_REF) {
37 auto &colref = (ColumnRefExpression &)expr;
38 if (colref.table_name.empty()) {
39 auto alias_entry = info.alias_map.find(colref.column_name);
40 if (alias_entry != info.alias_map.end()) {
41 // found entry!
42 return alias_entry->second;
43 }
44 }
45 }
46 // no alias reference found
47 // check the list of group columns for a match
48 auto entry = info.map.find(&expr);
49 if (entry != info.map.end()) {
50 return entry->second;
51 }
52#ifdef DEBUG
53 for (auto entry : info.map) {
54 assert(!entry.first->Equals(&expr));
55 assert(!expr.Equals(entry.first));
56 }
57#endif
58 return INVALID_INDEX;
59}
60
61BindResult SelectBinder::BindGroup(ParsedExpression &expr, idx_t depth, idx_t group_index) {
62 auto &group = node.groups[group_index];
63
64 return BindResult(make_unique<BoundColumnRefExpression>(expr.GetName(), group->return_type,
65 ColumnBinding(node.group_index, group_index), depth),
66 info.group_types[group_index]);
67}
68