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
8namespace duckdb {
9
10unique_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