diff --git a/flex/engines/graph_db/runtime/adhoc/var.cc b/flex/engines/graph_db/runtime/adhoc/var.cc index 96da98e8abaf..3f581aa80d4f 100644 --- a/flex/engines/graph_db/runtime/adhoc/var.cc +++ b/flex/engines/graph_db/runtime/adhoc/var.cc @@ -40,7 +40,8 @@ Var::Var(const ReadTransaction& txn, const Context& ctx, tag = pb.tag().id(); CHECK(ctx.get(tag) != nullptr); type_ = ctx.get(tag)->elem_type(); - } else if (pb.has_property() && pb.property().has_label()) { + } else if (pb.has_property() && + (pb.property().has_label() || pb.property().has_id())) { type_ = RTAnyType::kI64Value; } else { LOG(FATAL) << "not support"; @@ -95,6 +96,8 @@ Var::Var(const ReadTransaction& txn, const Context& ctx, create_edge_property_path_accessor(txn, name, ctx, tag, type_); } else if (pt.has_label()) { getter_ = create_edge_label_path_accessor(ctx, tag); + } else if (pt.has_id()) { + getter_ = create_edge_global_id_path_accessor(ctx, tag); } else { LOG(FATAL) << "not support..."; } @@ -154,6 +157,10 @@ Var::Var(const ReadTransaction& txn, const Context& ctx, if (pt.has_key()) { auto name = pt.key().name(); getter_ = create_edge_property_edge_accessor(txn, name, type_); + } else if (pt.has_label()) { + getter_ = create_edge_label_edge_accessor(); + } else if (pt.has_id()) { + getter_ = create_edge_global_id_edge_accessor(); } else { LOG(FATAL) << "not support"; } diff --git a/flex/engines/graph_db/runtime/common/accessors.cc b/flex/engines/graph_db/runtime/common/accessors.cc index 55712fc1bb72..fcec9738a4bb 100644 --- a/flex/engines/graph_db/runtime/common/accessors.cc +++ b/flex/engines/graph_db/runtime/common/accessors.cc @@ -175,6 +175,19 @@ std::shared_ptr create_edge_label_path_accessor(const Context& ctx, return std::make_shared(ctx, tag); } +std::shared_ptr create_edge_label_edge_accessor() { + return std::make_shared(); +} + +std::shared_ptr create_edge_global_id_path_accessor( + const Context& ctx, int tag) { + return std::make_shared(ctx, tag); +} + +std::shared_ptr create_edge_global_id_edge_accessor() { + return std::make_shared(); +} + std::shared_ptr create_edge_property_edge_accessor( const ReadTransaction& txn, const std::string& prop_name, RTAnyType type) { bool multip_properties = txn.schema().has_multi_props_edge(); diff --git a/flex/engines/graph_db/runtime/common/accessors.h b/flex/engines/graph_db/runtime/common/accessors.h index dd3f87cc7c99..33a468a7155d 100644 --- a/flex/engines/graph_db/runtime/common/accessors.h +++ b/flex/engines/graph_db/runtime/common/accessors.h @@ -548,6 +548,27 @@ class EdgeLabelPathAccessor : public IAccessor { const IEdgeColumn& col_; }; +class EdgeLabelEdgeAccessor : public IAccessor { + public: + using elem_t = int32_t; + EdgeLabelEdgeAccessor() {} + + elem_t typed_eval_edge(const LabelTriplet& label, vid_t src, vid_t dst, + const Any& data, size_t idx) const { + return static_cast(label.edge_label); + } + + RTAny eval_path(size_t idx) const override { + LOG(FATAL) << "not supposed to reach here..."; + return RTAny(); + } + + RTAny eval_edge(const LabelTriplet& label, vid_t src, vid_t dst, + const Any& data, size_t idx) const override { + return RTAny::from_int32(typed_eval_edge(label, src, dst, data, idx)); + } +}; + template class EdgePropertyEdgeAccessor : public IAccessor { public: @@ -573,6 +594,96 @@ class EdgePropertyEdgeAccessor : public IAccessor { } }; +// Access the global edge id of an edge in a path +// Currently we have no unique id for a edge. +// We construct the id from the edge's src, dst and label. +class EdgeGlobalIdPathAccessor : public IAccessor { + public: + using elem_t = int64_t; // edge global id + EdgeGlobalIdPathAccessor(const Context& ctx, int tag) + : edge_col_(*std::dynamic_pointer_cast(ctx.get(tag))) {} + + static uint32_t generate_edge_label_id(label_t src_label_id, + label_t dst_label_id, + label_t edge_label_id) { + uint32_t unique_edge_label_id = src_label_id; + static constexpr int num_bits = sizeof(label_t) * 8; + unique_edge_label_id = unique_edge_label_id << num_bits; + unique_edge_label_id = unique_edge_label_id | dst_label_id; + unique_edge_label_id = unique_edge_label_id << num_bits; + unique_edge_label_id = unique_edge_label_id | edge_label_id; + return unique_edge_label_id; + } + + static int64_t encode_unique_edge_id(uint32_t label_id, vid_t src, + vid_t dst) { + // We assume label_id is only used by 24 bits. + int64_t unique_edge_id = label_id; + unique_edge_id = unique_edge_id << 40; + // bitmask for top 40 bits set to 1 + int64_t bitmask = 0xFFFFFFFFFF000000; + // 24 bit | 20 bit | 20 bit + if (bitmask & (int64_t) src || bitmask & (int64_t) dst) { + LOG(ERROR) << "src or dst is too large to be encoded in 20 bits: " << src + << " " << dst; + } + unique_edge_id = unique_edge_id | (src << 20); + unique_edge_id = unique_edge_id | dst; + return unique_edge_id; + } + + elem_t typed_eval_path(size_t idx) const { + const auto& e = edge_col_.get_edge(idx); + auto label_id = generate_edge_label_id(std::get<0>(e).src_label, + std::get<0>(e).dst_label, + std::get<0>(e).edge_label); + return encode_unique_edge_id(label_id, std::get<1>(e), std::get<2>(e)); + } + + RTAny eval_path(size_t idx) const override { + return RTAny::from_int64(typed_eval_path(idx)); + } + + bool is_optional() const override { return edge_col_.is_optional(); } + + RTAny eval_path(size_t idx, int) const override { + if (!edge_col_.has_value(idx)) { + return RTAny(RTAnyType::kNull); + } + return RTAny::from_int64(typed_eval_path(idx)); + } + + std::shared_ptr builder() const override { + return edge_col_.builder(); + } + + private: + const IEdgeColumn& edge_col_; +}; + +class EdgeGlobalIdEdgeAccessor : public IAccessor { + public: + using elem_t = int64_t; // edge global id + EdgeGlobalIdEdgeAccessor() {} + + elem_t typed_eval_edge(const LabelTriplet& label, vid_t src, vid_t dst, + const Any& data, size_t idx) const { + auto label_id = EdgeGlobalIdPathAccessor::generate_edge_label_id( + label.src_label, label.dst_label, label.edge_label); + return EdgeGlobalIdPathAccessor::encode_unique_edge_id(label_id, src, dst); + } + + RTAny eval_path(size_t idx) const override { + LOG(FATAL) << "not supposed to reach here..."; + return RTAny(); + } + + RTAny eval_edge(const LabelTriplet& label, vid_t src, vid_t dst, + const Any& data, size_t idx) const override { + return RTAny::from_int64(typed_eval_edge(label, src, dst, data, idx)); + } +}; + template class MultiPropsEdgePropertyEdgeAccessor : public IAccessor { public: @@ -764,6 +875,13 @@ std::shared_ptr create_edge_property_path_accessor( std::shared_ptr create_edge_label_path_accessor(const Context& ctx, int tag); +std::shared_ptr create_edge_label_edge_accessor(); + +std::shared_ptr create_edge_global_id_path_accessor( + const Context& ctx, int tag); + +std::shared_ptr create_edge_global_id_edge_accessor(); + std::shared_ptr create_edge_property_edge_accessor( const ReadTransaction& txn, const std::string& prop_name, RTAnyType type); diff --git a/flex/engines/graph_db/runtime/common/leaf_utils.h b/flex/engines/graph_db/runtime/common/leaf_utils.h index d7bbe69cba15..e5be15bdd415 100644 --- a/flex/engines/graph_db/runtime/common/leaf_utils.h +++ b/flex/engines/graph_db/runtime/common/leaf_utils.h @@ -21,16 +21,22 @@ namespace bl = boost::leaf; -#define RETURN_UNSUPPORTED_ERROR(msg) \ - return ::boost::leaf::new_error( \ - ::gs::Status(::gs::StatusCode::UNSUPPORTED_OPERATION, msg)) +// Concatenate the current function name and line number to form the error +// message +#define PREPEND_LINE_INFO(msg) \ + std::string(__FILE__) + ":" + std::to_string(__LINE__) + \ + " func: " + std::string(__FUNCTION__) + ", " + msg + +#define RETURN_UNSUPPORTED_ERROR(msg) \ + return ::boost::leaf::new_error(::gs::Status( \ + ::gs::StatusCode::UNSUPPORTED_OPERATION, PREPEND_LINE_INFO(msg))) #define RETURN_BAD_REQUEST_ERROR(msg) \ return ::boost::leaf::new_error( \ - ::gs::Status(::gs::StatusCode::BAD_REQUEST, msg)) + ::gs::Status(::gs::StatusCode::BAD_REQUEST, PREPEND_LINE_INFO(msg))) #define RETURN_NOT_IMPLEMENTED_ERROR(msg) \ return ::boost::leaf::new_error( \ - ::gs::Status(::gs::StatusCode::UNIMPLEMENTED, msg)) + ::gs::Status(::gs::StatusCode::UNIMPLEMENTED, PREPEND_LINE_INFO(msg))) #endif // RUNTIME_COMMON_LEAF_UTILS_H_ diff --git a/flex/engines/graph_db/runtime/common/operators/scan.h b/flex/engines/graph_db/runtime/common/operators/scan.h index 55ed52f225a7..0b73a4e70e0b 100644 --- a/flex/engines/graph_db/runtime/common/operators/scan.h +++ b/flex/engines/graph_db/runtime/common/operators/scan.h @@ -18,8 +18,7 @@ #include "flex/engines/graph_db/runtime/common/columns/vertex_columns.h" #include "flex/engines/graph_db/runtime/common/context.h" - -#include "boost/leaf.hpp" +#include "flex/engines/graph_db/runtime/common/leaf_utils.h" namespace bl = boost::leaf; namespace gs { @@ -58,6 +57,9 @@ class Scan { } } ctx.set(params.alias, builder.finish()); + } else { + LOG(ERROR) << "No vertex labels in scan_vertex"; + RETURN_BAD_REQUEST_ERROR("No valid vertex labels in scan_vertex"); } return ctx; }