From 32a4c7cd19758c816b954ab1eda1132e9ebc10b2 Mon Sep 17 00:00:00 2001 From: Thespica Date: Thu, 1 Feb 2024 23:24:57 +0800 Subject: [PATCH 1/3] Support nullable key --- cpp/.gitignore | 1 + cpp/include/gar/graph_info.h | 29 ++++++++++++++++++++++++----- cpp/src/graph_info.cc | 28 ++++++++++++++++++++++++++-- cpp/test/test_info.cc | 18 ++++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/cpp/.gitignore b/cpp/.gitignore index 4f3221962..29b5a5943 100644 --- a/cpp/.gitignore +++ b/cpp/.gitignore @@ -1,5 +1,6 @@ /build/ /examples/*/build/ +/cmake-build-debug apidoc/html apidoc/xml diff --git a/cpp/include/gar/graph_info.h b/cpp/include/gar/graph_info.h index d319e1075..d55627916 100644 --- a/cpp/include/gar/graph_info.h +++ b/cpp/include/gar/graph_info.h @@ -33,16 +33,20 @@ class Property { std::string name; // property name std::shared_ptr type; // property data type bool is_primary; // primary key tag + bool is_nullable; // nullable tag for non-primary key explicit Property(const std::string& name, const std::shared_ptr& type = nullptr, - bool is_primary = false) - : name(name), type(type), is_primary(is_primary) {} + bool is_primary = false, bool is_nullable = true) + : name(name), + type(type), + is_primary(is_primary), + is_nullable(!is_primary && is_nullable) {} }; static bool operator==(const Property& lhs, const Property& rhs) { return (lhs.name == rhs.name) && (lhs.type == rhs.type) && - (lhs.is_primary == rhs.is_primary); + (lhs.is_primary == rhs.is_primary) && (lhs.is_nullable == rhs.is_nullable); } /** @@ -271,6 +275,14 @@ class VertexInfo { */ bool IsPrimaryKey(const std::string& property_name) const; + /** + * Returns whether the specified property is a nullable key. + * + * @param property_name The name of the property. + * @return True if the property is a nullable key, False otherwise. + */ + bool IsNullableKey(const std::string& property_name) const; + /** * Returns whether the vertex info contains the specified property group. * @@ -596,11 +608,18 @@ class EdgeInfo { * Returns whether the specified property is a primary key. * * @param property_name The name of the property. - * @return A Result object containing a bool indicating whether the property - * is a primary key, or a KeyError Status object if the property is not found. + * @return True if the property is a primary key, False otherwise. */ bool IsPrimaryKey(const std::string& property_name) const; + /** + * Returns whether the specified property is a nullable key. + * + * @param property_name The name of the property. + * @return True if the property is a nullable key, False otherwise. + */ + bool IsNullableKey(const std::string& property_name) const; + /** * Saves the edge info to a YAML file. * diff --git a/cpp/src/graph_info.cc b/cpp/src/graph_info.cc index c001b969e..d2b32779e 100644 --- a/cpp/src/graph_info.cc +++ b/cpp/src/graph_info.cc @@ -184,6 +184,7 @@ class VertexInfo::Impl { for (const auto& p : pg->GetProperties()) { property_name_to_index_.emplace(p.name, i); property_name_to_primary_.emplace(p.name, p.is_primary); + property_name_to_nullable_.emplace(p.name, p.is_nullable); property_name_to_type_.emplace(p.name, p.type); } } @@ -220,6 +221,7 @@ class VertexInfo::Impl { std::shared_ptr version_; std::unordered_map property_name_to_index_; std::unordered_map property_name_to_primary_; + std::unordered_map property_name_to_nullable_; std::unordered_map> property_name_to_type_; }; @@ -291,6 +293,14 @@ bool VertexInfo::IsPrimaryKey(const std::string& property_name) const { return it->second; } +bool VertexInfo::IsNullableKey(const std::string &property_name) const { + auto it = impl_->property_name_to_nullable_.find(property_name); + if (it == impl_->property_name_to_nullable_.end()) { + return false; + } + return it->second; +} + bool VertexInfo::HasProperty(const std::string& property_name) const { return impl_->property_name_to_index_.find(property_name) != impl_->property_name_to_index_.end(); @@ -382,7 +392,8 @@ Result> VertexInfo::Load( auto property_type = DataType::TypeNameToDataType(p_node["data_type"].As()); bool is_primary = p_node["is_primary"].As(); - property_vec.emplace_back(property_name, property_type, is_primary); + bool is_nullable = p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); + property_vec.emplace_back(property_name, property_type, is_primary, is_nullable); } property_groups.push_back( std::make_shared(property_vec, file_type, pg_prefix)); @@ -416,6 +427,7 @@ Result VertexInfo::Dump() const noexcept { p_node["name"] = p.name; p_node["data_type"] = p.type->ToTypeName(); p_node["is_primary"] = p.is_primary ? "true" : "false"; + p_node["is_nullable"] = p.is_nullable ? "true" : "false"; pg_node["properties"].PushBack(); pg_node["properties"][pg_node["properties"].Size() - 1] = p_node; } @@ -469,6 +481,7 @@ class EdgeInfo::Impl { for (const auto& p : pg->GetProperties()) { property_name_to_index_.emplace(p.name, i); property_name_to_primary_.emplace(p.name, p.is_primary); + property_name_to_nullable_.emplace(p.name, p.is_nullable); property_name_to_type_.emplace(p.name, p.type); } } @@ -522,6 +535,7 @@ class EdgeInfo::Impl { std::unordered_map adjacent_list_type_to_index_; std::unordered_map property_name_to_index_; std::unordered_map property_name_to_primary_; + std::unordered_map property_name_to_nullable_; std::unordered_map> property_name_to_type_; std::shared_ptr version_; @@ -706,6 +720,14 @@ bool EdgeInfo::IsPrimaryKey(const std::string& property_name) const { return it->second; } +bool EdgeInfo::IsNullableKey(const std::string &property_name) const { + auto it = impl_->property_name_to_nullable_.find(property_name); + if (it == impl_->property_name_to_nullable_.end()) { + return false; + } + return it->second; +} + Result> EdgeInfo::AddAdjacentList( std::shared_ptr adj_list) const { if (adj_list == nullptr) { @@ -817,7 +839,8 @@ Result> EdgeInfo::Load(std::shared_ptr yaml) { auto property_type = DataType::TypeNameToDataType(p_node["data_type"].As()); bool is_primary = p_node["is_primary"].As(); - property_vec.emplace_back(property_name, property_type, is_primary); + bool is_nullable = p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); + property_vec.emplace_back(property_name, property_type, is_primary, is_nullable); } property_groups.push_back( std::make_shared(property_vec, file_type, pg_prefix)); @@ -869,6 +892,7 @@ Result EdgeInfo::Dump() const noexcept { p_node["name"] = p.name; p_node["data_type"] = p.type->ToTypeName(); p_node["is_primary"] = p.is_primary ? "true" : "false"; + p_node["is_nullable"] = p.is_nullable ? "true" : "false"; pg_node["properties"].PushBack(); pg_node["properties"][pg_node["properties"].Size() - 1] = p_node; } diff --git a/cpp/test/test_info.cc b/cpp/test/test_info.cc index a67619fcd..252bfb345 100644 --- a/cpp/test/test_info.cc +++ b/cpp/test/test_info.cc @@ -71,7 +71,9 @@ TEST_CASE("Property") { REQUIRE(p0.name == "p0"); REQUIRE(p0.type->ToTypeName() == int32()->ToTypeName()); REQUIRE(p0.is_primary == true); + REQUIRE(p0.is_nullable == false); REQUIRE(p1.is_primary == false); + REQUIRE(p1.is_nullable == true); } TEST_CASE("PropertyGroup") { @@ -95,6 +97,7 @@ TEST_CASE("PropertyGroup") { REQUIRE(p.name == "p0"); REQUIRE(p.type->ToTypeName() == int32()->ToTypeName()); REQUIRE(p.is_primary == true); + REQUIRE(p.is_nullable == false); } SECTION("FileType") { @@ -199,6 +202,8 @@ TEST_CASE("VertexInfo") { int32()->ToTypeName()); REQUIRE(vertex_info->IsPrimaryKey("p0") == true); REQUIRE(vertex_info->IsPrimaryKey("p1") == false); + REQUIRE(vertex_info->IsNullableKey("p0") == false); + REQUIRE(vertex_info->IsNullableKey("p1") == true); REQUIRE(vertex_info->HasProperty("not_exist") == false); REQUIRE(vertex_info->IsPrimaryKey("not_exist") == false); REQUIRE(vertex_info->HasPropertyGroup(nullptr) == false); @@ -242,9 +247,11 @@ prefix: test_vertex prefix: p0_p1/ properties: - data_type: int32 + is_nullable: false is_primary: true name: p0 - data_type: string + is_nullable: true is_primary: false name: p1 version: gar/v1 @@ -269,6 +276,7 @@ version: gar/v1 REQUIRE(extend_info->GetPropertyType("p2").value()->ToTypeName() == int32()->ToTypeName()); REQUIRE(extend_info->IsPrimaryKey("p2") == false); + REQUIRE(extend_info->IsNullableKey("p2") == true); auto extend_info2 = extend_info->AddPropertyGroup(pg2); REQUIRE(!extend_info2.status().ok()); } @@ -327,8 +335,11 @@ TEST_CASE("EdgeInfo") { int32()->ToTypeName()); REQUIRE(edge_info->IsPrimaryKey("p0") == true); REQUIRE(edge_info->IsPrimaryKey("p1") == false); + REQUIRE(edge_info->IsNullableKey("p0") == false); + REQUIRE(edge_info->IsNullableKey("p1") == true); REQUIRE(edge_info->HasProperty("not_exist") == false); REQUIRE(edge_info->IsPrimaryKey("not_exist") == false); + REQUIRE(edge_info->IsNullableKey("not_exist") == false); REQUIRE(edge_info->HasPropertyGroup(nullptr) == false); } @@ -410,9 +421,11 @@ prefix: test_edge/ prefix: p0_p1/ properties: - data_type: int32 + is_nullable: false is_primary: true name: p0 - data_type: string + is_nullable: true is_primary: false name: p1 src_chunk_size: 100 @@ -601,17 +614,21 @@ prefix: vertex/person/ - name: id data_type: int64 is_primary: true + is_nullable: false file_type: parquet - properties: - name: firstName data_type: string is_primary: false + is_nullable: true - name: lastName data_type: string is_primary: false + is_nullable: true - name: gender data_type: string is_primary: false + is_nullable: true file_type: parquet version: gar/v1 )"; @@ -639,6 +656,7 @@ prefix: edge/person_knows_person/ - name: creationDate data_type: string is_primary: false + is_nullable: true version: gar/v1 )"; std::string graph_info_yaml = R"(name: ldbc_sample From dfab2d119867543e0eb1254e5494a636f97ad9eb Mon Sep 17 00:00:00 2001 From: Thespica Date: Fri, 2 Feb 2024 01:42:14 +0800 Subject: [PATCH 2/3] Fix format --- cpp/include/gar/graph_info.h | 3 ++- cpp/src/graph_info.cc | 36 ++++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/cpp/include/gar/graph_info.h b/cpp/include/gar/graph_info.h index d55627916..1d6674562 100644 --- a/cpp/include/gar/graph_info.h +++ b/cpp/include/gar/graph_info.h @@ -46,7 +46,8 @@ class Property { static bool operator==(const Property& lhs, const Property& rhs) { return (lhs.name == rhs.name) && (lhs.type == rhs.type) && - (lhs.is_primary == rhs.is_primary) && (lhs.is_nullable == rhs.is_nullable); + (lhs.is_primary == rhs.is_primary) && + (lhs.is_nullable == rhs.is_nullable); } /** diff --git a/cpp/src/graph_info.cc b/cpp/src/graph_info.cc index d2b32779e..63d83cf83 100644 --- a/cpp/src/graph_info.cc +++ b/cpp/src/graph_info.cc @@ -293,12 +293,12 @@ bool VertexInfo::IsPrimaryKey(const std::string& property_name) const { return it->second; } -bool VertexInfo::IsNullableKey(const std::string &property_name) const { - auto it = impl_->property_name_to_nullable_.find(property_name); - if (it == impl_->property_name_to_nullable_.end()) { - return false; - } - return it->second; +bool VertexInfo::IsNullableKey(const std::string& property_name) const { + auto it = impl_->property_name_to_nullable_.find(property_name); + if (it == impl_->property_name_to_nullable_.end()) { + return false; + } + return it->second; } bool VertexInfo::HasProperty(const std::string& property_name) const { @@ -392,8 +392,10 @@ Result> VertexInfo::Load( auto property_type = DataType::TypeNameToDataType(p_node["data_type"].As()); bool is_primary = p_node["is_primary"].As(); - bool is_nullable = p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); - property_vec.emplace_back(property_name, property_type, is_primary, is_nullable); + bool is_nullable = + p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); + property_vec.emplace_back(property_name, property_type, is_primary, + is_nullable); } property_groups.push_back( std::make_shared(property_vec, file_type, pg_prefix)); @@ -720,12 +722,12 @@ bool EdgeInfo::IsPrimaryKey(const std::string& property_name) const { return it->second; } -bool EdgeInfo::IsNullableKey(const std::string &property_name) const { - auto it = impl_->property_name_to_nullable_.find(property_name); - if (it == impl_->property_name_to_nullable_.end()) { - return false; - } - return it->second; +bool EdgeInfo::IsNullableKey(const std::string& property_name) const { + auto it = impl_->property_name_to_nullable_.find(property_name); + if (it == impl_->property_name_to_nullable_.end()) { + return false; + } + return it->second; } Result> EdgeInfo::AddAdjacentList( @@ -839,8 +841,10 @@ Result> EdgeInfo::Load(std::shared_ptr yaml) { auto property_type = DataType::TypeNameToDataType(p_node["data_type"].As()); bool is_primary = p_node["is_primary"].As(); - bool is_nullable = p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); - property_vec.emplace_back(property_name, property_type, is_primary, is_nullable); + bool is_nullable = + p_node["is_nullable"].IsNone() || p_node["is_nullable"].As(); + property_vec.emplace_back(property_name, property_type, is_primary, + is_nullable); } property_groups.push_back( std::make_shared(property_vec, file_type, pg_prefix)); From 0d25335885c75c3dc8fe1021dddfe7ec12ff34f7 Mon Sep 17 00:00:00 2001 From: Thespica Date: Fri, 2 Feb 2024 14:33:35 +0800 Subject: [PATCH 3/3] Add doc --- docs/file-format.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/file-format.rst b/docs/file-format.rst index f8d384df1..2b581ae78 100644 --- a/docs/file-format.rst +++ b/docs/file-format.rst @@ -124,7 +124,7 @@ A vertex information file which named "