ClickHouse/dbms/src/Interpreters/reinterpretAsIdentifier.cpp
2016-05-28 10:48:40 +03:00

50 lines
1.5 KiB
C++

#include <DB/Interpreters/Context.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <DB/Interpreters/ExpressionActions.h>
#include <DB/Interpreters/reinterpretAsIdentifier.h>
#include <DB/DataTypes/DataTypeString.h>
#include <DB/Parsers/ASTIdentifier.h>
#include <DB/Parsers/ASTLiteral.h>
namespace DB
{
namespace
{
ASTPtr reinterpretAsIdentifierImpl(const ASTPtr & expr, const Context & context)
{
/// for string literal return its value
if (const auto literal = typeid_cast<const ASTLiteral *>(expr.get()))
return new ASTIdentifier{{}, safeGet<const String &>(literal->value)};
/// otherwise evaluate the expression
Block block{};
/** pass a dummy column name because ExpressionAnalyzer
* does not work with no columns so far. */
ExpressionAnalyzer{
expr, context, {},
{ { "", std::make_shared<DataTypeString>() } }
}.getActions(false)->execute(block);
const auto & column_name_type = block.getByName(expr->getColumnName());
/// ensure the result of evaluation has String type
if (!typeid_cast<const DataTypeString *>(column_name_type.type.get()))
throw Exception{"Expression must evaluate to a String"};
return new ASTIdentifier{{}, column_name_type.column->getDataAt(0).toString()};
}
}
ASTIdentifier & reinterpretAsIdentifier(ASTPtr & expr, const Context & context)
{
/// for identifier just return its name
if (!typeid_cast<const ASTIdentifier *>(expr.get()))
expr = reinterpretAsIdentifierImpl(expr, context);
return static_cast<ASTIdentifier &>(*expr);
}
}