mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 01:25:21 +00:00
Fixing query parameters
This commit is contained in:
parent
54ece5f968
commit
fad6013270
@ -204,7 +204,7 @@ private:
|
||||
std::list<ExternalTable> external_tables;
|
||||
|
||||
/// Dictionary with query parameters for prepared statements.
|
||||
NameToNameMap parameters_substitution;
|
||||
NameToNameMap query_parameters;
|
||||
|
||||
ConnectionParameters connection_parameters;
|
||||
|
||||
@ -807,15 +807,12 @@ private:
|
||||
if (!parsed_query)
|
||||
return true;
|
||||
|
||||
if (!parameters_substitution.empty())
|
||||
{
|
||||
/// Replace ASTQueryParameter with ASTLiteral for prepared statements.
|
||||
ReplaceQueryParameterVisitor visitor(parameters_substitution);
|
||||
visitor.visit(parsed_query);
|
||||
/// Replace ASTQueryParameter with ASTLiteral for prepared statements.
|
||||
ReplaceQueryParameterVisitor visitor(query_parameters);
|
||||
visitor.visit(parsed_query);
|
||||
|
||||
/// Get new query after substitutions.
|
||||
query = serializeAST(*parsed_query);
|
||||
}
|
||||
/// Get new query after substitutions.
|
||||
query = serializeAST(*parsed_query);
|
||||
|
||||
processed_rows = 0;
|
||||
progress.reset();
|
||||
@ -1719,7 +1716,7 @@ public:
|
||||
if (pos != String::npos && pos + 1 != parameter.size())
|
||||
{
|
||||
const String name = parameter.substr(0, pos);
|
||||
if (!parameters_substitution.insert({name, parameter.substr(pos + 1)}).second)
|
||||
if (!query_parameters.insert({name, parameter.substr(pos + 1)}).second)
|
||||
throw Exception("Duplicate name " + name + " of query parameter", ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
else
|
||||
|
@ -505,7 +505,7 @@ void HTTPHandler::processQuery(
|
||||
{
|
||||
/// Save name and values of substitution in dictionary.
|
||||
const String parameter_name = key.substr(strlen("param_"));
|
||||
context.setParameterSubstitution(parameter_name, value);
|
||||
context.setQueryParameter(parameter_name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1868,22 +1868,20 @@ Context::SampleBlockCache & Context::getSampleBlockCache() const
|
||||
|
||||
bool Context::hasQueryParameters() const
|
||||
{
|
||||
return !parameters_substitution.empty();
|
||||
return !query_parameters.empty();
|
||||
}
|
||||
|
||||
|
||||
NameToNameMap Context::getParameterSubstitution() const
|
||||
const NameToNameMap & Context::getQueryParameters() const
|
||||
{
|
||||
if (hasQueryParameters())
|
||||
return parameters_substitution;
|
||||
throw Exception("Logical error: there are no parameters to substitute", ErrorCodes::LOGICAL_ERROR);
|
||||
return query_parameters;
|
||||
}
|
||||
|
||||
|
||||
void Context::setParameterSubstitution(const String & name, const String & value)
|
||||
void Context::setQueryParameter(const String & name, const String & value)
|
||||
{
|
||||
if (!parameters_substitution.insert({name, value}).second)
|
||||
throw Exception("Duplicate name " + name + " of query parameter", ErrorCodes::BAD_ARGUMENTS);
|
||||
if (!query_parameters.emplace(name, value).second)
|
||||
throw Exception("Duplicate name " + backQuote(name) + " of query parameter", ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -145,7 +145,7 @@ private:
|
||||
using DatabasePtr = std::shared_ptr<IDatabase>;
|
||||
using Databases = std::map<String, std::shared_ptr<IDatabase>>;
|
||||
|
||||
NameToNameMap parameters_substitution; /// Dictionary with query parameters for prepared statements.
|
||||
NameToNameMap query_parameters; /// Dictionary with query parameters for prepared statements.
|
||||
/// (key=name, value)
|
||||
|
||||
IHostContextPtr host_context; /// Arbitrary object that may used to attach some host specific information to query context,
|
||||
@ -472,8 +472,8 @@ public:
|
||||
|
||||
/// Query parameters for prepared statements.
|
||||
bool hasQueryParameters() const;
|
||||
NameToNameMap getParameterSubstitution() const;
|
||||
void setParameterSubstitution(const String & name, const String & value);
|
||||
const NameToNameMap & getQueryParameters() const;
|
||||
void setQueryParameter(const String & name, const String & value);
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
std::shared_ptr<CompiledExpressionCache> getCompiledExpressionCache() const;
|
||||
|
@ -28,11 +28,11 @@ void ReplaceQueryParameterVisitor::visit(ASTPtr & ast)
|
||||
|
||||
const String & ReplaceQueryParameterVisitor::getParamValue(const String & name)
|
||||
{
|
||||
auto search = parameters_substitution.find(name);
|
||||
if (search != parameters_substitution.end())
|
||||
auto search = query_parameters.find(name);
|
||||
if (search != query_parameters.end())
|
||||
return search->second;
|
||||
else
|
||||
throw Exception("Expected name '" + name + "' in argument --param_{name}", ErrorCodes::BAD_ARGUMENTS);
|
||||
throw Exception("Substitution " + backQuote(name) + " is not set", ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
void ReplaceQueryParameterVisitor::visitQueryParameter(ASTPtr & ast)
|
||||
|
@ -8,18 +8,18 @@ namespace DB
|
||||
|
||||
class ASTQueryParameter;
|
||||
|
||||
/// Get prepared statements in query, replace ASTQueryParameter with ASTLiteral.
|
||||
/// Visit substitutions in a query, replace ASTQueryParameter with ASTLiteral.
|
||||
class ReplaceQueryParameterVisitor
|
||||
{
|
||||
public:
|
||||
ReplaceQueryParameterVisitor(const NameToNameMap & parameters)
|
||||
: parameters_substitution(parameters)
|
||||
: query_parameters(parameters)
|
||||
{}
|
||||
|
||||
void visit(ASTPtr & ast);
|
||||
|
||||
private:
|
||||
const NameToNameMap parameters_substitution;
|
||||
const NameToNameMap & query_parameters;
|
||||
const String & getParamValue(const String & name);
|
||||
void visitQueryParameter(ASTPtr & ast);
|
||||
};
|
||||
|
@ -170,12 +170,9 @@ static std::tuple<ASTPtr, BlockIO> executeQueryImpl(
|
||||
/// TODO Parser should fail early when max_query_size limit is reached.
|
||||
ast = parseQuery(parser, begin, end, "", max_query_size);
|
||||
|
||||
if (context.hasQueryParameters()) /// Avoid change from TCPHandler.
|
||||
{
|
||||
/// Replace ASTQueryParameter with ASTLiteral for prepared statements.
|
||||
ReplaceQueryParameterVisitor visitor(context.getParameterSubstitution());
|
||||
visitor.visit(ast);
|
||||
}
|
||||
/// Replace ASTQueryParameter with ASTLiteral for prepared statements.
|
||||
ReplaceQueryParameterVisitor visitor(context.getQueryParameters());
|
||||
visitor.visit(ast);
|
||||
|
||||
auto * insert_query = ast->as<ASTInsertQuery>();
|
||||
|
||||
@ -208,8 +205,8 @@ static std::tuple<ASTPtr, BlockIO> executeQueryImpl(
|
||||
|
||||
try
|
||||
{
|
||||
if (context.hasQueryParameters()) /// Avoid change from TCPHandler.
|
||||
/// Get new query after substitutions.
|
||||
/// Get new query after substitutions.
|
||||
if (context.hasQueryParameters())
|
||||
query = serializeAST(*ast);
|
||||
|
||||
logQuery(query.substr(0, settings.log_queries_cut_to_length), context, internal);
|
||||
|
@ -7,7 +7,13 @@ namespace DB
|
||||
|
||||
void ASTQueryParameter::formatImplWithoutAlias(const FormatSettings & settings, FormatState &, FormatStateStacked) const
|
||||
{
|
||||
settings.ostr << backQuoteIfNeed(name) + ':' + type;
|
||||
settings.ostr
|
||||
<< (settings.hilite ? hilite_substitution : "") << '{'
|
||||
<< (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(name)
|
||||
<< (settings.hilite ? hilite_substitution : "") << ':'
|
||||
<< (settings.hilite ? hilite_identifier : "") << type
|
||||
<< (settings.hilite ? hilite_substitution : "") << '}'
|
||||
<< (settings.hilite ? hilite_none : "");
|
||||
}
|
||||
|
||||
void ASTQueryParameter::appendColumnNameImpl(WriteBuffer & ostr) const
|
||||
|
@ -17,12 +17,13 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
const char * IAST::hilite_keyword = "\033[1m";
|
||||
const char * IAST::hilite_identifier = "\033[0;36m";
|
||||
const char * IAST::hilite_function = "\033[0;33m";
|
||||
const char * IAST::hilite_operator = "\033[1;33m";
|
||||
const char * IAST::hilite_alias = "\033[0;32m";
|
||||
const char * IAST::hilite_none = "\033[0m";
|
||||
const char * IAST::hilite_keyword = "\033[1m";
|
||||
const char * IAST::hilite_identifier = "\033[0;36m";
|
||||
const char * IAST::hilite_function = "\033[0;33m";
|
||||
const char * IAST::hilite_operator = "\033[1;33m";
|
||||
const char * IAST::hilite_alias = "\033[0;32m";
|
||||
const char * IAST::hilite_substitution = "\033[1;36m";
|
||||
const char * IAST::hilite_none = "\033[0m";
|
||||
|
||||
|
||||
String backQuoteIfNeed(const String & x)
|
||||
|
@ -201,6 +201,7 @@ public:
|
||||
static const char * hilite_function;
|
||||
static const char * hilite_operator;
|
||||
static const char * hilite_alias;
|
||||
static const char * hilite_substitution;
|
||||
static const char * hilite_none;
|
||||
|
||||
private:
|
||||
|
@ -18,4 +18,7 @@ $CLICKHOUSE_CLIENT --max_threads=1 --param_date='2005-05-25 15:00:00' \
|
||||
$CLICKHOUSE_CLIENT --max_threads=1 --param_id=2 --param_phrase='test' \
|
||||
-q "SELECT * FROM ps WHERE i = {id:UInt8} and s = {phrase:String}";
|
||||
|
||||
$CLICKHOUSE_CLIENT -q "SELECT {s:String}" 2>&1 | grep -P '^Code: 36\.'
|
||||
|
||||
|
||||
$CLICKHOUSE_CLIENT -q "DROP TABLE ps";
|
||||
|
Loading…
Reference in New Issue
Block a user