2013-04-24 10:31:32 +00:00
|
|
|
|
#include <DB/Storages/MergeTree/PKCondition.h>
|
2012-12-05 12:44:55 +00:00
|
|
|
|
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
2013-06-03 13:17:17 +00:00
|
|
|
|
#include <DB/Interpreters/ExpressionAnalyzer.h>
|
2014-03-20 12:25:26 +00:00
|
|
|
|
#include <DB/Columns/ColumnSet.h>
|
2014-03-26 18:19:25 +00:00
|
|
|
|
#include <DB/Columns/ColumnTuple.h>
|
2014-03-31 14:49:43 +00:00
|
|
|
|
#include <DB/Parsers/ASTSet.h>
|
2015-11-29 08:06:29 +00:00
|
|
|
|
#include <DB/Functions/FunctionFactory.h>
|
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2015-06-24 21:24:06 +00:00
|
|
|
|
|
2015-09-21 12:13:05 +00:00
|
|
|
|
const PKCondition::AtomMap PKCondition::atom_map{
|
|
|
|
|
{
|
|
|
|
|
"notEquals",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.function = RPNElement::FUNCTION_NOT_IN_RANGE;
|
|
|
|
|
out.range = Range(value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"equals",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
|
|
|
|
out.function = RPNElement::FUNCTION_IN_RANGE;
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.range = Range(value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"less",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
|
|
|
|
out.function = RPNElement::FUNCTION_IN_RANGE;
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.range = Range::createRightBounded(value, false);
|
|
|
|
|
}
|
2015-10-28 21:00:44 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
"greater",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
|
|
|
|
out.function = RPNElement::FUNCTION_IN_RANGE;
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.range = Range::createLeftBounded(value, false);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"lessOrEquals",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
|
|
|
|
out.function = RPNElement::FUNCTION_IN_RANGE;
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.range = Range::createRightBounded(value, true);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"greaterOrEquals",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr &)
|
|
|
|
|
{
|
|
|
|
|
out.function = RPNElement::FUNCTION_IN_RANGE;
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.range = Range::createLeftBounded(value, true);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"in",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr & node)
|
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.function = RPNElement::FUNCTION_IN_SET;
|
|
|
|
|
out.in_function = node;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"notIn",
|
2015-10-28 21:00:44 +00:00
|
|
|
|
[] (RPNElement & out, const Field & value, ASTPtr & node)
|
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
out.function = RPNElement::FUNCTION_NOT_IN_SET;
|
|
|
|
|
out.in_function = node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-06-24 21:24:06 +00:00
|
|
|
|
|
|
|
|
|
inline bool Range::equals(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateEquals(), lhs, rhs); }
|
|
|
|
|
inline bool Range::less(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateLess(), lhs, rhs); }
|
|
|
|
|
|
|
|
|
|
|
2015-09-21 12:13:05 +00:00
|
|
|
|
Block PKCondition::getBlockWithConstants(
|
|
|
|
|
const ASTPtr & query, const Context & context, const NamesAndTypesList & all_columns)
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
Block result
|
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
{ new ColumnConstUInt8{1, 0}, new DataTypeUInt8, "_dummy" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto expr_for_constant_folding = ExpressionAnalyzer{query, context, nullptr, all_columns}
|
|
|
|
|
.getConstActions();
|
|
|
|
|
|
|
|
|
|
expr_for_constant_folding->execute(result);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
PKCondition::PKCondition(ASTPtr & query, const Context & context, const NamesAndTypesList & all_columns, const SortDescription & sort_descr_)
|
2013-05-06 12:15:34 +00:00
|
|
|
|
: sort_descr(sort_descr_)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < sort_descr.size(); ++i)
|
|
|
|
|
{
|
2014-02-10 12:44:51 +00:00
|
|
|
|
std::string name = sort_descr[i].column_name;
|
|
|
|
|
if (!pk_columns.count(name))
|
|
|
|
|
pk_columns[name] = i;
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
/** Вычисление выражений, зависящих только от констант.
|
|
|
|
|
* Чтобы индекс мог использоваться, если написано, например WHERE Date = toDate(now()).
|
|
|
|
|
*/
|
2015-11-29 08:06:29 +00:00
|
|
|
|
Block block_with_constants = getBlockWithConstants(query, context, all_columns);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
/// Преобразуем секцию WHERE в обратную польскую строку.
|
2014-06-26 00:58:14 +00:00
|
|
|
|
ASTSelectQuery & select = typeid_cast<ASTSelectQuery &>(*query);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
if (select.where_expression)
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
traverseAST(select.where_expression, context, block_with_constants);
|
2013-11-28 13:16:46 +00:00
|
|
|
|
|
|
|
|
|
if (select.prewhere_expression)
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
traverseAST(select.prewhere_expression, context, block_with_constants);
|
2015-03-27 03:37:46 +00:00
|
|
|
|
rpn.emplace_back(RPNElement::FUNCTION_AND);
|
2013-11-28 13:16:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (select.prewhere_expression)
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
traverseAST(select.prewhere_expression, context, block_with_constants);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-03-27 03:37:46 +00:00
|
|
|
|
rpn.emplace_back(RPNElement::FUNCTION_UNKNOWN);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 14:25:55 +00:00
|
|
|
|
bool PKCondition::addCondition(const String & column, const Range & range)
|
|
|
|
|
{
|
|
|
|
|
if (!pk_columns.count(column))
|
|
|
|
|
return false;
|
2015-03-27 03:37:46 +00:00
|
|
|
|
rpn.emplace_back(RPNElement::FUNCTION_IN_RANGE, pk_columns[column], range);
|
|
|
|
|
rpn.emplace_back(RPNElement::FUNCTION_AND);
|
2012-12-12 14:25:55 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
/** Получить значение константного выражения.
|
2015-10-28 21:00:44 +00:00
|
|
|
|
* Вернуть false, если выражение не константно.
|
|
|
|
|
*/
|
2015-11-29 08:06:29 +00:00
|
|
|
|
static bool getConstant(const ASTPtr & expr, Block & block_with_constants, Field & value)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
String column_name = expr->getColumnName();
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
if (const ASTLiteral * lit = typeid_cast<const ASTLiteral *>(&*expr))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
/// литерал
|
|
|
|
|
value = lit->value;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (block_with_constants.has(column_name) && block_with_constants.getByName(column_name).column->isConst())
|
|
|
|
|
{
|
|
|
|
|
/// выражение, вычислившееся в константу
|
|
|
|
|
value = (*block_with_constants.getByName(column_name).column)[0];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
void PKCondition::traverseAST(ASTPtr & node, const Context & context, Block & block_with_constants)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
RPNElement element;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
|
|
|
|
if (ASTFunction * func = typeid_cast<ASTFunction *>(&*node))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
if (operatorFromAST(func, element))
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
auto & args = typeid_cast<ASTExpressionList &>(*func->arguments).children;
|
|
|
|
|
for (size_t i = 0, size = args.size(); i < size; ++i)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
traverseAST(args[i], context, block_with_constants);
|
2014-10-06 05:49:31 +00:00
|
|
|
|
|
|
|
|
|
/** Первая часть условия - для корректной поддержки функций and и or произвольной арности
|
|
|
|
|
* - в этом случае добавляется n - 1 элементов (где n - количество аргументов).
|
|
|
|
|
*/
|
|
|
|
|
if (i != 0 || element.function == RPNElement::FUNCTION_NOT)
|
2014-02-13 11:05:51 +00:00
|
|
|
|
rpn.push_back(element);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
if (!atomFromAST(node, context, block_with_constants, element))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
element.function = RPNElement::FUNCTION_UNKNOWN;
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
rpn.push_back(element);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
|
|
|
|
|
bool PKCondition::isPrimaryKeyPossiblyWrappedByMonotonicFunctions(
|
|
|
|
|
const ASTPtr & node,
|
|
|
|
|
const Context & context,
|
|
|
|
|
size_t & out_primary_key_column_num,
|
|
|
|
|
RPNElement::MonotonicFunctionsChain & out_functions_chain)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
std::vector<const ASTFunction *> chain_not_tested_for_monotonicity;
|
|
|
|
|
|
|
|
|
|
if (!isPrimaryKeyPossiblyWrappedByMonotonicFunctionsImpl(node, out_primary_key_column_num, chain_not_tested_for_monotonicity))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
for (auto it = chain_not_tested_for_monotonicity.rbegin(); it != chain_not_tested_for_monotonicity.rend(); ++it)
|
|
|
|
|
{
|
|
|
|
|
FunctionPtr func = FunctionFactory::instance().tryGet((*it)->name, context);
|
|
|
|
|
if (!func || !func->hasInformationAboutMonotonicity())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
out_functions_chain.push_back(func);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PKCondition::isPrimaryKeyPossiblyWrappedByMonotonicFunctionsImpl(
|
|
|
|
|
const ASTPtr & node,
|
|
|
|
|
size_t & out_primary_key_column_num,
|
|
|
|
|
std::vector<const ASTFunction *> & out_functions_chain)
|
|
|
|
|
{
|
|
|
|
|
/** Сам по себе, столбец первичного ключа может быть функциональным выражением. Например, intHash32(UserID).
|
|
|
|
|
* Поэтому, используем полное имя выражения для поиска.
|
|
|
|
|
*/
|
|
|
|
|
String name = node->getColumnName();
|
|
|
|
|
|
|
|
|
|
auto it = pk_columns.find(name);
|
|
|
|
|
if (pk_columns.end() != it)
|
|
|
|
|
{
|
|
|
|
|
out_primary_key_column_num = it->second;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const ASTFunction * func = typeid_cast<const ASTFunction *>(node.get()))
|
|
|
|
|
{
|
|
|
|
|
const auto & args = func->arguments->children;
|
|
|
|
|
if (args.size() != 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
out_functions_chain.push_back(func);
|
|
|
|
|
|
|
|
|
|
if (!isPrimaryKeyPossiblyWrappedByMonotonicFunctionsImpl(args[0], out_primary_key_column_num, out_functions_chain))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PKCondition::atomFromAST(ASTPtr & node, const Context & context, Block & block_with_constants, RPNElement & out)
|
|
|
|
|
{
|
|
|
|
|
/** Функции < > = != <= >= in notIn, у которых один агрумент константа, другой - один из столбцов первичного ключа,
|
|
|
|
|
* либо он же, завёрнутый в цепочку возможно-монотонных функций.
|
|
|
|
|
*/
|
|
|
|
|
if (const ASTFunction * func = typeid_cast<const ASTFunction *>(&*node))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
const ASTs & args = typeid_cast<const ASTExpressionList &>(*func->arguments).children;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
if (args.size() != 2)
|
|
|
|
|
return false;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
/// Если true, слева константа.
|
|
|
|
|
bool inverted;
|
|
|
|
|
size_t column;
|
|
|
|
|
Field value;
|
2015-11-29 08:06:29 +00:00
|
|
|
|
RPNElement::MonotonicFunctionsChain chain;
|
2014-03-20 12:25:26 +00:00
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
if (getConstant(args[1], block_with_constants, value) && isPrimaryKeyPossiblyWrappedByMonotonicFunctions(args[0], context, column, chain))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
inverted = false;
|
|
|
|
|
}
|
2015-11-29 08:06:29 +00:00
|
|
|
|
else if (getConstant(args[0], block_with_constants, value) && isPrimaryKeyPossiblyWrappedByMonotonicFunctions(args[1], context, column, chain))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
inverted = true;
|
|
|
|
|
}
|
2015-11-29 08:06:29 +00:00
|
|
|
|
else if (typeid_cast<const ASTSet *>(args[1].get()) && isPrimaryKeyPossiblyWrappedByMonotonicFunctions(args[0], context, column, chain))
|
2014-03-20 12:25:26 +00:00
|
|
|
|
{
|
2014-03-26 18:19:25 +00:00
|
|
|
|
inverted = false;
|
2014-03-20 12:25:26 +00:00
|
|
|
|
}
|
2012-12-05 12:44:55 +00:00
|
|
|
|
else
|
|
|
|
|
return false;
|
2014-06-11 18:38:10 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
std::string func_name = func->name;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
/// Заменим <const> <sign> <column> на <column> <-sign> <const>
|
|
|
|
|
if (inverted)
|
|
|
|
|
{
|
|
|
|
|
if (func_name == "less")
|
|
|
|
|
func_name = "greater";
|
|
|
|
|
else if (func_name == "greater")
|
|
|
|
|
func_name = "less";
|
|
|
|
|
else if (func_name == "greaterOrEquals")
|
|
|
|
|
func_name = "lessOrEquals";
|
|
|
|
|
else if (func_name == "lessOrEquals")
|
|
|
|
|
func_name = "greaterOrEquals";
|
2015-10-28 21:00:44 +00:00
|
|
|
|
else if (func_name == "in" || func_name == "notIn")
|
|
|
|
|
{
|
|
|
|
|
/// const IN x не имеет смысла (в отличие от x IN const).
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
out.key_column = column;
|
2015-11-29 08:06:29 +00:00
|
|
|
|
out.monotonic_functions_chain = std::move(chain);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-09-21 12:13:05 +00:00
|
|
|
|
const auto atom_it = atom_map.find(func_name);
|
|
|
|
|
if (atom_it == std::end(atom_map))
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return false;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-09-21 12:13:05 +00:00
|
|
|
|
atom_it->second(out, value, node);
|
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
bool PKCondition::operatorFromAST(const ASTFunction * func, RPNElement & out)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2015-09-21 12:13:05 +00:00
|
|
|
|
/// Функции AND, OR, NOT.
|
2015-11-29 08:06:29 +00:00
|
|
|
|
const ASTs & args = typeid_cast<const ASTExpressionList &>(*func->arguments).children;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
if (func->name == "not")
|
|
|
|
|
{
|
|
|
|
|
if (args.size() != 1)
|
|
|
|
|
return false;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
out.function = RPNElement::FUNCTION_NOT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (func->name == "and")
|
|
|
|
|
out.function = RPNElement::FUNCTION_AND;
|
|
|
|
|
else if (func->name == "or")
|
|
|
|
|
out.function = RPNElement::FUNCTION_OR;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 03:37:46 +00:00
|
|
|
|
String PKCondition::toString() const
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
String res;
|
|
|
|
|
for (size_t i = 0; i < rpn.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (i)
|
|
|
|
|
res += ", ";
|
|
|
|
|
res += rpn[i].toString();
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
|
|
|
|
|
static void applyFunction(
|
|
|
|
|
FunctionPtr & func,
|
|
|
|
|
const DataTypePtr & arg_type, const Field & arg_value,
|
|
|
|
|
DataTypePtr & res_type, Field & res_value)
|
|
|
|
|
{
|
|
|
|
|
res_type = func->getReturnType({arg_type});
|
|
|
|
|
|
|
|
|
|
Block block
|
|
|
|
|
{
|
|
|
|
|
{ arg_type->createConstColumn(1, arg_value), arg_type, "x" },
|
|
|
|
|
{ nullptr, res_type, "y" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
func->execute(block, {0}, 1);
|
|
|
|
|
|
|
|
|
|
block.getByPosition(1).column->get(0, res_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk, const DataTypes & data_types, bool right_bounded) const
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
|
|
|
|
/// Найдем диапазоны элементов ключа.
|
|
|
|
|
std::vector<Range> key_ranges(sort_descr.size(), Range());
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-06 09:45:09 +00:00
|
|
|
|
if (right_bounded)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2012-12-06 09:45:09 +00:00
|
|
|
|
for (size_t i = 0; i < sort_descr.size(); ++i)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2012-12-06 09:45:09 +00:00
|
|
|
|
if (left_pk[i] == right_pk[i])
|
|
|
|
|
{
|
|
|
|
|
key_ranges[i] = Range(left_pk[i]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
key_ranges[i] = Range(left_pk[i], true, right_pk[i], true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-06 09:45:09 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2013-12-11 20:44:06 +00:00
|
|
|
|
key_ranges[0] = Range::createLeftBounded(left_pk[0], true);
|
2012-12-06 09:45:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
std::vector<BoolMask> rpn_stack;
|
|
|
|
|
for (size_t i = 0; i < rpn.size(); ++i)
|
|
|
|
|
{
|
2015-03-27 03:37:46 +00:00
|
|
|
|
const auto & element = rpn[i];
|
2012-12-05 12:44:55 +00:00
|
|
|
|
if (element.function == RPNElement::FUNCTION_UNKNOWN)
|
|
|
|
|
{
|
2015-03-27 03:06:06 +00:00
|
|
|
|
rpn_stack.emplace_back(true, true);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
2015-11-29 08:06:29 +00:00
|
|
|
|
else if (element.function == RPNElement::FUNCTION_IN_RANGE
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_NOT_IN_RANGE
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_IN_SET
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
2012-12-05 12:44:55 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
const Range * key_range = &key_ranges[element.key_column];
|
2013-12-11 20:44:06 +00:00
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
/// Случай, когда столбец обёрнут в цепочку возможно-монотонных функций.
|
|
|
|
|
Range key_range_transformed;
|
|
|
|
|
bool evaluation_is_not_possible = false;
|
|
|
|
|
if (!element.monotonic_functions_chain.empty())
|
2014-03-31 14:49:43 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
key_range_transformed = *key_range;
|
|
|
|
|
DataTypePtr current_type = data_types[element.key_column];
|
|
|
|
|
for (auto & func : element.monotonic_functions_chain)
|
|
|
|
|
{
|
|
|
|
|
/// Проверяем монотонность каждой функции на конкретном диапазоне.
|
2015-11-29 11:58:44 +00:00
|
|
|
|
IFunction::Monotonicity monotonicity = func->getMonotonicityForRange(
|
|
|
|
|
*current_type.get(), key_range_transformed.left, key_range_transformed.right);
|
|
|
|
|
|
|
|
|
|
/* std::cerr << "Function " << func->getName() << " is " << (monotonicity.is_monotonic ? "" : "not ")
|
|
|
|
|
<< "monotonic " << (monotonicity.is_monotonic ? (monotonicity.is_positive ? "(positive) " : "(negative) ") : "")
|
|
|
|
|
<< "in range "
|
|
|
|
|
<< "[" << apply_visitor(FieldVisitorToString(), key_range_transformed.left)
|
|
|
|
|
<< ", " << apply_visitor(FieldVisitorToString(), key_range_transformed.right) << "]\n";*/
|
2015-11-29 08:06:29 +00:00
|
|
|
|
|
|
|
|
|
if (!monotonicity.is_monotonic)
|
|
|
|
|
{
|
|
|
|
|
evaluation_is_not_possible = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Вычисляем функцию.
|
|
|
|
|
DataTypePtr new_type;
|
2015-11-29 11:58:44 +00:00
|
|
|
|
if (!key_range_transformed.left.isNull())
|
|
|
|
|
applyFunction(func, current_type, key_range_transformed.left, new_type, key_range_transformed.left);
|
|
|
|
|
if (!key_range_transformed.right.isNull())
|
|
|
|
|
applyFunction(func, current_type, key_range_transformed.right, new_type, key_range_transformed.right);
|
2015-12-07 19:30:50 +00:00
|
|
|
|
|
|
|
|
|
if (!new_type)
|
|
|
|
|
{
|
|
|
|
|
evaluation_is_not_possible = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
current_type.swap(new_type);
|
|
|
|
|
|
|
|
|
|
if (!monotonicity.is_positive)
|
|
|
|
|
key_range_transformed.swapLeftAndRight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (evaluation_is_not_possible)
|
|
|
|
|
{
|
|
|
|
|
rpn_stack.emplace_back(true, true);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
key_range = &key_range_transformed;
|
|
|
|
|
}
|
2014-03-26 10:56:21 +00:00
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
if (element.function == RPNElement::FUNCTION_IN_RANGE
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_NOT_IN_RANGE)
|
|
|
|
|
{
|
|
|
|
|
bool intersects = element.range.intersectsRange(*key_range);
|
|
|
|
|
bool contains = element.range.containsRange(*key_range);
|
|
|
|
|
|
|
|
|
|
rpn_stack.emplace_back(intersects, !contains);
|
|
|
|
|
if (element.function == RPNElement::FUNCTION_NOT_IN_RANGE)
|
2014-03-31 14:49:43 +00:00
|
|
|
|
rpn_stack.back() = !rpn_stack.back();
|
|
|
|
|
}
|
2015-11-29 08:06:29 +00:00
|
|
|
|
else /// Set
|
2014-03-31 14:49:43 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
auto in_func = typeid_cast<const ASTFunction *>(element.in_function.get());
|
|
|
|
|
const ASTs & args = typeid_cast<const ASTExpressionList &>(*in_func->arguments).children;
|
|
|
|
|
auto ast_set = typeid_cast<const ASTSet *>(args[1].get());
|
|
|
|
|
if (in_func && ast_set)
|
|
|
|
|
{
|
2015-11-29 12:54:58 +00:00
|
|
|
|
rpn_stack.push_back(ast_set->set->mayBeTrueInRange(*key_range));
|
2015-11-29 08:06:29 +00:00
|
|
|
|
if (element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
|
|
|
|
rpn_stack.back() = !rpn_stack.back();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw DB::Exception("Set for IN is not created yet!", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
}
|
2014-03-31 14:49:43 +00:00
|
|
|
|
}
|
2014-03-26 10:56:21 +00:00
|
|
|
|
}
|
2012-12-05 12:44:55 +00:00
|
|
|
|
else if (element.function == RPNElement::FUNCTION_NOT)
|
|
|
|
|
{
|
|
|
|
|
rpn_stack.back() = !rpn_stack.back();
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_AND)
|
|
|
|
|
{
|
2015-03-27 03:06:06 +00:00
|
|
|
|
auto arg1 = rpn_stack.back();
|
2012-12-05 12:44:55 +00:00
|
|
|
|
rpn_stack.pop_back();
|
2015-03-27 03:06:06 +00:00
|
|
|
|
auto arg2 = rpn_stack.back();
|
2012-12-05 12:44:55 +00:00
|
|
|
|
rpn_stack.back() = arg1 & arg2;
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_OR)
|
|
|
|
|
{
|
2015-03-27 03:06:06 +00:00
|
|
|
|
auto arg1 = rpn_stack.back();
|
2012-12-05 12:44:55 +00:00
|
|
|
|
rpn_stack.pop_back();
|
2015-03-27 03:06:06 +00:00
|
|
|
|
auto arg2 = rpn_stack.back();
|
2012-12-05 12:44:55 +00:00
|
|
|
|
rpn_stack.back() = arg1 | arg2;
|
|
|
|
|
}
|
|
|
|
|
else
|
2012-12-10 10:23:10 +00:00
|
|
|
|
throw Exception("Unexpected function type in PKCondition::RPNElement", ErrorCodes::LOGICAL_ERROR);
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
if (rpn_stack.size() != 1)
|
|
|
|
|
throw Exception("Unexpected stack size in PkCondition::mayBeTrueInRange", ErrorCodes::LOGICAL_ERROR);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
return rpn_stack[0].can_be_true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk, const DataTypes & data_types) const
|
2012-12-06 09:45:09 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
return mayBeTrueInRange(left_pk, right_pk, data_types, true);
|
2012-12-06 09:45:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-29 08:06:29 +00:00
|
|
|
|
bool PKCondition::mayBeTrueAfter(const Field * left_pk, const DataTypes & data_types) const
|
2012-12-06 09:45:09 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
return mayBeTrueInRange(left_pk, nullptr, data_types, false);
|
2012-12-06 09:45:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-28 21:00:44 +00:00
|
|
|
|
static const ASTSet & inFunctionToSet(const ASTPtr & in_function)
|
2014-04-01 10:25:56 +00:00
|
|
|
|
{
|
2015-10-28 21:00:44 +00:00
|
|
|
|
const auto & in_func = typeid_cast<const ASTFunction &>(*in_function);
|
|
|
|
|
const auto & args = typeid_cast<const ASTExpressionList &>(*in_func.arguments).children;
|
|
|
|
|
const auto & ast_set = typeid_cast<const ASTSet &>(*args[1]);
|
2014-04-01 10:25:56 +00:00
|
|
|
|
return ast_set;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 03:37:46 +00:00
|
|
|
|
String PKCondition::RPNElement::toString() const
|
2014-04-01 10:25:56 +00:00
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
auto print_wrapped_column = [this](std::ostringstream & ss)
|
|
|
|
|
{
|
|
|
|
|
for (auto it = monotonic_functions_chain.rbegin(); it != monotonic_functions_chain.rend(); ++it)
|
|
|
|
|
ss << (*it)->getName() << "(";
|
|
|
|
|
|
|
|
|
|
ss << "column " << key_column;
|
|
|
|
|
|
|
|
|
|
for (auto it = monotonic_functions_chain.rbegin(); it != monotonic_functions_chain.rend(); ++it)
|
|
|
|
|
ss << ")";
|
|
|
|
|
};
|
|
|
|
|
|
2014-04-01 10:25:56 +00:00
|
|
|
|
std::ostringstream ss;
|
|
|
|
|
switch (function)
|
|
|
|
|
{
|
|
|
|
|
case FUNCTION_AND:
|
|
|
|
|
return "and";
|
|
|
|
|
case FUNCTION_OR:
|
|
|
|
|
return "or";
|
|
|
|
|
case FUNCTION_NOT:
|
|
|
|
|
return "not";
|
|
|
|
|
case FUNCTION_UNKNOWN:
|
|
|
|
|
return "unknown";
|
|
|
|
|
case FUNCTION_NOT_IN_SET:
|
|
|
|
|
case FUNCTION_IN_SET:
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
ss << "(";
|
|
|
|
|
print_wrapped_column(ss);
|
|
|
|
|
ss << (function == FUNCTION_IN_SET ? " in " : " notIn ") << inFunctionToSet(in_function).set->describe();
|
|
|
|
|
ss << ")";
|
2014-04-01 10:25:56 +00:00
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
case FUNCTION_IN_RANGE:
|
|
|
|
|
case FUNCTION_NOT_IN_RANGE:
|
|
|
|
|
{
|
2015-11-29 08:06:29 +00:00
|
|
|
|
ss << "(";
|
|
|
|
|
print_wrapped_column(ss);
|
|
|
|
|
ss << (function == FUNCTION_NOT_IN_RANGE ? " not" : "") << " in " << range.toString();
|
|
|
|
|
ss << ")";
|
2014-04-01 10:25:56 +00:00
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
default:
|
2015-10-28 21:00:44 +00:00
|
|
|
|
throw Exception("Unknown function in RPNElement", ErrorCodes::LOGICAL_ERROR);
|
2014-04-01 10:25:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-27 03:06:06 +00:00
|
|
|
|
|
|
|
|
|
|
2015-03-27 03:37:46 +00:00
|
|
|
|
bool PKCondition::alwaysUnknown() const
|
2015-03-27 03:06:06 +00:00
|
|
|
|
{
|
|
|
|
|
std::vector<UInt8> rpn_stack;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < rpn.size(); ++i)
|
|
|
|
|
{
|
2015-03-27 03:37:46 +00:00
|
|
|
|
const auto & element = rpn[i];
|
2015-03-27 03:06:06 +00:00
|
|
|
|
|
|
|
|
|
if (element.function == RPNElement::FUNCTION_UNKNOWN)
|
|
|
|
|
{
|
|
|
|
|
rpn_stack.push_back(true);
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_NOT_IN_RANGE
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_IN_RANGE
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_IN_SET
|
|
|
|
|
|| element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
|
|
|
|
{
|
|
|
|
|
rpn_stack.push_back(false);
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_NOT)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_AND)
|
|
|
|
|
{
|
|
|
|
|
auto arg1 = rpn_stack.back();
|
|
|
|
|
rpn_stack.pop_back();
|
|
|
|
|
auto arg2 = rpn_stack.back();
|
|
|
|
|
rpn_stack.back() = arg1 & arg2;
|
|
|
|
|
}
|
|
|
|
|
else if (element.function == RPNElement::FUNCTION_OR)
|
|
|
|
|
{
|
|
|
|
|
auto arg1 = rpn_stack.back();
|
|
|
|
|
rpn_stack.pop_back();
|
|
|
|
|
auto arg2 = rpn_stack.back();
|
|
|
|
|
rpn_stack.back() = arg1 | arg2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw Exception("Unexpected function type in PKCondition::RPNElement", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rpn_stack[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-12-05 12:44:55 +00:00
|
|
|
|
}
|