Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat][Format][C++] Support nullable key for property in meta-data #355

Merged
merged 3 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpp/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/build/
/examples/*/build/
/cmake-build-debug

apidoc/html
apidoc/xml
30 changes: 25 additions & 5 deletions cpp/include/gar/graph_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,21 @@ class Property {
std::string name; // property name
std::shared_ptr<DataType> 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<DataType>& 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);
}

/**
Expand Down Expand Up @@ -271,6 +276,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.
*
Expand Down Expand Up @@ -596,11 +609,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.
*
Expand Down
32 changes: 30 additions & 2 deletions cpp/src/graph_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -220,6 +221,7 @@ class VertexInfo::Impl {
std::shared_ptr<const InfoVersion> version_;
std::unordered_map<std::string, int> property_name_to_index_;
std::unordered_map<std::string, bool> property_name_to_primary_;
std::unordered_map<std::string, bool> property_name_to_nullable_;
std::unordered_map<std::string, std::shared_ptr<DataType>>
property_name_to_type_;
};
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -382,7 +392,10 @@ Result<std::shared_ptr<VertexInfo>> VertexInfo::Load(
auto property_type =
DataType::TypeNameToDataType(p_node["data_type"].As<std::string>());
bool is_primary = p_node["is_primary"].As<bool>();
property_vec.emplace_back(property_name, property_type, is_primary);
bool is_nullable =
p_node["is_nullable"].IsNone() || p_node["is_nullable"].As<bool>();
property_vec.emplace_back(property_name, property_type, is_primary,
is_nullable);
}
property_groups.push_back(
std::make_shared<PropertyGroup>(property_vec, file_type, pg_prefix));
Expand Down Expand Up @@ -416,6 +429,7 @@ Result<std::string> 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;
}
Expand Down Expand Up @@ -469,6 +483,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);
}
}
Expand Down Expand Up @@ -522,6 +537,7 @@ class EdgeInfo::Impl {
std::unordered_map<AdjListType, int> adjacent_list_type_to_index_;
std::unordered_map<std::string, int> property_name_to_index_;
std::unordered_map<std::string, bool> property_name_to_primary_;
std::unordered_map<std::string, bool> property_name_to_nullable_;
std::unordered_map<std::string, std::shared_ptr<DataType>>
property_name_to_type_;
std::shared_ptr<const InfoVersion> version_;
Expand Down Expand Up @@ -706,6 +722,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<std::shared_ptr<EdgeInfo>> EdgeInfo::AddAdjacentList(
std::shared_ptr<AdjacentList> adj_list) const {
if (adj_list == nullptr) {
Expand Down Expand Up @@ -817,7 +841,10 @@ Result<std::shared_ptr<EdgeInfo>> EdgeInfo::Load(std::shared_ptr<Yaml> yaml) {
auto property_type =
DataType::TypeNameToDataType(p_node["data_type"].As<std::string>());
bool is_primary = p_node["is_primary"].As<bool>();
property_vec.emplace_back(property_name, property_type, is_primary);
bool is_nullable =
p_node["is_nullable"].IsNone() || p_node["is_nullable"].As<bool>();
property_vec.emplace_back(property_name, property_type, is_primary,
is_nullable);
}
property_groups.push_back(
std::make_shared<PropertyGroup>(property_vec, file_type, pg_prefix));
Expand Down Expand Up @@ -869,6 +896,7 @@ Result<std::string> 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;
}
Expand Down
18 changes: 18 additions & 0 deletions cpp/test/test_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand All @@ -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") {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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());
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
)";
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/file-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ A vertex information file which named "<label>.vertex.yml" defines a single grou
- the vertex label;
- the vertex chunk size;
- the relative path for vertex data files;
- the property groups attached: each property group has its own file type and the prefix for the path of its data files, it also lists all properties in this group, with every property containing its own name, data type and flagging of whether it is the primary key or not;
- the property groups attached: each property group has its own file type and the prefix for the path of its data files, it also lists all properties in this group, with every property containing its own name, data type, flagging of whether it is the primary key or not and flagging of whether it is nullable or not for non-primary key properties;
- the version of GraphAr.

An edge information file which named "<source label>_<edge label>_<destination label>.edge.yml" defines a single group of edges with specific label for source vertex, destination vertex and the edge. It describes the meta information for these edges, includes:
Expand Down
Loading