mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-29 02:52:13 +00:00
NOT LIKE only work for 'prefix%'
This commit is contained in:
parent
a8bce28c04
commit
69d6d42443
@ -29,6 +29,7 @@
|
|||||||
#include <Storages/KeyDescription.h>
|
#include <Storages/KeyDescription.h>
|
||||||
#include <Storages/MergeTree/MergeTreeIndexUtils.h>
|
#include <Storages/MergeTree/MergeTreeIndexUtils.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -55,11 +56,15 @@ String Range::toString() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Example: for `Hello\_World% ...` string it returns `Hello_World`, and for `%test%` returns an empty string.
|
/// Returns the prefix of like_pattern before the first wildcard, e.g. 'Hello\_World% ...' --> 'Hello\_World'
|
||||||
/// If perfect_prefix_match == true, only consider pattern in the format `prefix%_`
|
/// We call a prefix "perfect" if:
|
||||||
String extractFixedPrefixFromLikePattern(const String & like_pattern, bool perfect_prefix_match)
|
/// - (1) the prefix must have willcard
|
||||||
|
/// - (2) the first wildcard is '%' and is only followed by nothing or other '%'
|
||||||
|
/// e.g. 'test%' or 'test%% has perfect prefix 'test', 'test%x', 'test%_' or 'test_' has no perfect prefix.
|
||||||
|
String extractFixedPrefixFromLikePattern(std::string_view like_pattern, bool require_perfect_prefix)
|
||||||
{
|
{
|
||||||
String fixed_prefix;
|
String fixed_prefix;
|
||||||
|
fixed_prefix.reserve(like_pattern.size());
|
||||||
|
|
||||||
const char * pos = like_pattern.data();
|
const char * pos = like_pattern.data();
|
||||||
const char * end = pos + like_pattern.size();
|
const char * end = pos + like_pattern.size();
|
||||||
@ -68,12 +73,13 @@ String extractFixedPrefixFromLikePattern(const String & like_pattern, bool perfe
|
|||||||
switch (*pos)
|
switch (*pos)
|
||||||
{
|
{
|
||||||
case '%':
|
case '%':
|
||||||
[[fallthrough]];
|
|
||||||
case '_':
|
case '_':
|
||||||
if (perfect_prefix_match && std::find_if(pos+1, end, [](const char c) { return c != '%' && c != '_'; }) != end)
|
if (require_perfect_prefix)
|
||||||
return "";
|
{
|
||||||
|
bool is_prefect_prefix = std::all_of(pos, end, [](auto c) { return c == '%'; });
|
||||||
|
return is_prefect_prefix ? fixed_prefix : "";
|
||||||
|
}
|
||||||
return fixed_prefix;
|
return fixed_prefix;
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
++pos;
|
++pos;
|
||||||
if (pos == end)
|
if (pos == end)
|
||||||
@ -81,12 +87,13 @@ String extractFixedPrefixFromLikePattern(const String & like_pattern, bool perfe
|
|||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
fixed_prefix += *pos;
|
fixed_prefix += *pos;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
/// If we can reach this code, it means there was no wildcard found in the pattern, so it is not a perfect prefix
|
||||||
|
if (require_perfect_prefix)
|
||||||
|
return "";
|
||||||
return fixed_prefix;
|
return fixed_prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +356,7 @@ const KeyCondition::AtomMap KeyCondition::atom_map
|
|||||||
if (value.getType() != Field::Types::String)
|
if (value.getType() != Field::Types::String)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
String prefix = extractFixedPrefixFromLikePattern(value.get<const String &>());
|
String prefix = extractFixedPrefixFromLikePattern(value.get<const String &>(), /*required_perfect_prefix*/ false);
|
||||||
if (prefix.empty())
|
if (prefix.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -370,7 +377,7 @@ const KeyCondition::AtomMap KeyCondition::atom_map
|
|||||||
if (value.getType() != Field::Types::String)
|
if (value.getType() != Field::Types::String)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
String prefix = extractFixedPrefixFromLikePattern(value.get<const String &>(), true);
|
String prefix = extractFixedPrefixFromLikePattern(value.get<const String &>(), /*required_perfect_prefix*/ true);
|
||||||
if (prefix.empty())
|
if (prefix.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -485,6 +485,6 @@ private:
|
|||||||
bool strict;
|
bool strict;
|
||||||
};
|
};
|
||||||
|
|
||||||
String extractFixedPrefixFromLikePattern(const String & like_pattern, bool perfect_prefix_match = false);
|
String extractFixedPrefixFromLikePattern(std::string_view like_pattern, bool require_perfect_prefix);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ void StorageSystemMergeTreeMetadataCache::fillData(MutableColumns & res_columns,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String target = extractFixedPrefixFromLikePattern(key);
|
String target = extractFixedPrefixFromLikePattern(key, /*required_perfect_prefix*/ false);
|
||||||
if (target.empty())
|
if (target.empty())
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"SELECT from system.merge_tree_metadata_cache table must contain condition like key = 'key' or key LIKE 'prefix%' in WHERE clause.", ErrorCodes::BAD_ARGUMENTS);
|
"SELECT from system.merge_tree_metadata_cache table must contain condition like key = 'key' or key LIKE 'prefix%' in WHERE clause.", ErrorCodes::BAD_ARGUMENTS);
|
||||||
|
@ -1 +1,2 @@
|
|||||||
200000
|
200000
|
||||||
|
200000
|
||||||
|
@ -2,4 +2,11 @@ CREATE TABLE data (str String) ENGINE=MergeTree ORDER BY str;
|
|||||||
INSERT INTO data (str) SELECT 'aa' FROM numbers(100000);
|
INSERT INTO data (str) SELECT 'aa' FROM numbers(100000);
|
||||||
INSERT INTO data (str) SELECT 'ba' FROM numbers(100000);
|
INSERT INTO data (str) SELECT 'ba' FROM numbers(100000);
|
||||||
INSERT INTO data (str) SELECT 'ca' FROM numbers(100000);
|
INSERT INTO data (str) SELECT 'ca' FROM numbers(100000);
|
||||||
SELECT count()FROM data WHERE str NOT LIKE 'a%' SETTINGS force_primary_key=1;
|
SELECT count() FROM data WHERE str NOT LIKE 'a%' SETTINGS force_primary_key=1;
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE 'a%%' SETTINGS force_primary_key=1;
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE 'a' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE '%a' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE 'a_' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE 'a%_' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE '_a' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
SELECT count() FROM data WHERE str NOT LIKE 'a%\_' SETTINGS force_primary_key=1; -- { serverError 277 }
|
||||||
|
Loading…
Reference in New Issue
Block a user