mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
dbms: using numeric constants while evaluating PKCondition [#METR-19758].
This commit is contained in:
parent
e720a53cf2
commit
409954428b
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user