#include "binder/binder.h"
#include "binder/bound_standalone_call.h"
#include "binder/expression/expression_util.h"
#include "binder/expression_visitor.h"
#include "common/cast.h"
#include "common/exception/binder.h"
#include "main/client_context.h"
#include "main/db_config.h"
#include "parser/standalone_call.h"
#include <format>
using namespace lbug::common;
namespace lbug {
namespace binder {
std::unique_ptr<BoundStatement> Binder::bindStandaloneCall(const parser::Statement& statement) {
auto& callStatement = dynamic_cast_checked<const parser::StandaloneCall&>(statement);
const main::Option* option = main::DBConfig::getOptionByName(callStatement.getOptionName());
if (option == nullptr) {
option = clientContext->getExtensionOption(callStatement.getOptionName());
}
if (option == nullptr) {
throw BinderException{"Invalid option name: " + callStatement.getOptionName() + "."};
}
auto optionValue = expressionBinder.bindExpression(*callStatement.getOptionValue());
ExpressionUtil::validateExpressionType(*optionValue, ExpressionType::LITERAL);
if (LogicalTypeUtils::isFloatingPoint(optionValue->dataType.getLogicalTypeID()) &&
LogicalTypeUtils::isIntegral(LogicalType(option->parameterType))) {
throw BinderException{std::format(
"Expression {} has data type {} but expected {}. Implicit cast is not supported.",
optionValue->toString(),
LogicalTypeUtils::toString(optionValue->dataType.getLogicalTypeID()),
LogicalTypeUtils::toString(option->parameterType))};
}
optionValue =
expressionBinder.implicitCastIfNecessary(optionValue, LogicalType(option->parameterType));
if (ConstantExpressionVisitor::needFold(*optionValue)) {
optionValue = expressionBinder.foldExpression(optionValue);
}
return std::make_unique<BoundStandaloneCall>(option, std::move(optionValue));
}
} }