Add support for decimals to PatternEntry (#9577)
Summary: Add support for doubles to ObjectLibrary::PatternEntry. This support will allow patterns containing a non-integer number to be parsed correctly. Added appropriate test cases to cover this new option. Pull Request resolved: https://github.com/facebook/rocksdb/pull/9577 Reviewed By: pdillinger Differential Revision: D34269763 Pulled By: mrambacher fbshipit-source-id: b5ce16cbd3665c2974ec0f3412ef2b403ef8b155
This commit is contained in:
parent
48f6c2a049
commit
c42d0cf862
@ -64,7 +64,7 @@
|
||||
* Remove deprecated overloads of API DB::GetApproximateSizes.
|
||||
* Remove deprecated option DBOptions::new_table_reader_for_compaction_inputs.
|
||||
* Add Transaction::SetReadTimestampForValidation() and Transaction::SetCommitTimestamp(). Default impl returns NotSupported().
|
||||
|
||||
* Add support for decimal patterns to ObjectLibrary::PatternEntry
|
||||
### Behavior Changes
|
||||
* Disallow the combination of DBOptions.use_direct_io_for_flush_and_compaction == true and DBOptions.writable_file_max_buffer_size == 0. This combination can cause WritableFileWriter::Append() to loop forever, and it does not make much sense in direct IO.
|
||||
* `ReadOptions::total_order_seek` no longer affects `DB::Get()`. The original motivation for this interaction has been obsolete since RocksDB has been able to detect whether the current prefix extractor is compatible with that used to generate table files, probably RocksDB 5.14.0.
|
||||
|
@ -75,7 +75,8 @@ class ObjectLibrary {
|
||||
kMatchZeroOrMore, // [suffix].*
|
||||
kMatchAtLeastOne, // [suffix].+
|
||||
kMatchExact, // [suffix]
|
||||
kMatchNumeric, // [suffix][0-9]+
|
||||
kMatchInteger, // [suffix][0-9]+
|
||||
kMatchDecimal, // [suffix][0-9]+[.][0-9]+
|
||||
};
|
||||
|
||||
public:
|
||||
@ -123,8 +124,9 @@ class ObjectLibrary {
|
||||
|
||||
// Adds a separator (exact match of separator with trailing numbers) to the
|
||||
// entry
|
||||
PatternEntry& AddNumber(const std::string& separator) {
|
||||
separators_.emplace_back(separator, kMatchNumeric);
|
||||
PatternEntry& AddNumber(const std::string& separator, bool is_int = true) {
|
||||
separators_.emplace_back(separator,
|
||||
(is_int) ? kMatchInteger : kMatchDecimal);
|
||||
slength_ += separator.size() + 1;
|
||||
return *this;
|
||||
}
|
||||
|
@ -15,6 +15,39 @@
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
#ifndef ROCKSDB_LITE
|
||||
namespace {
|
||||
bool MatchesInteger(const std::string &target, size_t start, size_t pos) {
|
||||
// If it is numeric, everything up to the match must be a number
|
||||
int digits = 0;
|
||||
while (start < pos) {
|
||||
if (!isdigit(target[start++])) {
|
||||
return false;
|
||||
} else {
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
return (digits > 0);
|
||||
}
|
||||
|
||||
bool MatchesDecimal(const std::string &target, size_t start, size_t pos) {
|
||||
int digits = 0;
|
||||
for (bool point = false; start < pos; start++) {
|
||||
if (target[start] == '.') {
|
||||
if (point) {
|
||||
return false;
|
||||
} else {
|
||||
point = true;
|
||||
}
|
||||
} else if (!isdigit(target[start])) {
|
||||
return false;
|
||||
} else {
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
return (digits > 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
size_t ObjectLibrary::PatternEntry::MatchSeparatorAt(
|
||||
size_t start, Quantifier mode, const std::string &target, size_t tlen,
|
||||
const std::string &separator) const {
|
||||
@ -36,12 +69,13 @@ size_t ObjectLibrary::PatternEntry::MatchSeparatorAt(
|
||||
}
|
||||
if (pos == std::string::npos) {
|
||||
return pos;
|
||||
} else if (mode == kMatchNumeric) {
|
||||
// If it is numeric, everything up to the match must be a number
|
||||
while (start < pos) {
|
||||
if (!isdigit(target[start++])) {
|
||||
return std::string::npos;
|
||||
}
|
||||
} else if (mode == kMatchInteger) {
|
||||
if (!MatchesInteger(target, start, pos)) {
|
||||
return std::string::npos;
|
||||
}
|
||||
} else if (mode == kMatchDecimal) {
|
||||
if (!MatchesDecimal(target, start, pos)) {
|
||||
return std::string::npos;
|
||||
}
|
||||
}
|
||||
return pos + slen;
|
||||
@ -84,12 +118,10 @@ bool ObjectLibrary::PatternEntry::MatchesTarget(const std::string &name,
|
||||
return (start == tlen);
|
||||
} else if (start > tlen || (start == tlen && mode != kMatchZeroOrMore)) {
|
||||
return false;
|
||||
} else if (mode == kMatchNumeric) {
|
||||
while (start < tlen) {
|
||||
if (!isdigit(target[start++])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (mode == kMatchInteger) {
|
||||
return MatchesInteger(target, start, tlen);
|
||||
} else if (mode == kMatchDecimal) {
|
||||
return MatchesDecimal(target, start, tlen);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -599,6 +599,69 @@ TEST_F(PatternEntryTest, TestNumericEntry) {
|
||||
ASSERT_FALSE(entry.Matches("A:B"));
|
||||
ASSERT_FALSE(entry.Matches("A:1B"));
|
||||
ASSERT_FALSE(entry.Matches("A:B1"));
|
||||
|
||||
entry.AddSeparator(":", false);
|
||||
ASSERT_FALSE(entry.Matches("A"));
|
||||
ASSERT_FALSE(entry.Matches("AA"));
|
||||
ASSERT_FALSE(entry.Matches("A:"));
|
||||
ASSERT_FALSE(entry.Matches("AA:"));
|
||||
ASSERT_TRUE(entry.Matches("A:1:"));
|
||||
ASSERT_TRUE(entry.Matches("A:11:"));
|
||||
ASSERT_FALSE(entry.Matches("A:1"));
|
||||
ASSERT_FALSE(entry.Matches("A:B1:"));
|
||||
ASSERT_FALSE(entry.Matches("A:1B:"));
|
||||
ASSERT_FALSE(entry.Matches("A::"));
|
||||
}
|
||||
|
||||
TEST_F(PatternEntryTest, TestDoubleEntry) {
|
||||
ObjectLibrary::PatternEntry entry("A", false);
|
||||
entry.AddNumber(":", false);
|
||||
ASSERT_FALSE(entry.Matches("A"));
|
||||
ASSERT_FALSE(entry.Matches("AA"));
|
||||
ASSERT_FALSE(entry.Matches("A:"));
|
||||
ASSERT_FALSE(entry.Matches("AA:"));
|
||||
ASSERT_FALSE(entry.Matches("AA:1"));
|
||||
ASSERT_FALSE(entry.Matches("AA:11"));
|
||||
ASSERT_FALSE(entry.Matches("A:B"));
|
||||
ASSERT_FALSE(entry.Matches("A:1B"));
|
||||
ASSERT_FALSE(entry.Matches("A:B1"));
|
||||
ASSERT_TRUE(entry.Matches("A:1"));
|
||||
ASSERT_TRUE(entry.Matches("A:11"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.1"));
|
||||
ASSERT_TRUE(entry.Matches("A:11.11"));
|
||||
ASSERT_TRUE(entry.Matches("A:1."));
|
||||
ASSERT_TRUE(entry.Matches("A:.1"));
|
||||
ASSERT_TRUE(entry.Matches("A:0.1"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.0"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.0"));
|
||||
|
||||
ASSERT_FALSE(entry.Matches("A:1.0."));
|
||||
ASSERT_FALSE(entry.Matches("A:1.0.2"));
|
||||
ASSERT_FALSE(entry.Matches("A:.1.0"));
|
||||
ASSERT_FALSE(entry.Matches("A:..10"));
|
||||
ASSERT_FALSE(entry.Matches("A:10.."));
|
||||
ASSERT_FALSE(entry.Matches("A:."));
|
||||
|
||||
entry.AddSeparator(":", false);
|
||||
ASSERT_FALSE(entry.Matches("A:1"));
|
||||
ASSERT_FALSE(entry.Matches("A:1.0"));
|
||||
|
||||
ASSERT_TRUE(entry.Matches("A:11:"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.1:"));
|
||||
ASSERT_TRUE(entry.Matches("A:11.11:"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.:"));
|
||||
ASSERT_TRUE(entry.Matches("A:.1:"));
|
||||
ASSERT_TRUE(entry.Matches("A:0.1:"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.0:"));
|
||||
ASSERT_TRUE(entry.Matches("A:1.0:"));
|
||||
|
||||
ASSERT_FALSE(entry.Matches("A:1.0.:"));
|
||||
ASSERT_FALSE(entry.Matches("A:1.0.2:"));
|
||||
ASSERT_FALSE(entry.Matches("A:.1.0:"));
|
||||
ASSERT_FALSE(entry.Matches("A:..10:"));
|
||||
ASSERT_FALSE(entry.Matches("A:10..:"));
|
||||
ASSERT_FALSE(entry.Matches("A:.:"));
|
||||
ASSERT_FALSE(entry.Matches("A::"));
|
||||
}
|
||||
|
||||
TEST_F(PatternEntryTest, TestIndividualIdEntry) {
|
||||
|
Loading…
Reference in New Issue
Block a user