mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-30 19:42:00 +00:00
51 lines
1.6 KiB
C
51 lines
1.6 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <DB/Interpreters/Context.h>
|
||
|
#include <DB/Interpreters/ExpressionAnalyzer.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 ExpressioAnalyzer
|
||
|
* does not work with no columns so far. */
|
||
|
ExpressionAnalyzer{
|
||
|
expr, context,
|
||
|
{ { "", new 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()};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** \brief if `expr` is not already ASTIdentifier evaluates it
|
||
|
* and replaces by a new ASTIdentifier with the result of evaluation as its name.
|
||
|
* `expr` must evaluate to a String type */
|
||
|
inline 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);
|
||
|
}
|
||
|
}
|