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

Code before:
#include "duckdb/planner/binder.hpp"
#include "duckdb/planner/expression/bound_cast_expression.hpp"
#include "duckdb/planner/expression/bound_constant_expression.hpp"
#include "duckdb/planner/expression/bound_function_expression.hpp"
#include "duckdb/planner/expression/bound_lambda_expression.hpp"
#include "duckdb/planner/expression/bound_reference_expression.hpp"
#include "duckdb/planner/expression_binder.hpp"

namespace duckdb {

BindResult ExpressionBinder::TryBindLambdaOrJson(FunctionExpression &function, idx_t depth, CatalogEntry &func,
                                                 const LambdaSyntaxType syntax_type) {
	if (syntax_type == LambdaSyntaxType::LAMBDA_KEYWORD) {
		// lambda x: x + 1 syntax.
		return BindLambdaFunction(function, func.Cast<ScalarFunctionCatalogEntry>(), depth);
	}

	auto &config = ClientConfig::GetConfig(context);
	auto setting = config.lambda_syntax;
	bool invalid_syntax =
	    setting == LambdaSyntax::DISABLE_SINGLE_ARROW && syntax_type == LambdaSyntaxType::SINGLE_ARROW;
	const string msg = "Deprecated lambda arrow (->) detected. Please transition to the new lambda syntax, "
	                   "i.e.., lambda x, i: x + i, before DuckDB's next release. \n"
	                   "Use SET lambda_syntax='ENABLE_SINGLE_ARROW' to revert to the deprecated behavior. \n"
	                   "For more information, see https://duckdb.org/docs/stable/sql/functions/lambda.html.";
	DUCKDB_LOG_WARN(context, msg);

	BindResult lambda_bind_result;
	ErrorData error;
	try {
		lambda_bind_result = BindLambdaFunction(function, func.Cast<ScalarFunctionCatalogEntry>(), depth);
	} catch (const std::exception &ex) {
		error = ErrorData(ex);
	}

	if (error.HasError() && error.Type() == ExceptionType::PARAMETER_NOT_RESOLVED && invalid_syntax) {
		ErrorData deprecation_error(ExceptionType::BINDER, msg);
		deprecation_error.Throw();
	} else if (error.HasError()) {
		error.Throw();
	}

	if (!lambda_bind_result.HasError()) {
		if (!invalid_syntax) {
			return lambda_bind_result;
		}
		return BindResult(msg);
	}
	if (StringUtil::Contains(lambda_bind_result.error.RawMessage(), "Deprecated lambda arrow (->) detected.")) {
		return lambda_bind_result;
	}

Review comment (refactor):
We likely want to move this to the places where we successfully return from the function (despite having the deprecated syntax). Otherwise, we might throw both an error and a warning.

Code after:
#include "duckdb/planner/binder.hpp"
#include "duckdb/planner/expression/bound_cast_expression.hpp"
#include "duckdb/planner/expression/bound_constant_expression.hpp"
#include "duckdb/planner/expression/bound_function_expression.hpp"
#include "duckdb/planner/expression/bound_lambda_expression.hpp"
#include "duckdb/planner/expression/bound_reference_expression.hpp"
#include "duckdb/planner/expression_binder.hpp"

namespace duckdb {

BindResult ExpressionBinder::TryBindLambdaOrJson(FunctionExpression &function, idx_t depth, CatalogEntry &func,
                                                 const LambdaSyntaxType syntax_type) {
	if (syntax_type == LambdaSyntaxType::LAMBDA_KEYWORD) {
		// lambda x: x + 1 syntax.
		return BindLambdaFunction(function, func.Cast<ScalarFunctionCatalogEntry>(), depth);
	}

	auto &config = ClientConfig::GetConfig(context);
	auto setting = config.lambda_syntax;
	bool invalid_syntax =
	    setting == LambdaSyntax::DISABLE_SINGLE_ARROW && syntax_type == LambdaSyntaxType::SINGLE_ARROW;
	bool warn_deprecated_syntax = setting == LambdaSyntax::DEFAULT && syntax_type == LambdaSyntaxType::SINGLE_ARROW;
	const string msg = "Deprecated lambda arrow (->) detected. Please transition to the new lambda syntax, "
	                   "i.e.., lambda x, i: x + i, before DuckDB's next release. \n"
	                   "Use SET lambda_syntax='ENABLE_SINGLE_ARROW' to revert to the deprecated behavior. \n"
	                   "For more information, see https://duckdb.org/docs/stable/sql/functions/lambda.html.";

	BindResult lambda_bind_result;
	ErrorData error;
	try {
		lambda_bind_result = BindLambdaFunction(function, func.Cast<ScalarFunctionCatalogEntry>(), depth);
	} catch (const std::exception &ex) {
		error = ErrorData(ex);
	}

	if (error.HasError() && error.Type() == ExceptionType::PARAMETER_NOT_RESOLVED && invalid_syntax) {
		ErrorData deprecation_error(ExceptionType::BINDER, msg);
		deprecation_error.Throw();
	} else if (error.HasError()) {
		error.Throw();
	}

	if (!lambda_bind_result.HasError()) {
		if (!invalid_syntax) {
			if (warn_deprecated_syntax) {
				DUCKDB_LOG_WARNING(context, msg);
			}
			return lambda_bind_result;
		}
		return BindResult(msg);
	}