提交 40995442 编写于 作者: A Alexey Milovidov

dbms: using numeric constants while evaluating PKCondition [#METR-19758].

上级 e720a53c
......@@ -201,7 +201,7 @@ public:
bool mayBeTrueAfter(const Field * left_pk, const DataTypes & data_types) const;
/// Проверяет, что индекс не может быть использован.
bool alwaysUnknown() const;
bool alwaysUnknownOrTrue() const;
/// Наложить дополнительное условие: значение в столбце column должно быть в диапазоне range.
/// Возвращает, есть ли такой столбец в первичном ключе.
......@@ -230,6 +230,9 @@ private:
FUNCTION_NOT,
FUNCTION_AND,
FUNCTION_OR,
/// Константы
ALWAYS_FALSE,
ALWAYS_TRUE,
};
RPNElement() {}
......
......@@ -141,10 +141,10 @@ BlockInputStreams MergeTreeDataSelectExecutor::read(
PKCondition key_condition(query, context, data.getColumnsList(), data.getSortDescription());
PKCondition date_condition(query, context, data.getColumnsList(), SortDescription(1, SortColumnDescription(data.date_column_name, 1)));
if (settings.force_primary_key && key_condition.alwaysUnknown())
if (settings.force_primary_key && key_condition.alwaysUnknownOrTrue())
throw Exception("Primary key is not used and setting 'force_primary_key' is set.", ErrorCodes::INDEX_NOT_USED);
if (settings.force_index_by_date && date_condition.alwaysUnknown())
if (settings.force_index_by_date && date_condition.alwaysUnknownOrTrue())
throw Exception("Index by date is not used and setting 'force_index_by_date' is set.", ErrorCodes::INDEX_NOT_USED);
/// Выберем куски, в которых могут быть данные, удовлетворяющие date_condition, и которые подходят под условие на _part,
......@@ -811,7 +811,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange(
size_t marks_count = index.size() / key_size;
/// Если индекс не используется.
if (key_condition.alwaysUnknown())
if (key_condition.alwaysUnknownOrTrue())
{
res.push_back(MarkRange(0, marks_count));
}
......
......@@ -265,8 +265,10 @@ bool PKCondition::isPrimaryKeyPossiblyWrappedByMonotonicFunctionsImpl(
bool PKCondition::atomFromAST(ASTPtr & node, const Context & context, Block & block_with_constants, RPNElement & out)
{
/** Функции < > = != <= >= in notIn, у которых один агрумент константа, другой - один из столбцов первичного ключа,
* либо он же, завёрнутый в цепочку возможно-монотонных функций.
* либо он же, завёрнутый в цепочку возможно-монотонных функций,
* либо константное выражение - число.
*/
Field value;
if (const ASTFunction * func = typeid_cast<const ASTFunction *>(&*node))
{
const ASTs & args = typeid_cast<const ASTExpressionList &>(*func->arguments).children;
......@@ -277,7 +279,6 @@ bool PKCondition::atomFromAST(ASTPtr & node, const Context & context, Block & bl
/// Если true, слева константа.
bool inverted;
size_t column;
Field value;
RPNElement::MonotonicFunctionsChain chain;
if (getConstant(args[1], block_with_constants, value) && isPrimaryKeyPossiblyWrappedByMonotonicFunctions(args[0], context, column, chain))
......@@ -326,6 +327,20 @@ bool PKCondition::atomFromAST(ASTPtr & node, const Context & context, Block & bl
return true;
}
else if (getConstant(node, block_with_constants, value)) /// Для случаев, когда написано, например, WHERE 0 AND something
{
if (value.getType() == Field::Types::UInt64
|| value.getType() == Field::Types::Int64
|| value.getType() == Field::Types::Float64)
{
/// Ноль во всех типах представлен в памяти так же, как в UInt64.
out.function = value.get<UInt64>()
? RPNElement::ALWAYS_TRUE
: RPNElement::ALWAYS_FALSE;
return true;
}
}
return false;
}
......@@ -525,6 +540,14 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
auto arg2 = rpn_stack.back();
rpn_stack.back() = arg1 | arg2;
}
else if (element.function == RPNElement::ALWAYS_FALSE)
{
rpn_stack.emplace_back(false, true);
}
else if (element.function == RPNElement::ALWAYS_TRUE)
{
rpn_stack.emplace_back(true, false);
}
else
throw Exception("Unexpected function type in PKCondition::RPNElement", ErrorCodes::LOGICAL_ERROR);
}
......@@ -595,13 +618,17 @@ String PKCondition::RPNElement::toString() const
ss << ")";
return ss.str();
}
case ALWAYS_FALSE:
return "false";
case ALWAYS_TRUE:
return "true";
default:
throw Exception("Unknown function in RPNElement", ErrorCodes::LOGICAL_ERROR);
}
}
bool PKCondition::alwaysUnknown() const
bool PKCondition::alwaysUnknownOrTrue() const
{
std::vector<UInt8> rpn_stack;
......@@ -609,14 +636,16 @@ bool PKCondition::alwaysUnknown() const
{
const auto & element = rpn[i];
if (element.function == RPNElement::FUNCTION_UNKNOWN)
if (element.function == RPNElement::FUNCTION_UNKNOWN
|| element.function == RPNElement::ALWAYS_TRUE)
{
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)
|| element.function == RPNElement::FUNCTION_NOT_IN_SET
|| element.function == RPNElement::ALWAYS_FALSE)
{
rpn_stack.push_back(false);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册