| 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 | |