2018-07-16 01:02:46 +00:00
|
|
|
#include <sstream>
|
2017-12-26 21:34:06 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2018-10-01 13:27:39 +00:00
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
2017-12-26 21:34:06 +00:00
|
|
|
#include <Parsers/IAST.h>
|
|
|
|
#include <Parsers/ASTFunction.h>
|
|
|
|
#include <Parsers/ASTIdentifier.h>
|
|
|
|
#include <Parsers/ASTLiteral.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
|
|
|
#include <Parsers/ASTExpressionList.h>
|
|
|
|
#include <Interpreters/ExpressionAnalyzer.h>
|
|
|
|
#include <Storages/transformQueryForExternalDatabase.h>
|
2018-10-09 14:13:08 +00:00
|
|
|
#include <Storages/MergeTree/KeyCondition.h>
|
2017-12-26 21:34:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-10-09 14:21:19 +00:00
|
|
|
static void replaceConstFunction(IAST & node, const Context & context, const NamesAndTypesList & all_columns)
|
2018-10-01 13:27:39 +00:00
|
|
|
{
|
2018-10-01 14:06:36 +00:00
|
|
|
for (size_t i = 0; i < node.children.size(); ++i)
|
|
|
|
{
|
2018-10-01 13:27:39 +00:00
|
|
|
auto child = node.children[i];
|
2018-10-09 14:21:19 +00:00
|
|
|
if (ASTExpressionList * exp_list = typeid_cast<ASTExpressionList *>(&*child))
|
2018-10-01 13:27:39 +00:00
|
|
|
replaceConstFunction(*exp_list, context, all_columns);
|
|
|
|
|
2018-10-09 14:13:08 +00:00
|
|
|
if (ASTFunction * function = typeid_cast<ASTFunction *>(&*child))
|
2018-10-01 13:27:39 +00:00
|
|
|
{
|
2018-10-09 14:13:08 +00:00
|
|
|
auto result_block = KeyCondition::getBlockWithConstants(function->ptr(), context, all_columns);
|
2018-10-01 14:06:36 +00:00
|
|
|
if (!result_block.has(child->getColumnName()))
|
2018-10-01 13:27:39 +00:00
|
|
|
return;
|
2018-10-03 10:08:02 +00:00
|
|
|
|
2018-10-01 13:27:39 +00:00
|
|
|
auto result_column = result_block.getByName(child->getColumnName()).column;
|
|
|
|
|
2018-10-09 14:21:19 +00:00
|
|
|
node.children[i] = std::make_shared<ASTLiteral>((*result_column)[0]);
|
2018-10-01 13:27:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-26 21:34:06 +00:00
|
|
|
static bool isCompatible(const IAST & node)
|
|
|
|
{
|
|
|
|
if (const ASTFunction * function = typeid_cast<const ASTFunction *>(&node))
|
|
|
|
{
|
|
|
|
String name = function->name;
|
|
|
|
if (!(name == "and"
|
|
|
|
|| name == "or"
|
|
|
|
|| name == "not"
|
|
|
|
|| name == "equals"
|
|
|
|
|| name == "notEquals"
|
2018-09-20 14:34:30 +00:00
|
|
|
|| name == "like"
|
|
|
|
|| name == "notLike"
|
2018-09-21 11:33:58 +00:00
|
|
|
|| name == "in"
|
2017-12-26 21:34:06 +00:00
|
|
|
|| name == "greater"
|
|
|
|
|| name == "less"
|
|
|
|
|| name == "lessOrEquals"
|
|
|
|
|| name == "greaterOrEquals"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (const auto & expr : function->arguments->children)
|
|
|
|
if (!isCompatible(*expr.get()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ASTLiteral * literal = typeid_cast<const ASTLiteral *>(&node))
|
|
|
|
{
|
2017-12-27 21:45:05 +00:00
|
|
|
/// Foreign databases often have no support for Array and Tuple literals.
|
|
|
|
if (literal->value.getType() == Field::Types::Array
|
|
|
|
|| literal->value.getType() == Field::Types::Tuple)
|
2017-12-26 21:34:06 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeid_cast<const ASTIdentifier *>(&node))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String transformQueryForExternalDatabase(
|
|
|
|
const IAST & query,
|
|
|
|
const NamesAndTypesList & available_columns,
|
2018-07-16 01:02:46 +00:00
|
|
|
IdentifierQuotingStyle identifier_quoting_style,
|
2017-12-26 21:34:06 +00:00
|
|
|
const String & database,
|
|
|
|
const String & table,
|
|
|
|
const Context & context)
|
|
|
|
{
|
2018-10-03 12:03:39 +00:00
|
|
|
auto clone_query = query.clone();
|
|
|
|
ExpressionAnalyzer analyzer(clone_query, context, {}, available_columns);
|
2018-02-26 09:05:06 +00:00
|
|
|
const Names & used_columns = analyzer.getRequiredSourceColumns();
|
2017-12-26 21:34:06 +00:00
|
|
|
|
|
|
|
auto select = std::make_shared<ASTSelectQuery>();
|
|
|
|
|
|
|
|
select->replaceDatabaseAndTable(database, table);
|
|
|
|
|
|
|
|
auto select_expr_list = std::make_shared<ASTExpressionList>();
|
|
|
|
for (const auto & name : used_columns)
|
2018-02-26 03:37:08 +00:00
|
|
|
select_expr_list->children.push_back(std::make_shared<ASTIdentifier>(name));
|
2017-12-26 21:34:06 +00:00
|
|
|
|
|
|
|
select->select_expression_list = std::move(select_expr_list);
|
|
|
|
|
|
|
|
/** If there was WHERE,
|
|
|
|
* copy it to transformed query if it is compatible,
|
|
|
|
* or if it is AND expression,
|
|
|
|
* copy only compatible parts of it.
|
|
|
|
*/
|
|
|
|
|
2018-10-09 14:13:08 +00:00
|
|
|
ASTPtr & original_where = typeid_cast<ASTSelectQuery &>(*clone_query).where_expression;
|
2017-12-26 21:34:06 +00:00
|
|
|
if (original_where)
|
|
|
|
{
|
2018-10-01 13:27:39 +00:00
|
|
|
replaceConstFunction(*original_where, context, available_columns);
|
2017-12-26 21:34:06 +00:00
|
|
|
if (isCompatible(*original_where))
|
|
|
|
{
|
|
|
|
select->where_expression = original_where;
|
|
|
|
}
|
|
|
|
else if (const ASTFunction * function = typeid_cast<const ASTFunction *>(original_where.get()))
|
|
|
|
{
|
|
|
|
if (function->name == "and")
|
|
|
|
{
|
2018-10-29 14:17:58 +00:00
|
|
|
bool compatible_found = false;
|
2017-12-26 21:34:06 +00:00
|
|
|
auto new_function_and = std::make_shared<ASTFunction>();
|
|
|
|
auto new_function_and_arguments = std::make_shared<ASTExpressionList>();
|
|
|
|
new_function_and->arguments = new_function_and_arguments;
|
|
|
|
new_function_and->children.push_back(new_function_and_arguments);
|
|
|
|
|
|
|
|
for (const auto & elem : function->arguments->children)
|
2018-10-29 14:17:58 +00:00
|
|
|
{
|
2017-12-26 21:34:06 +00:00
|
|
|
if (isCompatible(*elem))
|
2018-10-26 17:14:43 +00:00
|
|
|
{
|
2017-12-26 21:34:06 +00:00
|
|
|
new_function_and_arguments->children.push_back(elem);
|
2018-10-29 14:17:58 +00:00
|
|
|
compatible_found = true;
|
2018-10-26 17:14:43 +00:00
|
|
|
}
|
2018-10-29 14:17:58 +00:00
|
|
|
}
|
2017-12-26 21:34:06 +00:00
|
|
|
|
2018-10-29 14:17:58 +00:00
|
|
|
if (compatible_found)
|
2018-10-26 17:14:43 +00:00
|
|
|
select->where_expression = std::move(new_function_and);
|
2017-12-26 21:34:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-16 01:02:46 +00:00
|
|
|
std::stringstream out;
|
|
|
|
IAST::FormatSettings settings(out, true);
|
|
|
|
settings.always_quote_identifiers = true;
|
|
|
|
settings.identifier_quoting_style = identifier_quoting_style;
|
|
|
|
|
|
|
|
select->format(settings);
|
2018-09-20 14:34:30 +00:00
|
|
|
|
2018-07-16 01:02:46 +00:00
|
|
|
return out.str();
|
2017-12-26 21:34:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|