Repository: duckdb/duckdb
File: src/planner/binder/expression/bind_unnest_expression.cpp (C++)

Code before:
	}
	// now perform struct unnests, if any
	if (struct_unnests > 0) {
		vector<unique_ptr<Expression>> struct_expressions;
		struct_expressions.push_back(std::move(unnest_expr));
		for (idx_t i = 0; i < struct_unnests; i++) {
			vector<unique_ptr<Expression>> new_expressions;
			// check if there are any structs left
			bool has_structs = false;
			for (auto &expr : struct_expressions) {
				if (expr->return_type.id() == LogicalTypeId::STRUCT) {
					// struct! push a struct_extract
					auto &child_types = StructType::GetChildTypes(expr->return_type);
					if (StructType::IsUnnamed(expr->return_type)) {
						for (idx_t child_index = 0; child_index < child_types.size(); child_index++) {
							new_expressions.push_back(
							    CreateBoundStructExtractIndex(context, expr->Copy(), child_index + 1));
						}
					} else {
						for (auto &entry : child_types) {
							vector<string> current_key_path;
							// During recursive expansion, not all expressions are BoundFunctionExpression
							if (keep_parent_names && expr->type == ExpressionType::BOUND_FUNCTION) {
								current_key_path.push_back(expr->alias);
							}
							new_expressions.push_back(CreateBoundStructExtract(context, expr->Copy(), entry.first,
							                                                   current_key_path, keep_parent_names));
						}
					}
					has_structs = true;
				} else {
					// not a struct - push as-is
					new_expressions.push_back(std::move(expr));
				}
			}
			struct_expressions = std::move(new_expressions);
			if (!has_structs) {
				break;
			}
		}
		unnest_expr = make_uniq<BoundExpandedExpression>(std::move(struct_expressions));
	}
	return BindResult(std::move(unnest_expr));
}

} // namespace duckdb


Review comment (refactor):
if `keep_parent_names` is true we call `full_path.push_back(key);` in `CreateBoundStructExtract()`. Maybe we can push `entry.first` into `current_key_path` here? Then we can also pass one less argument to `CreateBoundStructExtract`

Code after:
	if (struct_unnests > 0) {
		vector<unique_ptr<Expression>> struct_expressions;
		struct_expressions.push_back(std::move(unnest_expr));
		for (idx_t i = 0; i < struct_unnests; i++) {
			vector<unique_ptr<Expression>> new_expressions;
			// check if there are any structs left
			bool has_structs = false;
			for (auto &expr : struct_expressions) {
				if (expr->return_type.id() == LogicalTypeId::STRUCT) {
					// struct! push a struct_extract
					auto &child_types = StructType::GetChildTypes(expr->return_type);
					if (StructType::IsUnnamed(expr->return_type)) {
						for (idx_t child_index = 0; child_index < child_types.size(); child_index++) {
							new_expressions.push_back(
							    CreateBoundStructExtractIndex(context, expr->Copy(), child_index + 1));
						}
					} else {
						for (auto &entry : child_types) {
							vector<string> current_key_path;
							// During recursive expansion, not all expressions are BoundFunctionExpression
							if (keep_parent_names && expr->type == ExpressionType::BOUND_FUNCTION) {
								current_key_path.push_back(expr->alias);
							}
							current_key_path.push_back(entry.first);
							new_expressions.push_back(
							    CreateBoundStructExtract(context, expr->Copy(), current_key_path, keep_parent_names));
						}
					}
					has_structs = true;
				} else {
					// not a struct - push as-is
					new_expressions.push_back(std::move(expr));
				}
			}
			struct_expressions = std::move(new_expressions);
			if (!has_structs) {
				break;
			}
		}
		unnest_expr = make_uniq<BoundExpandedExpression>(std::move(struct_expressions));
	}
	return BindResult(std::move(unnest_expr));
}

} // namespace duckdb