2019-06-04 18:15:32 +00:00
|
|
|
#include <boost/algorithm/string/replace.hpp>
|
2019-05-18 21:07:23 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2019-10-08 18:42:22 +00:00
|
|
|
#include <Common/quoteString.h>
|
2019-05-18 23:57:26 +00:00
|
|
|
#include <Columns/IColumn.h>
|
2019-05-18 21:07:23 +00:00
|
|
|
#include <Core/Field.h>
|
|
|
|
#include <DataTypes/IDataType.h>
|
|
|
|
#include <DataTypes/DataTypeFactory.h>
|
|
|
|
#include <Formats/FormatSettings.h>
|
|
|
|
#include <IO/ReadBufferFromString.h>
|
2020-01-03 14:10:56 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2019-05-18 21:07:23 +00:00
|
|
|
#include <Parsers/ASTLiteral.h>
|
|
|
|
#include <Parsers/ASTQueryParameter.h>
|
|
|
|
#include <Interpreters/ReplaceQueryParameterVisitor.h>
|
2019-06-14 17:15:30 +00:00
|
|
|
#include <Interpreters/addTypeConversionToAST.h>
|
|
|
|
|
2019-05-18 21:07:23 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2019-06-16 17:32:37 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int UNKNOWN_QUERY_PARAMETER;
|
|
|
|
extern const int BAD_QUERY_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-18 21:07:23 +00:00
|
|
|
void ReplaceQueryParameterVisitor::visit(ASTPtr & ast)
|
|
|
|
{
|
|
|
|
for (auto & child : ast->children)
|
|
|
|
{
|
|
|
|
if (child->as<ASTQueryParameter>())
|
2019-06-14 17:15:30 +00:00
|
|
|
visitQueryParameter(child);
|
2019-05-18 21:07:23 +00:00
|
|
|
else
|
|
|
|
visit(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 16:18:24 +00:00
|
|
|
const String & ReplaceQueryParameterVisitor::getParamValue(const String & name)
|
2019-05-18 21:07:23 +00:00
|
|
|
{
|
2019-06-15 17:52:53 +00:00
|
|
|
auto search = query_parameters.find(name);
|
|
|
|
if (search != query_parameters.end())
|
2019-05-18 21:07:23 +00:00
|
|
|
return search->second;
|
|
|
|
else
|
2019-06-16 17:32:37 +00:00
|
|
|
throw Exception("Substitution " + backQuote(name) + " is not set", ErrorCodes::UNKNOWN_QUERY_PARAMETER);
|
2019-05-18 21:07:23 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 16:18:24 +00:00
|
|
|
void ReplaceQueryParameterVisitor::visitQueryParameter(ASTPtr & ast)
|
2019-05-18 21:07:23 +00:00
|
|
|
{
|
2019-06-14 16:18:24 +00:00
|
|
|
const auto & ast_param = ast->as<ASTQueryParameter &>();
|
|
|
|
const String & value = getParamValue(ast_param.name);
|
2019-06-14 17:15:30 +00:00
|
|
|
const String & type_name = ast_param.type;
|
2019-06-04 18:15:32 +00:00
|
|
|
|
2019-06-14 17:15:30 +00:00
|
|
|
const auto data_type = DataTypeFactory::instance().get(type_name);
|
2019-05-18 21:07:23 +00:00
|
|
|
auto temp_column_ptr = data_type->createColumn();
|
2019-05-18 23:57:26 +00:00
|
|
|
IColumn & temp_column = *temp_column_ptr;
|
2019-05-18 21:07:23 +00:00
|
|
|
ReadBufferFromString read_buffer{value};
|
|
|
|
FormatSettings format_settings;
|
2020-01-03 14:10:56 +00:00
|
|
|
data_type->deserializeAsTextEscaped(temp_column, read_buffer, format_settings);
|
2019-05-18 21:07:23 +00:00
|
|
|
|
2019-06-05 21:04:17 +00:00
|
|
|
if (!read_buffer.eof())
|
2020-01-03 14:10:56 +00:00
|
|
|
throw Exception("Value " + value + " cannot be parsed as " + type_name + " for query parameter '" + ast_param.name + "'"
|
|
|
|
" because it isn't parsed completely: only " + toString(read_buffer.count()) + " of " + toString(value.size()) + " bytes was parsed: "
|
|
|
|
+ value.substr(0, read_buffer.count()), ErrorCodes::BAD_QUERY_PARAMETER);
|
2019-06-05 21:04:17 +00:00
|
|
|
|
2019-06-14 17:15:30 +00:00
|
|
|
ast = addTypeConversionToAST(std::make_shared<ASTLiteral>(temp_column[0]), type_name);
|
2019-05-18 21:07:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|