1 | #include "duckdb/planner/binder.hpp" |
2 | #include "duckdb/planner/tableref/bound_expressionlistref.hpp" |
3 | #include "duckdb/parser/tableref/expressionlistref.hpp" |
4 | #include "duckdb/planner/expression_binder/insert_binder.hpp" |
5 | #include "duckdb/common/to_string.hpp" |
6 | #include "duckdb/planner/expression/bound_cast_expression.hpp" |
7 | |
8 | namespace duckdb { |
9 | |
10 | unique_ptr<BoundTableRef> Binder::Bind(ExpressionListRef &expr) { |
11 | auto result = make_uniq<BoundExpressionListRef>(); |
12 | result->types = expr.expected_types; |
13 | result->names = expr.expected_names; |
14 | // bind value list |
15 | InsertBinder binder(*this, context); |
16 | binder.target_type = LogicalType(LogicalTypeId::INVALID); |
17 | for (idx_t list_idx = 0; list_idx < expr.values.size(); list_idx++) { |
18 | auto &expression_list = expr.values[list_idx]; |
19 | if (result->names.empty()) { |
20 | // no names provided, generate them |
21 | for (idx_t val_idx = 0; val_idx < expression_list.size(); val_idx++) { |
22 | result->names.push_back(x: "col" + to_string(val: val_idx)); |
23 | } |
24 | } |
25 | |
26 | vector<unique_ptr<Expression>> list; |
27 | for (idx_t val_idx = 0; val_idx < expression_list.size(); val_idx++) { |
28 | if (!result->types.empty()) { |
29 | D_ASSERT(result->types.size() == expression_list.size()); |
30 | binder.target_type = result->types[val_idx]; |
31 | } |
32 | auto expr = binder.Bind(expr&: expression_list[val_idx]); |
33 | list.push_back(x: std::move(expr)); |
34 | } |
35 | result->values.push_back(x: std::move(list)); |
36 | } |
37 | if (result->types.empty() && !expr.values.empty()) { |
38 | // there are no types specified |
39 | // we have to figure out the result types |
40 | // for each column, we iterate over all of the expressions and select the max logical type |
41 | // we initialize all types to SQLNULL |
42 | result->types.resize(new_size: expr.values[0].size(), x: LogicalType::SQLNULL); |
43 | // now loop over the lists and select the max logical type |
44 | for (idx_t list_idx = 0; list_idx < result->values.size(); list_idx++) { |
45 | auto &list = result->values[list_idx]; |
46 | for (idx_t val_idx = 0; val_idx < list.size(); val_idx++) { |
47 | result->types[val_idx] = |
48 | LogicalType::MaxLogicalType(left: result->types[val_idx], right: list[val_idx]->return_type); |
49 | } |
50 | } |
51 | // finally do another loop over the expressions and add casts where required |
52 | for (idx_t list_idx = 0; list_idx < result->values.size(); list_idx++) { |
53 | auto &list = result->values[list_idx]; |
54 | for (idx_t val_idx = 0; val_idx < list.size(); val_idx++) { |
55 | list[val_idx] = |
56 | BoundCastExpression::AddCastToType(context, expr: std::move(list[val_idx]), target_type: result->types[val_idx]); |
57 | } |
58 | } |
59 | } |
60 | result->bind_index = GenerateTableIndex(); |
61 | bind_context.AddGenericBinding(index: result->bind_index, alias: expr.alias, names: result->names, types: result->types); |
62 | return std::move(result); |
63 | } |
64 | |
65 | } // namespace duckdb |
66 | |