Apache GraphAr C++ Library
The C++ Library for Apache GraphAr
graph_info.cc
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <unordered_set>
21 #include <utility>
22 
23 #include "graphar/status.h"
24 #include "mini-yaml/yaml/Yaml.hpp"
25 
26 #include "graphar/filesystem.h"
27 #include "graphar/graph_info.h"
28 #include "graphar/result.h"
29 #include "graphar/types.h"
30 #include "graphar/version_parser.h"
31 #include "graphar/yaml.h"
32 
33 namespace graphar {
34 
35 #define CHECK_HAS_ADJ_LIST_TYPE(adj_list_type) \
36  do { \
37  if (!HasAdjacentListType(adj_list_type)) { \
38  return Status::KeyError( \
39  "Adjacency list type: ", AdjListTypeToString(adj_list_type), \
40  " is not found in edge info."); \
41  } \
42  } while (false)
43 
44 namespace {
45 
46 std::string ConcatEdgeTriple(const std::string& src_type,
47  const std::string& edge_type,
48  const std::string& dst_type) {
49  return src_type + REGULAR_SEPARATOR + edge_type + REGULAR_SEPARATOR +
50  dst_type;
51 }
52 
53 template <int NotFoundValue = -1>
54 int LookupKeyIndex(const std::unordered_map<std::string, int>& key_to_index,
55  const std::string& type) {
56  auto it = key_to_index.find(type);
57  if (it == key_to_index.end()) {
58  return NotFoundValue;
59  }
60  return it->second;
61 }
62 
63 template <typename T>
64 std::vector<T> AddVectorElement(const std::vector<T>& values, T new_element) {
65  std::vector<T> out;
66  out.reserve(values.size() + 1);
67  for (size_t i = 0; i < values.size(); ++i) {
68  out.push_back(values[i]);
69  }
70  out.emplace_back(std::move(new_element));
71  return out;
72 }
73 
74 template <typename T>
75 std::vector<T> RemoveVectorElement(const std::vector<T>& values, size_t index) {
76  if (index >= values.size()) {
77  return values;
78  }
79  std::vector<T> out;
80  out.reserve(values.size() - 1);
81  for (size_t i = 0; i < values.size(); ++i) {
82  if (i != index) {
83  out.push_back(values[i]);
84  }
85  }
86  return out;
87 }
88 
89 std::string BuildPath(const std::vector<std::string>& paths) {
90  std::string path;
91  for (const auto& p : paths) {
92  if (p.back() == '/') {
93  path += p;
94  } else {
95  path += p + "/";
96  }
97  }
98  return path;
99 }
100 } // namespace
101 
102 bool operator==(const Property& lhs, const Property& rhs) {
103  return (lhs.name == rhs.name) && (lhs.type == rhs.type) &&
104  (lhs.is_primary == rhs.is_primary) &&
105  (lhs.is_nullable == rhs.is_nullable) &&
106  (lhs.cardinality == rhs.cardinality);
107 }
108 
109 PropertyGroup::PropertyGroup(const std::vector<Property>& properties,
110  FileType file_type, const std::string& prefix)
111  : properties_(properties), file_type_(file_type), prefix_(prefix) {
112  if (prefix_.empty() && !properties_.empty()) {
113  for (const auto& p : properties_) {
114  prefix_ += p.name + REGULAR_SEPARATOR;
115  }
116  prefix_.back() = '/';
117  }
118 }
119 
120 const std::vector<Property>& PropertyGroup::GetProperties() const {
121  return properties_;
122 }
123 
124 bool PropertyGroup::HasProperty(const std::string& property_name) const {
125  for (const auto& p : properties_) {
126  if (p.name == property_name) {
127  return true;
128  }
129  }
130  return false;
131 }
132 
134  if (prefix_.empty() ||
135  (file_type_ != FileType::CSV && file_type_ != FileType::PARQUET &&
136  file_type_ != FileType::ORC)) {
137  return false;
138  }
139  if (properties_.empty()) {
140  return false;
141  }
142  std::unordered_set<std::string> check_property_unique_set;
143  for (const auto& p : properties_) {
144  if (p.name.empty() || p.type == nullptr) {
145  return false;
146  }
147  if (check_property_unique_set.find(p.name) !=
148  check_property_unique_set.end()) {
149  return false;
150  } else {
151  check_property_unique_set.insert(p.name);
152  }
153  // TODO(@acezen): support list type in csv file
154  if (p.type->id() == Type::LIST && file_type_ == FileType::CSV) {
155  // list type is not supported in csv file
156  return false;
157  }
158  // TODO(@yangxk): support cardinality in csv file
159  if (p.cardinality != Cardinality::SINGLE && file_type_ == FileType::CSV) {
160  // list cardinality is not supported in csv file
161  return false;
162  }
163  }
164  return true;
165 }
166 
167 std::shared_ptr<PropertyGroup> CreatePropertyGroup(
168  const std::vector<Property>& properties, FileType file_type,
169  const std::string& prefix) {
170  if (properties.empty()) {
171  // empty property group is not allowed
172  return nullptr;
173  }
174  return std::make_shared<PropertyGroup>(properties, file_type, prefix);
175 }
176 
177 bool operator==(const PropertyGroup& lhs, const PropertyGroup& rhs) {
178  return (lhs.GetPrefix() == rhs.GetPrefix()) &&
179  (lhs.GetFileType() == rhs.GetFileType()) &&
180  (lhs.GetProperties() == rhs.GetProperties());
181 }
182 
183 AdjacentList::AdjacentList(AdjListType type, FileType file_type,
184  const std::string& prefix)
185  : type_(type), file_type_(file_type), prefix_(prefix) {
186  if (prefix_.empty()) {
187  prefix_ = std::string(AdjListTypeToString(type_)) + "/";
188  }
189 }
190 
192  if (type_ != AdjListType::unordered_by_source &&
193  type_ != AdjListType::ordered_by_source &&
194  type_ != AdjListType::unordered_by_dest &&
195  type_ != AdjListType::ordered_by_dest) {
196  return false;
197  }
198  if (prefix_.empty() ||
199  (file_type_ != FileType::CSV && file_type_ != FileType::PARQUET &&
200  file_type_ != FileType::ORC)) {
201  return false;
202  }
203  return true;
204 }
205 
206 std::shared_ptr<AdjacentList> CreateAdjacentList(AdjListType type,
207  FileType file_type,
208  const std::string& prefix) {
209  return std::make_shared<AdjacentList>(type, file_type, prefix);
210 }
211 
213  public:
214  Impl(const std::string& type, IdType chunk_size, const std::string& prefix,
215  const PropertyGroupVector& property_groups,
216  const std::vector<std::string>& labels,
217  std::shared_ptr<const InfoVersion> version)
218  : type_(type),
219  chunk_size_(chunk_size),
220  property_groups_(std::move(property_groups)),
221  labels_(labels),
222  prefix_(prefix),
223  version_(std::move(version)) {
224  if (prefix_.empty()) {
225  prefix_ = type_ + "/"; // default prefix
226  }
227  for (size_t i = 0; i < property_groups_.size(); i++) {
228  const auto& pg = property_groups_[i];
229  if (!pg) {
230  continue;
231  }
232  for (const auto& p : pg->GetProperties()) {
233  property_name_to_index_.emplace(p.name, i);
234  property_name_to_primary_.emplace(p.name, p.is_primary);
235  property_name_to_nullable_.emplace(p.name, p.is_nullable);
236  property_name_to_type_.emplace(p.name, p.type);
237  property_name_to_cardinality_.emplace(p.name, p.cardinality);
238  }
239  }
240  }
241 
242  bool is_validated() const noexcept {
243  if (type_.empty() || chunk_size_ <= 0 || prefix_.empty()) {
244  return false;
245  }
246  std::unordered_set<std::string> check_property_unique_set;
247  for (const auto& pg : property_groups_) {
248  // check if property group is validated
249  if (!pg || !pg->IsValidated()) {
250  return false;
251  }
252  // check if property name is unique in all property groups
253  for (const auto& p : pg->GetProperties()) {
254  if (check_property_unique_set.find(p.name) !=
255  check_property_unique_set.end()) {
256  return false;
257  } else {
258  check_property_unique_set.insert(p.name);
259  }
260  }
261  }
262 
263  return true;
264  }
265 
266  std::string type_;
267  IdType chunk_size_;
268  PropertyGroupVector property_groups_;
269  std::vector<std::string> labels_;
270  std::string prefix_;
271  std::shared_ptr<const InfoVersion> version_;
272  std::unordered_map<std::string, int> property_name_to_index_;
273  std::unordered_map<std::string, bool> property_name_to_primary_;
274  std::unordered_map<std::string, bool> property_name_to_nullable_;
275  std::unordered_map<std::string, std::shared_ptr<DataType>>
276  property_name_to_type_;
277  std::unordered_map<std::string, Cardinality> property_name_to_cardinality_;
278 };
279 
280 VertexInfo::VertexInfo(const std::string& type, IdType chunk_size,
281  const PropertyGroupVector& property_groups,
282  const std::vector<std::string>& labels,
283  const std::string& prefix,
284  std::shared_ptr<const InfoVersion> version)
285  : impl_(new Impl(type, chunk_size, prefix, property_groups, labels,
286  version)) {}
287 
288 VertexInfo::~VertexInfo() = default;
289 
290 const std::string& VertexInfo::GetType() const { return impl_->type_; }
291 
292 IdType VertexInfo::GetChunkSize() const { return impl_->chunk_size_; }
293 
294 const std::string& VertexInfo::GetPrefix() const { return impl_->prefix_; }
295 
296 const std::vector<std::string>& VertexInfo::GetLabels() const {
297  return impl_->labels_;
298 }
299 
300 const std::shared_ptr<const InfoVersion>& VertexInfo::version() const {
301  return impl_->version_;
302 }
303 
304 Result<std::string> VertexInfo::GetFilePath(
305  std::shared_ptr<PropertyGroup> property_group, IdType chunk_index) const {
306  if (property_group == nullptr) {
307  return Status::Invalid("property group is nullptr");
308  }
309  return BuildPath({impl_->prefix_, property_group->GetPrefix()}) + "chunk" +
310  std::to_string(chunk_index);
311 }
312 
313 Result<std::string> VertexInfo::GetPathPrefix(
314  std::shared_ptr<PropertyGroup> property_group) const {
315  if (property_group == nullptr) {
316  return Status::Invalid("property group is nullptr");
317  }
318  return BuildPath({impl_->prefix_, property_group->GetPrefix()});
319 }
320 
321 Result<std::string> VertexInfo::GetVerticesNumFilePath() const {
322  return BuildPath({impl_->prefix_}) + "vertex_count";
323 }
324 
326  return static_cast<int>(impl_->property_groups_.size());
327 }
328 
329 std::shared_ptr<PropertyGroup> VertexInfo::GetPropertyGroup(
330  const std::string& property_name) const {
331  int i = LookupKeyIndex(impl_->property_name_to_index_, property_name);
332  return i == -1 ? nullptr : impl_->property_groups_[i];
333 }
334 
335 std::shared_ptr<PropertyGroup> VertexInfo::GetPropertyGroupByIndex(
336  int index) const {
337  if (index < 0 || index >= static_cast<int>(impl_->property_groups_.size())) {
338  return nullptr;
339  }
340  return impl_->property_groups_[index];
341 }
342 
343 const PropertyGroupVector& VertexInfo::GetPropertyGroups() const {
344  return impl_->property_groups_;
345 }
346 
347 bool VertexInfo::IsPrimaryKey(const std::string& property_name) const {
348  auto it = impl_->property_name_to_primary_.find(property_name);
349  if (it == impl_->property_name_to_primary_.end()) {
350  return false;
351  }
352  return it->second;
353 }
354 
355 bool VertexInfo::IsNullableKey(const std::string& property_name) const {
356  auto it = impl_->property_name_to_nullable_.find(property_name);
357  if (it == impl_->property_name_to_nullable_.end()) {
358  return false;
359  }
360  return it->second;
361 }
362 
363 bool VertexInfo::HasProperty(const std::string& property_name) const {
364  return impl_->property_name_to_index_.find(property_name) !=
365  impl_->property_name_to_index_.end();
366 }
367 
369  const std::shared_ptr<PropertyGroup>& property_group) const {
370  if (property_group == nullptr) {
371  return false;
372  }
373  for (const auto& pg : impl_->property_groups_) {
374  if (*pg == *property_group) {
375  return true;
376  }
377  }
378  return false;
379 }
380 
381 Result<std::shared_ptr<DataType>> VertexInfo::GetPropertyType(
382  const std::string& property_name) const {
383  auto it = impl_->property_name_to_type_.find(property_name);
384  if (it == impl_->property_name_to_type_.end()) {
385  return Status::Invalid("property name not found: ", property_name);
386  }
387  return it->second;
388 }
389 
390 Result<Cardinality> VertexInfo::GetPropertyCardinality(
391  const std::string& property_name) const {
392  auto it = impl_->property_name_to_cardinality_.find(property_name);
393  if (it == impl_->property_name_to_cardinality_.end()) {
394  return Status::Invalid("property name not found: ", property_name);
395  }
396  return it->second;
397 }
398 
399 Result<std::shared_ptr<VertexInfo>> VertexInfo::AddPropertyGroup(
400  std::shared_ptr<PropertyGroup> property_group) const {
401  if (property_group == nullptr) {
402  return Status::Invalid("property group is nullptr");
403  }
404  for (const auto& property : property_group->GetProperties()) {
405  if (HasProperty(property.name)) {
406  return Status::Invalid("property in the property group already exists: ",
407  property.name);
408  }
409  }
410  return std::make_shared<VertexInfo>(
411  impl_->type_, impl_->chunk_size_,
412  AddVectorElement(impl_->property_groups_, property_group), impl_->labels_,
413  impl_->prefix_, impl_->version_);
414 }
415 
416 Result<std::shared_ptr<VertexInfo>> VertexInfo::RemovePropertyGroup(
417  std::shared_ptr<PropertyGroup> property_group) const {
418  if (property_group == nullptr) {
419  return Status::Invalid("property group is nullptr");
420  }
421  int idx = -1;
422  for (size_t i = 0; i < impl_->property_groups_.size(); i++) {
423  if (*(impl_->property_groups_[i]) == *property_group) {
424  idx = i;
425  break;
426  }
427  }
428  if (idx == -1) {
429  return Status::Invalid("property group not found");
430  }
431  return std::make_shared<VertexInfo>(
432  impl_->type_, impl_->chunk_size_,
433  RemoveVectorElement(impl_->property_groups_, static_cast<size_t>(idx)),
434  impl_->labels_, impl_->prefix_, impl_->version_);
435 }
436 
437 bool VertexInfo::IsValidated() const { return impl_->is_validated(); }
438 
439 std::shared_ptr<VertexInfo> CreateVertexInfo(
440  const std::string& type, IdType chunk_size,
441  const PropertyGroupVector& property_groups,
442  const std::vector<std::string>& labels, const std::string& prefix,
443  std::shared_ptr<const InfoVersion> version) {
444  if (type.empty() || chunk_size <= 0) {
445  return nullptr;
446  }
447  return std::make_shared<VertexInfo>(type, chunk_size, property_groups, labels,
448  prefix, version);
449 }
450 
451 Result<std::shared_ptr<VertexInfo>> VertexInfo::Load(
452  std::shared_ptr<Yaml> yaml) {
453  if (yaml == nullptr) {
454  return Status::Invalid("yaml shared pointer is nullptr");
455  }
456  std::string type = yaml->operator[]("type").As<std::string>();
457  IdType chunk_size =
458  static_cast<IdType>(yaml->operator[]("chunk_size").As<int64_t>());
459  std::string prefix;
460  if (!yaml->operator[]("prefix").IsNone()) {
461  prefix = yaml->operator[]("prefix").As<std::string>();
462  }
463  std::vector<std::string> labels;
464  const auto& labels_node = yaml->operator[]("labels");
465  if (labels_node.IsSequence()) {
466  for (auto it = labels_node.Begin(); it != labels_node.End(); it++) {
467  labels.push_back((*it).second.As<std::string>());
468  }
469  }
470  std::shared_ptr<const InfoVersion> version = nullptr;
471  if (!yaml->operator[]("version").IsNone()) {
472  GAR_ASSIGN_OR_RAISE(
473  version,
474  InfoVersion::Parse(yaml->operator[]("version").As<std::string>()));
475  }
476  PropertyGroupVector property_groups;
477  auto property_groups_node = yaml->operator[]("property_groups");
478  if (!property_groups_node.IsNone()) { // property_groups exist
479  for (auto it = property_groups_node.Begin();
480  it != property_groups_node.End(); it++) {
481  std::string pg_prefix;
482  auto& node = (*it).second;
483  if (!node["prefix"].IsNone()) {
484  pg_prefix = node["prefix"].As<std::string>();
485  }
486  auto file_type = StringToFileType(node["file_type"].As<std::string>());
487  std::vector<Property> property_vec;
488  auto& properties = node["properties"];
489  for (auto iit = properties.Begin(); iit != properties.End(); iit++) {
490  auto& p_node = (*iit).second;
491  auto property_name = p_node["name"].As<std::string>();
492  auto property_type =
493  DataType::TypeNameToDataType(p_node["data_type"].As<std::string>());
494  bool is_primary = p_node["is_primary"].As<bool>();
495  bool is_nullable =
496  p_node["is_nullable"].IsNone() || p_node["is_nullable"].As<bool>();
497  Cardinality cardinality = Cardinality::SINGLE;
498  if (!p_node["cardinality"].IsNone()) {
499  cardinality =
500  StringToCardinality(p_node["cardinality"].As<std::string>());
501  }
502  property_vec.emplace_back(property_name, property_type, is_primary,
503  is_nullable, cardinality);
504  }
505  property_groups.push_back(
506  std::make_shared<PropertyGroup>(property_vec, file_type, pg_prefix));
507  }
508  }
509  return std::make_shared<VertexInfo>(type, chunk_size, property_groups, labels,
510  prefix, version);
511 }
512 
513 Result<std::shared_ptr<VertexInfo>> VertexInfo::Load(const std::string& input) {
514  GAR_ASSIGN_OR_RAISE(auto yaml, Yaml::Load(input));
515  return VertexInfo::Load(yaml);
516 }
517 
518 Result<std::string> VertexInfo::Dump() const noexcept {
519  if (!IsValidated()) {
520  return Status::Invalid("The vertex info is not validated");
521  }
522  std::string dump_string;
523  ::Yaml::Node node;
524  try {
525  node["type"] = impl_->type_;
526  node["chunk_size"] = std::to_string(impl_->chunk_size_);
527  node["prefix"] = impl_->prefix_;
528  if (impl_->labels_.size() > 0) {
529  node["labels"];
530  for (const auto& label : impl_->labels_) {
531  node["labels"].PushBack();
532  node["labels"][node["labels"].Size() - 1] = label;
533  }
534  }
535  for (const auto& pg : impl_->property_groups_) {
536  ::Yaml::Node pg_node;
537  if (!pg->GetPrefix().empty()) {
538  pg_node["prefix"] = pg->GetPrefix();
539  }
540  pg_node["file_type"] = FileTypeToString(pg->GetFileType());
541  for (const auto& p : pg->GetProperties()) {
542  ::Yaml::Node p_node;
543  p_node["name"] = p.name;
544  p_node["data_type"] = p.type->ToTypeName();
545  p_node["is_primary"] = p.is_primary ? "true" : "false";
546  p_node["is_nullable"] = p.is_nullable ? "true" : "false";
547  if (p.cardinality != Cardinality::SINGLE) {
548  p_node["cardinality"] = CardinalityToString(p.cardinality);
549  }
550  pg_node["properties"].PushBack();
551  pg_node["properties"][pg_node["properties"].Size() - 1] = p_node;
552  }
553  node["property_groups"].PushBack();
554  node["property_groups"][node["property_groups"].Size() - 1] = pg_node;
555  }
556  if (impl_->version_ != nullptr) {
557  node["version"] = impl_->version_->ToString();
558  }
559  ::Yaml::Serialize(node, dump_string);
560  } catch (const std::exception& e) {
561  return Status::Invalid("Failed to dump vertex info: ", e.what());
562  }
563  return dump_string;
564 }
565 
566 Status VertexInfo::Save(const std::string& path) const {
567  std::string no_url_path;
568  GAR_ASSIGN_OR_RAISE(auto fs, FileSystemFromUriOrPath(path, &no_url_path));
569  GAR_ASSIGN_OR_RAISE(auto yaml_content, this->Dump());
570  return fs->WriteValueToFile(yaml_content, no_url_path);
571 }
572 
574  public:
575  Impl(const std::string& src_type, const std::string& edge_type,
576  const std::string& dst_type, IdType chunk_size, IdType src_chunk_size,
577  IdType dst_chunk_size, bool directed, const std::string& prefix,
578  const AdjacentListVector& adjacent_lists,
579  const PropertyGroupVector& property_groups,
580  std::shared_ptr<const InfoVersion> version)
581  : src_type_(src_type),
582  edge_type_(edge_type),
583  dst_type_(dst_type),
584  chunk_size_(chunk_size),
585  src_chunk_size_(src_chunk_size),
586  dst_chunk_size_(dst_chunk_size),
587  directed_(directed),
588  prefix_(prefix),
589  adjacent_lists_(std::move(adjacent_lists)),
590  property_groups_(std::move(property_groups)),
591  version_(std::move(version)) {
592  if (prefix_.empty()) {
593  prefix_ = src_type_ + REGULAR_SEPARATOR + edge_type_ + REGULAR_SEPARATOR +
594  dst_type_ + "/"; // default prefix
595  }
596  for (size_t i = 0; i < adjacent_lists_.size(); i++) {
597  if (!adjacent_lists_[i]) {
598  continue;
599  }
600 
601  auto adj_list_type = adjacent_lists_[i]->GetType();
602  adjacent_list_type_to_index_[adj_list_type] = i;
603  }
604  for (size_t i = 0; i < property_groups_.size(); i++) {
605  const auto& pg = property_groups_[i];
606  if (!pg) {
607  continue;
608  }
609  for (const auto& p : pg->GetProperties()) {
610  property_name_to_index_.emplace(p.name, i);
611  property_name_to_primary_.emplace(p.name, p.is_primary);
612  property_name_to_nullable_.emplace(p.name, p.is_nullable);
613  property_name_to_type_.emplace(p.name, p.type);
614  }
615  }
616  }
617 
618  bool is_validated() const noexcept {
619  if (src_type_.empty() || edge_type_.empty() || dst_type_.empty() ||
620  chunk_size_ <= 0 || src_chunk_size_ <= 0 || dst_chunk_size_ <= 0 ||
621  prefix_.empty() || adjacent_lists_.empty()) {
622  return false;
623  }
624 
625  for (const auto& al : adjacent_lists_) {
626  if (!al || !al->IsValidated()) {
627  return false;
628  }
629  }
630 
631  std::unordered_set<std::string> check_property_unique_set;
632  for (const auto& pg : property_groups_) {
633  // check if property group is validated
634  if (!pg || !pg->IsValidated()) {
635  return false;
636  }
637  // check if property name is unique in all property groups
638  for (const auto& p : pg->GetProperties()) {
639  if (p.cardinality != Cardinality::SINGLE) {
640  // edge property only supports single cardinality
641  std::cout
642  << "Edge property only supports single cardinality, but got: "
643  << CardinalityToString(p.cardinality) << std::endl;
644  return false;
645  }
646  if (check_property_unique_set.find(p.name) !=
647  check_property_unique_set.end()) {
648  return false;
649  } else {
650  check_property_unique_set.insert(p.name);
651  }
652  }
653  }
654  if (adjacent_lists_.size() != adjacent_list_type_to_index_.size()) {
655  return false;
656  }
657  return true;
658  }
659 
660  std::string src_type_;
661  std::string edge_type_;
662  std::string dst_type_;
663  IdType chunk_size_;
664  IdType src_chunk_size_;
665  IdType dst_chunk_size_;
666  bool directed_;
667  std::string prefix_;
668  AdjacentListVector adjacent_lists_;
669  PropertyGroupVector property_groups_;
670  std::unordered_map<AdjListType, int> adjacent_list_type_to_index_;
671  std::unordered_map<std::string, int> property_name_to_index_;
672  std::unordered_map<std::string, bool> property_name_to_primary_;
673  std::unordered_map<std::string, bool> property_name_to_nullable_;
674  std::unordered_map<std::string, std::shared_ptr<DataType>>
675  property_name_to_type_;
676  std::shared_ptr<const InfoVersion> version_;
677 };
678 
679 EdgeInfo::EdgeInfo(const std::string& src_type, const std::string& edge_type,
680  const std::string& dst_type, IdType chunk_size,
681  IdType src_chunk_size, IdType dst_chunk_size, bool directed,
682  const AdjacentListVector& adjacent_lists,
683  const PropertyGroupVector& property_groups,
684  const std::string& prefix,
685  std::shared_ptr<const InfoVersion> version)
686  : impl_(new Impl(src_type, edge_type, dst_type, chunk_size, src_chunk_size,
687  dst_chunk_size, directed, prefix, adjacent_lists,
688  property_groups, version)) {}
689 
690 EdgeInfo::~EdgeInfo() = default;
691 
692 const std::string& EdgeInfo::GetSrcType() const { return impl_->src_type_; }
693 
694 const std::string& EdgeInfo::GetEdgeType() const { return impl_->edge_type_; }
695 
696 const std::string& EdgeInfo::GetDstType() const { return impl_->dst_type_; }
697 
698 IdType EdgeInfo::GetChunkSize() const { return impl_->chunk_size_; }
699 
700 IdType EdgeInfo::GetSrcChunkSize() const { return impl_->src_chunk_size_; }
701 
702 IdType EdgeInfo::GetDstChunkSize() const { return impl_->dst_chunk_size_; }
703 
704 const std::string& EdgeInfo::GetPrefix() const { return impl_->prefix_; }
705 
706 bool EdgeInfo::IsDirected() const { return impl_->directed_; }
707 
708 const std::shared_ptr<const InfoVersion>& EdgeInfo::version() const {
709  return impl_->version_;
710 }
711 
712 bool EdgeInfo::HasAdjacentListType(AdjListType adj_list_type) const {
713  return impl_->adjacent_list_type_to_index_.find(adj_list_type) !=
714  impl_->adjacent_list_type_to_index_.end();
715 }
716 
717 bool EdgeInfo::HasProperty(const std::string& property_name) const {
718  return impl_->property_name_to_index_.find(property_name) !=
719  impl_->property_name_to_index_.end();
720 }
721 
723  const std::shared_ptr<PropertyGroup>& property_group) const {
724  if (property_group == nullptr) {
725  return false;
726  }
727  for (const auto& pg : impl_->property_groups_) {
728  if (*pg == *property_group) {
729  return true;
730  }
731  }
732  return false;
733 }
734 
735 std::shared_ptr<AdjacentList> EdgeInfo::GetAdjacentList(
736  AdjListType adj_list_type) const {
737  auto it = impl_->adjacent_list_type_to_index_.find(adj_list_type);
738  if (it == impl_->adjacent_list_type_to_index_.end()) {
739  return nullptr;
740  }
741  return impl_->adjacent_lists_[it->second];
742 }
743 
745  return static_cast<int>(impl_->property_groups_.size());
746 }
747 
748 const PropertyGroupVector& EdgeInfo::GetPropertyGroups() const {
749  return impl_->property_groups_;
750 }
751 
752 std::shared_ptr<PropertyGroup> EdgeInfo::GetPropertyGroup(
753  const std::string& property_name) const {
754  int i = LookupKeyIndex(impl_->property_name_to_index_, property_name);
755  return i == -1 ? nullptr : impl_->property_groups_[i];
756 }
757 
758 std::shared_ptr<PropertyGroup> EdgeInfo::GetPropertyGroupByIndex(
759  int index) const {
760  if (index < 0 || index >= static_cast<int>(impl_->property_groups_.size())) {
761  return nullptr;
762  }
763  return impl_->property_groups_[index];
764 }
765 
767  AdjListType adj_list_type) const {
768  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
769  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
770  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
771  "vertex_count";
772 }
773 
774 Result<std::string> EdgeInfo::GetEdgesNumFilePath(
775  IdType vertex_chunk_index, AdjListType adj_list_type) const {
776  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
777  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
778  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
779  "edge_count" + std::to_string(vertex_chunk_index);
780 }
781 
782 Result<std::string> EdgeInfo::GetAdjListFilePath(
783  IdType vertex_chunk_index, IdType edge_chunk_index,
784  AdjListType adj_list_type) const {
785  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
786  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
787  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
788  "adj_list/part" + std::to_string(vertex_chunk_index) + "/chunk" +
789  std::to_string(edge_chunk_index);
790 }
791 
792 Result<std::string> EdgeInfo::GetAdjListPathPrefix(
793  AdjListType adj_list_type) const {
794  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
795  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
796  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
797  "adj_list/";
798 }
799 
801  IdType vertex_chunk_index, AdjListType adj_list_type) const {
802  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
803  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
804  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
805  "offset/chunk" + std::to_string(vertex_chunk_index);
806 }
807 
808 Result<std::string> EdgeInfo::GetOffsetPathPrefix(
809  AdjListType adj_list_type) const {
810  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
811  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
812  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix()}) +
813  "offset/";
814 }
815 
816 Result<std::string> EdgeInfo::GetPropertyFilePath(
817  const std::shared_ptr<PropertyGroup>& property_group,
818  AdjListType adj_list_type, IdType vertex_chunk_index,
819  IdType edge_chunk_index) const {
820  if (property_group == nullptr) {
821  return Status::Invalid("property group is nullptr");
822  }
823  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
824  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
825  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix(),
826  property_group->GetPrefix()}) +
827  "part" + std::to_string(vertex_chunk_index) + "/chunk" +
828  std::to_string(edge_chunk_index);
829 }
830 
832  const std::shared_ptr<PropertyGroup>& property_group,
833  AdjListType adj_list_type) const {
834  if (property_group == nullptr) {
835  return Status::Invalid("property group is nullptr");
836  }
837  CHECK_HAS_ADJ_LIST_TYPE(adj_list_type);
838  int i = impl_->adjacent_list_type_to_index_.at(adj_list_type);
839  return BuildPath({impl_->prefix_, impl_->adjacent_lists_[i]->GetPrefix(),
840  property_group->GetPrefix()});
841 }
842 
843 Result<std::shared_ptr<DataType>> EdgeInfo::GetPropertyType(
844  const std::string& property_name) const {
845  auto it = impl_->property_name_to_type_.find(property_name);
846  if (it == impl_->property_name_to_type_.end()) {
847  return Status::Invalid("property name not found: ", property_name);
848  }
849  return it->second;
850 }
851 
852 bool EdgeInfo::IsPrimaryKey(const std::string& property_name) const {
853  auto it = impl_->property_name_to_primary_.find(property_name);
854  if (it == impl_->property_name_to_primary_.end()) {
855  return false;
856  }
857  return it->second;
858 }
859 
860 bool EdgeInfo::IsNullableKey(const std::string& property_name) const {
861  auto it = impl_->property_name_to_nullable_.find(property_name);
862  if (it == impl_->property_name_to_nullable_.end()) {
863  return false;
864  }
865  return it->second;
866 }
867 
868 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::AddAdjacentList(
869  std::shared_ptr<AdjacentList> adj_list) const {
870  if (adj_list == nullptr) {
871  return Status::Invalid("adj list is nullptr");
872  }
873  if (HasAdjacentListType(adj_list->GetType())) {
874  return Status::Invalid("adj list type already exists: ",
875  AdjListTypeToString(adj_list->GetType()));
876  }
877  return std::make_shared<EdgeInfo>(
878  impl_->src_type_, impl_->edge_type_, impl_->dst_type_, impl_->chunk_size_,
879  impl_->src_chunk_size_, impl_->dst_chunk_size_, impl_->directed_,
880  AddVectorElement(impl_->adjacent_lists_, adj_list),
881  impl_->property_groups_, impl_->prefix_, impl_->version_);
882 }
883 
884 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::RemoveAdjacentList(
885  std::shared_ptr<AdjacentList> adj_list) const {
886  if (adj_list == nullptr) {
887  return Status::Invalid("adj list is nullptr");
888  }
889  int idx = -1;
890  for (size_t i = 0; i < impl_->adjacent_lists_.size(); i++) {
891  if (impl_->adjacent_lists_[i]->GetType() == adj_list->GetType()) {
892  idx = i;
893  break;
894  }
895  }
896  if (idx == -1) {
897  return Status::Invalid("adj list not found");
898  }
899  return std::make_shared<EdgeInfo>(
900  impl_->src_type_, impl_->edge_type_, impl_->dst_type_, impl_->chunk_size_,
901  impl_->src_chunk_size_, impl_->dst_chunk_size_, impl_->directed_,
902  RemoveVectorElement(impl_->adjacent_lists_, static_cast<size_t>(idx)),
903  impl_->property_groups_, impl_->prefix_, impl_->version_);
904 }
905 
906 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::AddPropertyGroup(
907  std::shared_ptr<PropertyGroup> property_group) const {
908  if (property_group == nullptr) {
909  return Status::Invalid("property group is nullptr");
910  }
911  for (const auto& property : property_group->GetProperties()) {
912  if (HasProperty(property.name)) {
913  return Status::Invalid("property in property group already exists: ",
914  property.name);
915  }
916  }
917  return std::make_shared<EdgeInfo>(
918  impl_->src_type_, impl_->edge_type_, impl_->dst_type_, impl_->chunk_size_,
919  impl_->src_chunk_size_, impl_->dst_chunk_size_, impl_->directed_,
920  impl_->adjacent_lists_,
921  AddVectorElement(impl_->property_groups_, property_group), impl_->prefix_,
922  impl_->version_);
923 }
924 
925 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::RemovePropertyGroup(
926  std::shared_ptr<PropertyGroup> property_group) const {
927  if (property_group == nullptr) {
928  return Status::Invalid("property group is nullptr");
929  }
930  int idx = -1;
931  for (size_t i = 0; i < impl_->property_groups_.size(); i++) {
932  if (*(impl_->property_groups_[i]) == *property_group) {
933  idx = i;
934  }
935  }
936  if (idx == -1) {
937  return Status::Invalid("property group not found");
938  }
939  return std::make_shared<EdgeInfo>(
940  impl_->src_type_, impl_->edge_type_, impl_->dst_type_, impl_->chunk_size_,
941  impl_->src_chunk_size_, impl_->dst_chunk_size_, impl_->directed_,
942  impl_->adjacent_lists_,
943  RemoveVectorElement(impl_->property_groups_, static_cast<size_t>(idx)),
944  impl_->prefix_, impl_->version_);
945 }
946 
947 bool EdgeInfo::IsValidated() const { return impl_->is_validated(); }
948 
949 std::shared_ptr<EdgeInfo> CreateEdgeInfo(
950  const std::string& src_type, const std::string& edge_type,
951  const std::string& dst_type, IdType chunk_size, IdType src_chunk_size,
952  IdType dst_chunk_size, bool directed,
953  const AdjacentListVector& adjacent_lists,
954  const PropertyGroupVector& property_groups, const std::string& prefix,
955  std::shared_ptr<const InfoVersion> version) {
956  if (src_type.empty() || edge_type.empty() || dst_type.empty() ||
957  chunk_size <= 0 || src_chunk_size <= 0 || dst_chunk_size <= 0 ||
958  adjacent_lists.empty()) {
959  return nullptr;
960  }
961  return std::make_shared<EdgeInfo>(
962  src_type, edge_type, dst_type, chunk_size, src_chunk_size, dst_chunk_size,
963  directed, adjacent_lists, property_groups, prefix, version);
964 }
965 
966 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::Load(std::shared_ptr<Yaml> yaml) {
967  if (yaml == nullptr) {
968  return Status::Invalid("yaml shared pointer is nullptr.");
969  }
970  std::string src_type = yaml->operator[]("src_type").As<std::string>();
971  std::string edge_type = yaml->operator[]("edge_type").As<std::string>();
972  std::string dst_type = yaml->operator[]("dst_type").As<std::string>();
973  IdType chunk_size =
974  static_cast<IdType>(yaml->operator[]("chunk_size").As<int64_t>());
975  IdType src_chunk_size =
976  static_cast<IdType>(yaml->operator[]("src_chunk_size").As<int64_t>());
977  IdType dst_chunk_size =
978  static_cast<IdType>(yaml->operator[]("dst_chunk_size").As<int64_t>());
979  bool directed = yaml->operator[]("directed").As<bool>();
980  std::string prefix;
981  if (!yaml->operator[]("prefix").IsNone()) {
982  prefix = yaml->operator[]("prefix").As<std::string>();
983  }
984  std::shared_ptr<const InfoVersion> version = nullptr;
985  if (!yaml->operator[]("version").IsNone()) {
986  GAR_ASSIGN_OR_RAISE(
987  version,
988  InfoVersion::Parse(yaml->operator[]("version").As<std::string>()));
989  }
990 
991  AdjacentListVector adjacent_lists;
992  PropertyGroupVector property_groups;
993  auto adj_lists_node = yaml->operator[]("adj_lists");
994  if (adj_lists_node.IsSequence()) {
995  for (auto it = adj_lists_node.Begin(); it != adj_lists_node.End(); it++) {
996  auto& node = (*it).second;
997  auto ordered = node["ordered"].As<bool>();
998  auto aligned = node["aligned_by"].As<std::string>();
999  auto adj_list_type = OrderedAlignedToAdjListType(ordered, aligned);
1000  auto file_type = StringToFileType(node["file_type"].As<std::string>());
1001  std::string adj_list_prefix;
1002  if (!node["prefix"].IsNone()) {
1003  adj_list_prefix = node["prefix"].As<std::string>();
1004  }
1005  adjacent_lists.push_back(std::make_shared<AdjacentList>(
1006  adj_list_type, file_type, adj_list_prefix));
1007  }
1008  }
1009  auto property_groups_node = yaml->operator[]("property_groups");
1010  if (!property_groups_node.IsNone()) { // property_groups exist
1011  for (auto pg_it = property_groups_node.Begin();
1012  pg_it != property_groups_node.End(); pg_it++) {
1013  auto& pg_node = (*pg_it).second;
1014  std::string pg_prefix;
1015  if (!pg_node["prefix"].IsNone()) {
1016  pg_prefix = pg_node["prefix"].As<std::string>();
1017  }
1018  auto file_type = StringToFileType(pg_node["file_type"].As<std::string>());
1019  auto properties = pg_node["properties"];
1020  std::vector<Property> property_vec;
1021  for (auto p_it = properties.Begin(); p_it != properties.End(); p_it++) {
1022  auto& p_node = (*p_it).second;
1023  auto property_name = p_node["name"].As<std::string>();
1024  auto property_type =
1025  DataType::TypeNameToDataType(p_node["data_type"].As<std::string>());
1026  if (!p_node["cardinality"].IsNone() &&
1027  StringToCardinality(p_node["cardinality"].As<std::string>()) !=
1028  Cardinality::SINGLE) {
1029  return Status::YamlError(
1030  "Unsupported set cardinality for edge property.");
1031  }
1032  bool is_primary = p_node["is_primary"].As<bool>();
1033  bool is_nullable =
1034  p_node["is_nullable"].IsNone() || p_node["is_nullable"].As<bool>();
1035  property_vec.emplace_back(property_name, property_type, is_primary,
1036  is_nullable);
1037  }
1038  property_groups.push_back(
1039  std::make_shared<PropertyGroup>(property_vec, file_type, pg_prefix));
1040  }
1041  }
1042  return std::make_shared<EdgeInfo>(
1043  src_type, edge_type, dst_type, chunk_size, src_chunk_size, dst_chunk_size,
1044  directed, adjacent_lists, property_groups, prefix, version);
1045 }
1046 
1047 Result<std::shared_ptr<EdgeInfo>> EdgeInfo::Load(const std::string& input) {
1048  GAR_ASSIGN_OR_RAISE(auto yaml, Yaml::Load(input));
1049  return EdgeInfo::Load(yaml);
1050 }
1051 
1052 Result<std::string> EdgeInfo::Dump() const noexcept {
1053  if (!IsValidated()) {
1054  return Status::Invalid("The edge info is not validated.");
1055  }
1056  std::string dump_string;
1057  ::Yaml::Node node;
1058  try {
1059  node["src_type"] = impl_->src_type_;
1060  node["edge_type"] = impl_->edge_type_;
1061  node["dst_type"] = impl_->dst_type_;
1062  node["chunk_size"] = std::to_string(impl_->chunk_size_);
1063  node["src_chunk_size"] = std::to_string(impl_->src_chunk_size_);
1064  node["dst_chunk_size"] = std::to_string(impl_->dst_chunk_size_);
1065  node["prefix"] = impl_->prefix_;
1066  node["directed"] = impl_->directed_ ? "true" : "false";
1067  for (const auto& adjacent_list : impl_->adjacent_lists_) {
1068  ::Yaml::Node adj_list_node;
1069  auto adj_list_type = adjacent_list->GetType();
1070  auto pair = AdjListTypeToOrderedAligned(adj_list_type);
1071  adj_list_node["ordered"] = pair.first ? "true" : "false";
1072  adj_list_node["aligned_by"] = pair.second;
1073  adj_list_node["prefix"] = adjacent_list->GetPrefix();
1074  adj_list_node["file_type"] =
1075  FileTypeToString(adjacent_list->GetFileType());
1076  node["adj_lists"].PushBack();
1077  node["adj_lists"][node["adj_lists"].Size() - 1] = adj_list_node;
1078  }
1079  for (const auto& pg : impl_->property_groups_) {
1080  ::Yaml::Node pg_node;
1081  if (!pg->GetPrefix().empty()) {
1082  pg_node["prefix"] = pg->GetPrefix();
1083  }
1084  pg_node["file_type"] = FileTypeToString(pg->GetFileType());
1085  for (const auto& p : pg->GetProperties()) {
1086  ::Yaml::Node p_node;
1087  p_node["name"] = p.name;
1088  p_node["data_type"] = p.type->ToTypeName();
1089  p_node["is_primary"] = p.is_primary ? "true" : "false";
1090  p_node["is_nullable"] = p.is_nullable ? "true" : "false";
1091  pg_node["properties"].PushBack();
1092  pg_node["properties"][pg_node["properties"].Size() - 1] = p_node;
1093  }
1094  node["property_groups"].PushBack();
1095  node["property_groups"][node["property_groups"].Size() - 1] = pg_node;
1096  }
1097  if (impl_->version_ != nullptr) {
1098  node["version"] = impl_->version_->ToString();
1099  }
1100  ::Yaml::Serialize(node, dump_string);
1101  } catch (const std::exception& e) {
1102  return Status::Invalid("Failed to dump edge info: ", e.what());
1103  }
1104  return dump_string;
1105 }
1106 
1107 Status EdgeInfo::Save(const std::string& path) const {
1108  std::string no_url_path;
1109  GAR_ASSIGN_OR_RAISE(auto fs, FileSystemFromUriOrPath(path, &no_url_path));
1110  GAR_ASSIGN_OR_RAISE(auto yaml_content, this->Dump());
1111  return fs->WriteValueToFile(yaml_content, no_url_path);
1112 }
1113 
1114 namespace {
1115 
1116 static std::string PathToDirectory(const std::string& path) {
1117  if (path.rfind("s3://", 0) == 0) {
1118  int t = path.find_last_of('?');
1119  std::string prefix = path.substr(0, t);
1120  std::string suffix = path.substr(t);
1121  const size_t last_slash_idx = prefix.rfind('/');
1122  if (std::string::npos != last_slash_idx) {
1123  return prefix.substr(0, last_slash_idx + 1) + suffix;
1124  }
1125  } else {
1126  const size_t last_slash_idx = path.rfind('/');
1127  if (std::string::npos != last_slash_idx) {
1128  return path.substr(0, last_slash_idx + 1); // +1 to include the slash
1129  }
1130  }
1131  return path;
1132 }
1133 
1134 static Result<std::shared_ptr<GraphInfo>> ConstructGraphInfo(
1135  std::shared_ptr<Yaml> graph_meta, const std::string& default_name,
1136  const std::string& default_prefix, const std::shared_ptr<FileSystem> fs,
1137  const std::string& no_url_path) {
1138  std::string name = default_name;
1139  std::string prefix = default_prefix;
1140  if (!graph_meta->operator[]("name").IsNone()) {
1141  name = graph_meta->operator[]("name").As<std::string>();
1142  }
1143  if (!graph_meta->operator[]("prefix").IsNone()) {
1144  prefix = graph_meta->operator[]("prefix").As<std::string>();
1145  }
1146  std::shared_ptr<const InfoVersion> version = nullptr;
1147  if (!graph_meta->operator[]("version").IsNone()) {
1148  GAR_ASSIGN_OR_RAISE(
1149  version, InfoVersion::Parse(
1150  graph_meta->operator[]("version").As<std::string>()));
1151  }
1152  std::unordered_map<std::string, std::string> extra_info;
1153  if (!graph_meta->operator[]("extra_info").IsNone()) {
1154  auto& extra_info_node = graph_meta->operator[]("extra_info");
1155  for (auto it = extra_info_node.Begin(); it != extra_info_node.End(); it++) {
1156  auto node = (*it).second;
1157  auto key = node["key"].As<std::string>();
1158  auto value = node["value"].As<std::string>();
1159  extra_info.emplace(key, value);
1160  }
1161  }
1162 
1163  VertexInfoVector vertex_infos;
1164  EdgeInfoVector edge_infos;
1165  const auto& vertices = graph_meta->operator[]("vertices");
1166  if (vertices.IsSequence()) {
1167  for (auto it = vertices.Begin(); it != vertices.End(); it++) {
1168  std::string vertex_meta_file =
1169  no_url_path + (*it).second.As<std::string>();
1170  GAR_ASSIGN_OR_RAISE(auto input,
1171  fs->ReadFileToValue<std::string>(vertex_meta_file));
1172  GAR_ASSIGN_OR_RAISE(auto vertex_meta, Yaml::Load(input));
1173  GAR_ASSIGN_OR_RAISE(auto vertex_info, VertexInfo::Load(vertex_meta));
1174  vertex_infos.push_back(vertex_info);
1175  }
1176  }
1177  const auto& edges = graph_meta->operator[]("edges");
1178  if (edges.IsSequence()) {
1179  for (auto it = edges.Begin(); it != edges.End(); it++) {
1180  std::string edge_meta_file = no_url_path + (*it).second.As<std::string>();
1181  GAR_ASSIGN_OR_RAISE(auto input,
1182  fs->ReadFileToValue<std::string>(edge_meta_file));
1183  GAR_ASSIGN_OR_RAISE(auto edge_meta, Yaml::Load(input));
1184  GAR_ASSIGN_OR_RAISE(auto edge_info, EdgeInfo::Load(edge_meta));
1185  edge_infos.push_back(edge_info);
1186  }
1187  }
1188 
1189  std::vector<std::string> labels;
1190  if (!graph_meta->operator[]("labels").IsNone()) {
1191  const auto& labels_node = graph_meta->operator[]("labels");
1192  if (labels_node.IsSequence()) {
1193  for (auto it = labels_node.Begin(); it != labels_node.End(); it++) {
1194  labels.push_back((*it).second.As<std::string>());
1195  }
1196  }
1197  }
1198  return std::make_shared<GraphInfo>(name, vertex_infos, edge_infos, labels,
1199  prefix, version, extra_info);
1200 }
1201 
1202 } // namespace
1203 
1205  public:
1206  Impl(const std::string& graph_name, VertexInfoVector vertex_infos,
1207  EdgeInfoVector edge_infos, const std::vector<std::string>& labels,
1208  const std::string& prefix, std::shared_ptr<const InfoVersion> version,
1209  const std::unordered_map<std::string, std::string>& extra_info)
1210  : name_(graph_name),
1211  vertex_infos_(std::move(vertex_infos)),
1212  edge_infos_(std::move(edge_infos)),
1213  labels_(labels),
1214  prefix_(prefix),
1215  version_(std::move(version)),
1216  extra_info_(extra_info) {
1217  for (size_t i = 0; i < vertex_infos_.size(); i++) {
1218  if (vertex_infos_[i] != nullptr) {
1219  vtype_to_index_[vertex_infos_[i]->GetType()] = i;
1220  }
1221  }
1222  for (size_t i = 0; i < edge_infos_.size(); i++) {
1223  if (edge_infos_[i] != nullptr) {
1224  std::string edge_key = ConcatEdgeTriple(edge_infos_[i]->GetSrcType(),
1225  edge_infos_[i]->GetEdgeType(),
1226  edge_infos_[i]->GetDstType());
1227  etype_to_index_[edge_key] = i;
1228  }
1229  }
1230  }
1231 
1232  bool is_validated() const noexcept {
1233  if (name_.empty() || prefix_.empty()) {
1234  return false;
1235  }
1236  for (const auto& v : vertex_infos_) {
1237  if (!v || !v->IsValidated()) {
1238  return false;
1239  }
1240  }
1241  for (const auto& e : edge_infos_) {
1242  if (!e || !e->IsValidated()) {
1243  return false;
1244  }
1245  }
1246  if (vertex_infos_.size() != vtype_to_index_.size() ||
1247  edge_infos_.size() != etype_to_index_.size()) {
1248  return false;
1249  }
1250  return true;
1251  }
1252 
1253  std::string name_;
1254  VertexInfoVector vertex_infos_;
1255  EdgeInfoVector edge_infos_;
1256  std::vector<std::string> labels_;
1257  std::string prefix_;
1258  std::shared_ptr<const InfoVersion> version_;
1259  std::unordered_map<std::string, std::string> extra_info_;
1260  std::unordered_map<std::string, int> vtype_to_index_;
1261  std::unordered_map<std::string, int> etype_to_index_;
1262 };
1263 
1265  const std::string& graph_name, VertexInfoVector vertex_infos,
1266  EdgeInfoVector edge_infos, const std::vector<std::string>& labels,
1267  const std::string& prefix, std::shared_ptr<const InfoVersion> version,
1268  const std::unordered_map<std::string, std::string>& extra_info)
1269  : impl_(new Impl(graph_name, std::move(vertex_infos), std::move(edge_infos),
1270  labels, prefix, version, extra_info)) {}
1271 
1272 GraphInfo::~GraphInfo() = default;
1273 
1274 const std::string& GraphInfo::GetName() const { return impl_->name_; }
1275 
1276 const std::vector<std::string>& GraphInfo::GetLabels() const {
1277  return impl_->labels_;
1278 }
1279 
1280 const std::string& GraphInfo::GetPrefix() const { return impl_->prefix_; }
1281 
1282 const std::shared_ptr<const InfoVersion>& GraphInfo::version() const {
1283  return impl_->version_;
1284 }
1285 
1286 const std::unordered_map<std::string, std::string>& GraphInfo::GetExtraInfo()
1287  const {
1288  return impl_->extra_info_;
1289 }
1290 
1291 std::shared_ptr<VertexInfo> GraphInfo::GetVertexInfo(
1292  const std::string& type) const {
1293  int i = GetVertexInfoIndex(type);
1294  return i == -1 ? nullptr : impl_->vertex_infos_[i];
1295 }
1296 
1297 int GraphInfo::GetVertexInfoIndex(const std::string& type) const {
1298  return LookupKeyIndex(impl_->vtype_to_index_, type);
1299 }
1300 
1301 std::shared_ptr<EdgeInfo> GraphInfo::GetEdgeInfo(
1302  const std::string& src_type, const std::string& edge_type,
1303  const std::string& dst_type) const {
1304  int i = GetEdgeInfoIndex(src_type, edge_type, dst_type);
1305  return i == -1 ? nullptr : impl_->edge_infos_[i];
1306 }
1307 
1308 int GraphInfo::GetEdgeInfoIndex(const std::string& src_type,
1309  const std::string& edge_type,
1310  const std::string& dst_type) const {
1311  std::string edge_key = ConcatEdgeTriple(src_type, edge_type, dst_type);
1312  return LookupKeyIndex(impl_->etype_to_index_, edge_key);
1313 }
1314 
1316  return static_cast<int>(impl_->vertex_infos_.size());
1317 }
1318 
1320  return static_cast<int>(impl_->edge_infos_.size());
1321 }
1322 
1323 const std::shared_ptr<VertexInfo> GraphInfo::GetVertexInfoByIndex(
1324  int index) const {
1325  if (index < 0 || index >= static_cast<int>(impl_->vertex_infos_.size())) {
1326  return nullptr;
1327  }
1328  return impl_->vertex_infos_[index];
1329 }
1330 
1331 const std::shared_ptr<EdgeInfo> GraphInfo::GetEdgeInfoByIndex(int index) const {
1332  if (index < 0 || index >= static_cast<int>(impl_->edge_infos_.size())) {
1333  return nullptr;
1334  }
1335  return impl_->edge_infos_[index];
1336 }
1337 
1338 const VertexInfoVector& GraphInfo::GetVertexInfos() const {
1339  return impl_->vertex_infos_;
1340 }
1341 
1342 const EdgeInfoVector& GraphInfo::GetEdgeInfos() const {
1343  return impl_->edge_infos_;
1344 }
1345 
1346 bool GraphInfo::IsValidated() const { return impl_->is_validated(); }
1347 
1348 Result<std::shared_ptr<GraphInfo>> GraphInfo::AddVertex(
1349  std::shared_ptr<VertexInfo> vertex_info) const {
1350  if (vertex_info == nullptr) {
1351  return Status::Invalid("vertex info is nullptr");
1352  }
1353  if (GetVertexInfoIndex(vertex_info->GetType()) != -1) {
1354  return Status::Invalid("vertex info already exists");
1355  }
1356  return std::make_shared<GraphInfo>(
1357  impl_->name_, AddVectorElement(impl_->vertex_infos_, vertex_info),
1358  impl_->edge_infos_, impl_->labels_, impl_->prefix_, impl_->version_);
1359 }
1360 
1361 Result<std::shared_ptr<GraphInfo>> GraphInfo::RemoveVertex(
1362  std::shared_ptr<VertexInfo> vertex_info) const {
1363  if (vertex_info == nullptr) {
1364  return Status::Invalid("vertex info is nullptr");
1365  }
1366  int idx = GetVertexInfoIndex(vertex_info->GetType());
1367  if (idx == -1) {
1368  return Status::Invalid("vertex info not found");
1369  }
1370  return std::make_shared<GraphInfo>(
1371  impl_->name_,
1372  RemoveVectorElement(impl_->vertex_infos_, static_cast<size_t>(idx)),
1373  impl_->edge_infos_, impl_->labels_, impl_->prefix_, impl_->version_,
1374  impl_->extra_info_);
1375 }
1376 
1377 Result<std::shared_ptr<GraphInfo>> GraphInfo::AddEdge(
1378  std::shared_ptr<EdgeInfo> edge_info) const {
1379  if (edge_info == nullptr) {
1380  return Status::Invalid("edge info is nullptr");
1381  }
1382  if (GetEdgeInfoIndex(edge_info->GetSrcType(), edge_info->GetEdgeType(),
1383  edge_info->GetDstType()) != -1) {
1384  return Status::Invalid("edge info already exists");
1385  }
1386  return std::make_shared<GraphInfo>(
1387  impl_->name_, impl_->vertex_infos_,
1388  AddVectorElement(impl_->edge_infos_, edge_info), impl_->labels_,
1389  impl_->prefix_, impl_->version_);
1390 }
1391 
1392 Result<std::shared_ptr<GraphInfo>> GraphInfo::RemoveEdge(
1393  std::shared_ptr<EdgeInfo> edge_info) const {
1394  if (edge_info == nullptr) {
1395  return Status::Invalid("edge info is nullptr");
1396  }
1397  int idx = GetEdgeInfoIndex(edge_info->GetSrcType(), edge_info->GetEdgeType(),
1398  edge_info->GetDstType());
1399  if (idx == -1) {
1400  return Status::Invalid("edge info not found");
1401  }
1402  return std::make_shared<GraphInfo>(
1403  impl_->name_, impl_->vertex_infos_,
1404  RemoveVectorElement(impl_->edge_infos_, static_cast<size_t>(idx)),
1405  impl_->labels_, impl_->prefix_, impl_->version_, impl_->extra_info_);
1406 }
1407 
1408 std::shared_ptr<GraphInfo> CreateGraphInfo(
1409  const std::string& name, const VertexInfoVector& vertex_infos,
1410  const EdgeInfoVector& edge_infos, const std::vector<std::string>& labels,
1411  const std::string& prefix, std::shared_ptr<const InfoVersion> version,
1412  const std::unordered_map<std::string, std::string>& extra_info) {
1413  if (name.empty()) {
1414  return nullptr;
1415  }
1416  return std::make_shared<GraphInfo>(name, vertex_infos, edge_infos, labels,
1417  prefix, version, extra_info);
1418 }
1419 
1420 Result<std::shared_ptr<GraphInfo>> GraphInfo::Load(const std::string& path) {
1421  std::string no_url_path;
1422  GAR_ASSIGN_OR_RAISE(auto fs, FileSystemFromUriOrPath(path, &no_url_path));
1423  GAR_ASSIGN_OR_RAISE(auto yaml_content,
1424  fs->ReadFileToValue<std::string>(no_url_path));
1425  GAR_ASSIGN_OR_RAISE(auto graph_meta, Yaml::Load(yaml_content));
1426  std::string default_name = "graph";
1427  std::string default_prefix = PathToDirectory(path);
1428  no_url_path = PathToDirectory(no_url_path);
1429  return ConstructGraphInfo(graph_meta, default_name, default_prefix, fs,
1430  no_url_path);
1431 }
1432 
1433 Result<std::shared_ptr<GraphInfo>> GraphInfo::Load(
1434  const std::string& input, const std::string& relative_location) {
1435  GAR_ASSIGN_OR_RAISE(auto graph_meta, Yaml::Load(input));
1436  std::string default_name = "graph";
1437  std::string default_prefix =
1438  relative_location; // default chunk file prefix is relative location
1439  std::string no_url_path;
1440  GAR_ASSIGN_OR_RAISE(auto fs,
1441  FileSystemFromUriOrPath(relative_location, &no_url_path));
1442  return ConstructGraphInfo(graph_meta, default_name, default_prefix, fs,
1443  no_url_path);
1444 }
1445 
1446 Result<std::string> GraphInfo::Dump() const {
1447  if (!IsValidated()) {
1448  return Status::Invalid("The graph info is not validated.");
1449  }
1450  ::Yaml::Node node;
1451  std::string dump_string;
1452  try {
1453  node["name"] = impl_->name_;
1454  node["prefix"] = impl_->prefix_;
1455  node["vertices"];
1456  node["edges"];
1457  for (const auto& vertex : GetVertexInfos()) {
1458  node["vertices"].PushBack();
1459  node["vertices"][node["vertices"].Size() - 1] =
1460  vertex->GetType() + ".vertex.yaml";
1461  }
1462  for (const auto& edge : GetEdgeInfos()) {
1463  node["edges"].PushBack();
1464  node["edges"][node["edges"].Size() - 1] =
1465  ConcatEdgeTriple(edge->GetSrcType(), edge->GetEdgeType(),
1466  edge->GetDstType()) +
1467  ".edge.yaml";
1468  }
1469  if (impl_->labels_.size() > 0) {
1470  node["labels"];
1471  for (const auto& label : impl_->labels_) {
1472  node["labels"].PushBack();
1473  node["labels"][node["labels"].Size() - 1] = label;
1474  }
1475  }
1476  if (impl_->version_ != nullptr) {
1477  node["version"] = impl_->version_->ToString();
1478  }
1479  if (impl_->extra_info_.size() > 0) {
1480  node["extra_info"];
1481  for (const auto& pair : impl_->extra_info_) {
1482  ::Yaml::Node extra_info_node;
1483  extra_info_node["key"] = pair.first;
1484  extra_info_node["value"] = pair.second;
1485  node["extra_info"].PushBack();
1486  node["extra_info"][node["extra_info"].Size() - 1] = extra_info_node;
1487  }
1488  }
1489  ::Yaml::Serialize(node, dump_string);
1490  } catch (const std::exception& e) {
1491  return Status::Invalid("Failed to dump graph info: ", e.what());
1492  }
1493  return dump_string;
1494 }
1495 
1496 Status GraphInfo::Save(const std::string& path) const {
1497  std::string no_url_path;
1498  GAR_ASSIGN_OR_RAISE(auto fs, FileSystemFromUriOrPath(path, &no_url_path));
1499  GAR_ASSIGN_OR_RAISE(auto yaml_content, this->Dump());
1500  return fs->WriteValueToFile(yaml_content, no_url_path);
1501 }
1502 
1503 } // namespace graphar
bool IsValidated() const
Definition: graph_info.cc:191
AdjacentList(AdjListType type, FileType file_type, const std::string &prefix="")
Definition: graph_info.cc:183
const std::string & GetEdgeType() const
Definition: graph_info.cc:694
static Result< std::shared_ptr< EdgeInfo > > Load(std::shared_ptr< Yaml > yaml)
Definition: graph_info.cc:966
Result< std::string > GetAdjListFilePath(IdType vertex_chunk_index, IdType edge_chunk_index, AdjListType adj_list_type) const
Get the file path of adj list topology chunk.
Definition: graph_info.cc:782
Status Save(const std::string &file_name) const
Definition: graph_info.cc:1107
Result< std::shared_ptr< EdgeInfo > > RemovePropertyGroup(std::shared_ptr< PropertyGroup > property_group) const
Removes a property group from the EdgeInfo instance and returns a new EdgeInfo.
Definition: graph_info.cc:925
Result< std::shared_ptr< DataType > > GetPropertyType(const std::string &property_name) const
Definition: graph_info.cc:843
bool IsValidated() const
Definition: graph_info.cc:947
const std::string & GetPrefix() const
Definition: graph_info.cc:704
Result< std::string > GetEdgesNumFilePath(IdType vertex_chunk_index, AdjListType adj_list_type) const
Definition: graph_info.cc:774
Result< std::string > GetPropertyGroupPathPrefix(const std::shared_ptr< PropertyGroup > &property_group, AdjListType adj_list_type) const
Definition: graph_info.cc:831
bool IsPrimaryKey(const std::string &property_name) const
Definition: graph_info.cc:852
Result< std::string > GetAdjListOffsetFilePath(IdType vertex_chunk_index, AdjListType adj_list_type) const
Get the adjacency list offset chunk file path of vertex chunk the offset chunks is aligned with the v...
Definition: graph_info.cc:800
IdType GetChunkSize() const
Definition: graph_info.cc:698
bool HasProperty(const std::string &property_name) const
Returns whether the edge info contains the given property.
Definition: graph_info.cc:717
Result< std::shared_ptr< EdgeInfo > > AddAdjacentList(std::shared_ptr< AdjacentList > adj_list) const
Definition: graph_info.cc:868
Result< std::shared_ptr< EdgeInfo > > RemoveAdjacentList(std::shared_ptr< AdjacentList > adj_list) const
Removes an adjacency list from the EdgeInfo instance and returns a new EdgeInfo.
Definition: graph_info.cc:884
Result< std::string > Dump() const noexcept
Definition: graph_info.cc:1052
bool IsNullableKey(const std::string &property_name) const
Definition: graph_info.cc:860
std::shared_ptr< PropertyGroup > GetPropertyGroupByIndex(int index) const
Get the property group at the specified index.
Definition: graph_info.cc:758
bool HasPropertyGroup(const std::shared_ptr< PropertyGroup > &property_group) const
Returns whether the edge info contains the given property group.
Definition: graph_info.cc:722
const std::shared_ptr< const InfoVersion > & version() const
Definition: graph_info.cc:708
Result< std::shared_ptr< EdgeInfo > > AddPropertyGroup(std::shared_ptr< PropertyGroup > property_group) const
Definition: graph_info.cc:906
const std::string & GetSrcType() const
Definition: graph_info.cc:692
bool HasAdjacentListType(AdjListType adj_list_type) const
Definition: graph_info.cc:712
Result< std::string > GetOffsetPathPrefix(AdjListType adj_list_type) const
Definition: graph_info.cc:808
bool IsDirected() const
Definition: graph_info.cc:706
Result< std::string > GetAdjListPathPrefix(AdjListType adj_list_type) const
Get the path prefix of the adjacency list topology chunk for the given adjacency list type.
Definition: graph_info.cc:792
EdgeInfo(const std::string &src_type, const std::string &edge_type, const std::string &dst_type, IdType chunk_size, IdType src_chunk_size, IdType dst_chunk_size, bool directed, const AdjacentListVector &adjacent_lists, const PropertyGroupVector &property_groups, const std::string &prefix="", std::shared_ptr< const InfoVersion > version=nullptr)
Construct an EdgeInfo object with the given information and property groups.
Definition: graph_info.cc:679
IdType GetDstChunkSize() const
Definition: graph_info.cc:702
Result< std::string > GetPropertyFilePath(const std::shared_ptr< PropertyGroup > &property_group, AdjListType adj_list_type, IdType vertex_chunk_index, IdType edge_chunk_index) const
Get the chunk file path of adj list property group the property group chunks is aligned with the adj ...
Definition: graph_info.cc:816
const std::string & GetDstType() const
Definition: graph_info.cc:696
IdType GetSrcChunkSize() const
Definition: graph_info.cc:700
const PropertyGroupVector & GetPropertyGroups() const
Get the property groups.
Definition: graph_info.cc:748
Result< std::string > GetVerticesNumFilePath(AdjListType adj_list_type) const
Get the file path for the number of vertices.
Definition: graph_info.cc:766
std::shared_ptr< PropertyGroup > GetPropertyGroup(const std::string &property) const
Get the property group containing the given property.
Definition: graph_info.cc:752
int PropertyGroupNum() const
Get the number of property groups.
Definition: graph_info.cc:744
int GetVertexInfoIndex(const std::string &type) const
Get the vertex info index with the given type.
Definition: graph_info.cc:1297
const EdgeInfoVector & GetEdgeInfos() const
Get the edge infos of graph info.
Definition: graph_info.cc:1342
GraphInfo(const std::string &graph_name, VertexInfoVector vertex_infos, EdgeInfoVector edge_infos, const std::vector< std::string > &labels={}, const std::string &prefix="./", std::shared_ptr< const InfoVersion > version=nullptr, const std::unordered_map< std::string, std::string > &extra_info={})
Constructs a GraphInfo instance.
Definition: graph_info.cc:1264
Status Save(const std::string &path) const
Definition: graph_info.cc:1496
const std::shared_ptr< VertexInfo > GetVertexInfoByIndex(int index) const
Get the vertex info at the specified index.
Definition: graph_info.cc:1323
Result< std::shared_ptr< GraphInfo > > AddVertex(std::shared_ptr< VertexInfo > vertex_info) const
Adds a vertex info to the GraphInfo instance and returns a new GraphInfo.
Definition: graph_info.cc:1348
const std::string & GetPrefix() const
Get the absolute path prefix of the chunk files.
Definition: graph_info.cc:1280
static Result< std::shared_ptr< GraphInfo > > Load(const std::string &path)
Loads the input file as a GraphInfo instance.
Definition: graph_info.cc:1420
bool IsValidated() const
Definition: graph_info.cc:1346
Result< std::string > Dump() const
Definition: graph_info.cc:1446
std::shared_ptr< EdgeInfo > GetEdgeInfo(const std::string &src_type, const std::string &edge_type, const std::string &dst_type) const
Get the edge info with the given source vertex type, edge type, and destination vertex type.
Definition: graph_info.cc:1301
int EdgeInfoNum() const
Get the number of edge infos.
Definition: graph_info.cc:1319
std::shared_ptr< VertexInfo > GetVertexInfo(const std::string &type) const
Get the vertex info with the given type.
Definition: graph_info.cc:1291
const std::vector< std::string > & GetLabels() const
Get the vertex labels of the graph.
Definition: graph_info.cc:1276
Result< std::shared_ptr< GraphInfo > > AddEdge(std::shared_ptr< EdgeInfo > edge_info) const
Adds an edge info to the GraphInfo instance and returns a new GraphInfo.
Definition: graph_info.cc:1377
const VertexInfoVector & GetVertexInfos() const
Get the vertex infos of graph info.
Definition: graph_info.cc:1338
const std::unordered_map< std::string, std::string > & GetExtraInfo() const
Get the extra metadata of the graph info object.
Definition: graph_info.cc:1286
int GetEdgeInfoIndex(const std::string &src_type, const std::string &edge_type, const std::string &dst_type) const
Get the edge info index with the given source vertex type, edge type, and destination type.
Definition: graph_info.cc:1308
int VertexInfoNum() const
Get the number of vertex infos.
Definition: graph_info.cc:1315
const std::string & GetName() const
Get the name of the graph.
Definition: graph_info.cc:1274
Result< std::shared_ptr< GraphInfo > > RemoveEdge(std::shared_ptr< EdgeInfo > edge_info) const
Removes an edge info from the GraphInfo instance and returns a new GraphInfo.
Definition: graph_info.cc:1392
Result< std::shared_ptr< GraphInfo > > RemoveVertex(std::shared_ptr< VertexInfo > vertex_info) const
Removes a vertex info from the GraphInfo instance and returns a new GraphInfo.
Definition: graph_info.cc:1361
const std::shared_ptr< const InfoVersion > & version() const
Get the version info of the graph info object.
Definition: graph_info.cc:1282
const std::shared_ptr< EdgeInfo > GetEdgeInfoByIndex(int index) const
Get the edge info at the specified index.
Definition: graph_info.cc:1331
static Result< std::shared_ptr< const InfoVersion > > Parse(const std::string &str) noexcept
bool IsValidated() const
Definition: graph_info.cc:133
PropertyGroup(const std::vector< Property > &properties, FileType file_type, const std::string &prefix="")
Definition: graph_info.cc:109
const std::vector< Property > & GetProperties() const
Definition: graph_info.cc:120
Status outcome object (success or error)
Definition: status.h:123
static Status YamlError(Args &&... args)
Definition: status.h:204
static Status Invalid(Args &&... args)
Definition: status.h:188
const std::string & GetType() const
Definition: graph_info.cc:290
std::shared_ptr< PropertyGroup > GetPropertyGroup(const std::string &property_name) const
Definition: graph_info.cc:329
Result< std::string > GetPathPrefix(std::shared_ptr< PropertyGroup > property_group) const
Definition: graph_info.cc:313
const std::vector< std::string > & GetLabels() const
Definition: graph_info.cc:296
IdType GetChunkSize() const
Definition: graph_info.cc:292
const std::shared_ptr< const InfoVersion > & version() const
Definition: graph_info.cc:300
Result< std::shared_ptr< VertexInfo > > AddPropertyGroup(std::shared_ptr< PropertyGroup > property_group) const
Definition: graph_info.cc:399
bool HasProperty(const std::string &property_name) const
Definition: graph_info.cc:363
bool HasPropertyGroup(const std::shared_ptr< PropertyGroup > &property_group) const
Definition: graph_info.cc:368
Result< std::string > GetFilePath(std::shared_ptr< PropertyGroup > property_group, IdType chunk_index) const
Definition: graph_info.cc:304
bool IsPrimaryKey(const std::string &property_name) const
Definition: graph_info.cc:347
bool IsValidated() const
Definition: graph_info.cc:437
int PropertyGroupNum() const
Definition: graph_info.cc:325
Result< std::shared_ptr< VertexInfo > > RemovePropertyGroup(std::shared_ptr< PropertyGroup > property_group) const
Removes a property group from the VertexInfo instance and returns a new VertexInfo.
Definition: graph_info.cc:416
const std::string & GetPrefix() const
Definition: graph_info.cc:294
Result< std::string > GetVerticesNumFilePath() const
Definition: graph_info.cc:321
Result< std::shared_ptr< DataType > > GetPropertyType(const std::string &property_name) const
Definition: graph_info.cc:381
VertexInfo(const std::string &type, IdType chunk_size, const PropertyGroupVector &property_groups, const std::vector< std::string > &labels={}, const std::string &prefix="", std::shared_ptr< const InfoVersion > version=nullptr)
Definition: graph_info.cc:280
bool IsNullableKey(const std::string &property_name) const
Definition: graph_info.cc:355
Result< std::string > Dump() const noexcept
Definition: graph_info.cc:518
static Result< std::shared_ptr< VertexInfo > > Load(std::shared_ptr< Yaml > yaml)
Definition: graph_info.cc:451
std::shared_ptr< PropertyGroup > GetPropertyGroupByIndex(int index) const
Definition: graph_info.cc:335
Status Save(const std::string &file_name) const
Definition: graph_info.cc:566
const PropertyGroupVector & GetPropertyGroups() const
Definition: graph_info.cc:343
static Result< std::shared_ptr< Yaml > > Load(const std::string &input)
Definition: yaml.cc:34