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