Skip to content

Commit

Permalink
fix map hash method (#4707)
Browse files Browse the repository at this point in the history
  • Loading branch information
jievince committed Oct 11, 2022
1 parent 79a7b46 commit adf9d87
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/common/datatypes/Map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ std::size_t hash<nebula::Map>::operator()(const nebula::Map& m) const noexcept {
size_t seed = 0;
for (auto& v : m.kvs) {
seed ^= hash<std::string>()(v.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= hash<nebula::Value>()(v.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
Expand Down
67 changes: 67 additions & 0 deletions src/common/datatypes/test/ValueTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* This source code is licensed under Apache 2.0 License.
*/
#include <gtest/gtest.h>
#include <robin_hood.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>

#include "common/base/Base.h"
Expand Down Expand Up @@ -1708,6 +1709,72 @@ TEST(Value, DedupByConstRowPointer) {
ASSERT_EQ(unique.size(), 1);
}

TEST(Value, Hash) {
{
std::vector<Row> rows;
for (size_t i = 0; i < 128; ++i) {
Row row;
Map m;
m.kvs.emplace("prop1", static_cast<int64_t>(i));
row.values.emplace_back(m);
rows.emplace_back(row);
}
EXPECT_EQ(rows.size(), 128);

robin_hood::unordered_flat_set<const Row*, std::hash<const Row*>> unique;
unique.reserve(rows.size());
for (auto& row : rows) {
unique.emplace(&row);
}
EXPECT_EQ(unique.size(), 128);
}
{
std::vector<Map> maps;
for (size_t i = 0; i < 128; ++i) {
Map m;
m.kvs.emplace("prop1", static_cast<int64_t>(i));
maps.emplace_back(m);
}
EXPECT_EQ(maps.size(), 128);

robin_hood::unordered_flat_set<Map, std::hash<Map>> unique;
unique.reserve(maps.size());
for (auto& m : maps) {
unique.emplace(m);
}
EXPECT_EQ(unique.size(), 128);
}
{
std::vector<Map> maps;
for (size_t i = 0; i < 128; ++i) {
Map m;
m.kvs.emplace("prop1", static_cast<int64_t>(i));
maps.emplace_back(m);
}
EXPECT_EQ(maps.size(), 128);

struct BadMapHasher {
size_t operator()(const Map& m) const {
size_t seed = 0;
for (auto& v : m.kvs) {
// Only the `key` participates in the hash, `value` is ignored.
// It's easy to lead to hash collision if the `key` is the same.
seed ^= std::hash<std::string>()(v.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
robin_hood::unordered_flat_set<Map, BadMapHasher> unique;
unique.reserve(maps.size());
for (size_t i = 0; i < maps.size() - 1; ++i) {
unique.emplace(maps[i]);
}
EXPECT_EQ(unique.size(), 127);
// std::overflow_error: robin_hood::map overflow
EXPECT_THROW(unique.emplace(maps.back()), std::overflow_error);
}
}

} // namespace nebula

int main(int argc, char** argv) {
Expand Down
7 changes: 7 additions & 0 deletions tests/tck/features/go/GO.feature
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ Feature: Go Sentence
Then the result should be, in any order, with relax comparison:
| serve._dst |
| "Spurs" |
When executing query:
"""
GO FROM "Tim Duncan" OVER serve YIELD DISTINCT properties(edge) | YIELD COUNT(*)
"""
Then the result should be, in any order, with relax comparison:
| COUNT(*) |
| 1 |
When executing query:
"""
GO FROM "Tim Duncan", "Tony Parker" OVER like WHERE $$.player.age > 9223372036854775807+1 YIELD like._dst
Expand Down

0 comments on commit adf9d87

Please sign in to comment.