1#include <boost/algorithm/string/replace.hpp>
2#include <Common/typeid_cast.h>
3#include <Common/quoteString.h>
4#include <Columns/IColumn.h>
5#include <Core/Field.h>
6#include <DataTypes/IDataType.h>
7#include <DataTypes/DataTypeFactory.h>
8#include <Formats/FormatSettings.h>
9#include <IO/ReadBufferFromString.h>
10#include <Parsers/ASTLiteral.h>
11#include <Parsers/ASTQueryParameter.h>
12#include <Interpreters/ReplaceQueryParameterVisitor.h>
13#include <Interpreters/addTypeConversionToAST.h>
14
15
16namespace DB
17{
18
19namespace ErrorCodes
20{
21 extern const int UNKNOWN_QUERY_PARAMETER;
22 extern const int BAD_QUERY_PARAMETER;
23}
24
25
26void ReplaceQueryParameterVisitor::visit(ASTPtr & ast)
27{
28 for (auto & child : ast->children)
29 {
30 if (child->as<ASTQueryParameter>())
31 visitQueryParameter(child);
32 else
33 visit(child);
34 }
35}
36
37const String & ReplaceQueryParameterVisitor::getParamValue(const String & name)
38{
39 auto search = query_parameters.find(name);
40 if (search != query_parameters.end())
41 return search->second;
42 else
43 throw Exception("Substitution " + backQuote(name) + " is not set", ErrorCodes::UNKNOWN_QUERY_PARAMETER);
44}
45
46void ReplaceQueryParameterVisitor::visitQueryParameter(ASTPtr & ast)
47{
48 const auto & ast_param = ast->as<ASTQueryParameter &>();
49 const String & value = getParamValue(ast_param.name);
50 const String & type_name = ast_param.type;
51
52 const auto data_type = DataTypeFactory::instance().get(type_name);
53 auto temp_column_ptr = data_type->createColumn();
54 IColumn & temp_column = *temp_column_ptr;
55 ReadBufferFromString read_buffer{value};
56 FormatSettings format_settings;
57 data_type->deserializeAsWholeText(temp_column, read_buffer, format_settings);
58
59 if (!read_buffer.eof())
60 throw Exception("Value " + value + " cannot be parsed as " + type_name + " for query parameter '" + ast_param.name + "'", ErrorCodes::BAD_QUERY_PARAMETER);
61
62 ast = addTypeConversionToAST(std::make_shared<ASTLiteral>(temp_column[0]), type_name);
63}
64
65}
66