Current section
Files
Jump to
Current section
Files
c_src/duckdb/src/planner/binder/expression/bind_columnref_expression.cpp
#include "duckdb/parser/expression/columnref_expression.hpp"
#include "duckdb/planner/binder.hpp"
#include "duckdb/planner/expression/bound_columnref_expression.hpp"
#include "duckdb/planner/expression_binder.hpp"
#include "duckdb/parser/expression/operator_expression.hpp"
#include "duckdb/common/string_util.hpp"
namespace duckdb {
BindResult ExpressionBinder::BindExpression(ColumnRefExpression &colref, idx_t depth) {
D_ASSERT(!colref.column_name.empty());
// individual column reference
// resolve to either a base table or a subquery expression
if (colref.table_name.empty()) {
auto using_binding = binder.bind_context.GetUsingBinding(colref.column_name);
if (using_binding) {
// we are referencing a USING column
// check if we can refer to one of the base columns directly
unique_ptr<Expression> expression;
if (!using_binding->primary_binding.empty()) {
// we can! just assign the table name and re-bind
colref.table_name = using_binding->primary_binding;
return BindExpression(colref, depth);
} else {
// we cannot! we need to bind this as a coalesce between all the relevant columns
auto coalesce = make_unique<OperatorExpression>(ExpressionType::OPERATOR_COALESCE);
for (auto &entry : using_binding->bindings) {
coalesce->children.push_back(make_unique<ColumnRefExpression>(colref.column_name, entry));
}
return BindExpression(*coalesce, depth);
}
}
// no table name: find a binding that contains this
if (binder.macro_binding != nullptr && binder.macro_binding->HasMatchingBinding(colref.column_name)) {
// priority to macro parameter bindings TODO: throw a warning when this name conflicts
colref.table_name = binder.macro_binding->alias;
} else {
colref.table_name = binder.bind_context.GetMatchingBinding(colref.column_name);
}
if (colref.table_name.empty()) {
auto similar_bindings = binder.bind_context.GetSimilarBindings(colref.column_name);
string candidate_str = StringUtil::CandidatesMessage(similar_bindings, "Candidate bindings");
return BindResult(binder.FormatError(colref.query_location,
"Referenced column \"%s\" not found in FROM clause!%s",
colref.column_name.c_str(), candidate_str));
}
}
// if it was a macro parameter, let macro_binding bind it to the argument
BindResult result = binder.macro_binding != nullptr && colref.table_name == binder.macro_binding->alias
? binder.macro_binding->Bind(colref, depth)
: binder.bind_context.BindColumn(colref, depth);
if (!result.HasError()) {
BoundColumnReferenceInfo ref;
ref.name = colref.column_name;
ref.query_location = colref.query_location;
bound_columns.push_back(move(ref));
} else {
result.error = binder.FormatError(colref, result.error);
}
return result;
}
} // namespace duckdb