@zhyass and I found some codes may be incorrect in

https://github.com/ClickHouse/ClickHouse/blob/33ffe11d0397aa6904c246172223b1da1fbcf1cc/src/Storages/MergeTree/KeyCondition.cpp#L280-L297

It tries to extract fixed prefix from the like pattern to find the range, but it's wrong, A counterexample is ：

like_pattern  -> "a%c",  the prefix will be "a" and the range will be ` Range("a", true,"b", false)` yet the String "axxxxxd" still not match match this pattern (  axxxxxd not like a%c => true  ).

`Not like` is not the reverse of `Like` in continuous key ranges.

The only special case to work fine for "not like" to range is that string pattern ends with "%" or "_" , eg:    'a%', 'a\_'

cc @alexey-milovidov 
}
    /** Evaluation of expressions that depend only on constants.
      * For the index to be used, if it is written, for example `WHERE Date = toDate(now())`.
      */
    Block block_with_constants = getBlockWithConstants(query_info.query, query_info.syntax_analyzer_result, context);
    for (const auto & [name, _] : query_info.syntax_analyzer_result->array_join_result_to_source)
        array_joined_columns.insert(name);
    const ASTSelectQuery & select = query_info.query->as<ASTSelectQuery &>();
    if (select.where() || select.prewhere())
    {
        ASTPtr filter_query;
        if (select.where() && select.prewhere())
            filter_query = makeASTFunction("and", select.where(), select.prewhere());
        else
            filter_query = select.where() ? select.where() : select.prewhere();
        /** When non-strictly monotonic functions are employed in functional index (e.g. ORDER BY toStartOfHour(dateTime)),
          * the use of NOT operator in predicate will result in the indexing algorithm leave out some data.
          * This is caused by rewriting in KeyCondition::tryParseAtomFromAST of relational operators to less strict
          * when parsing the AST into internal RPN representation.
          * To overcome the problem, before parsing the AST we transform it to its semantically equivalent form where all NOT's
          * are pushed down and applied (when possible) to leaf nodes.
          */
        traverseAST(cloneASTWithInversionPushDown(filter_query), context, block_with_constants);
    }
    else
    {
        rpn.emplace_back(RPNElement::FUNCTION_UNKNOWN);
    }
}
bool KeyCondition::addCondition(const String & column, const Range & range)