Skip to content

Commit

Permalink
feat(interactive): Support labels and type Functions in Cypher Qu…
Browse files Browse the repository at this point in the history
…eries (alibaba#3255)

<!--
Thanks for your contribution! please review
https://github.com/alibaba/GraphScope/blob/main/CONTRIBUTING.md before
opening an issue.
-->

## What do these changes do?
as titled.

<!-- Please give a short brief about these changes. -->

## Related issue number

<!-- Are there any issues opened that will be resolved by merging this
change? -->

Fixes

---------

Co-authored-by: zhanglei1949 <[email protected]>
Co-authored-by: xiaolei.zl <[email protected]>
Co-authored-by: Longbin Lai <[email protected]>
  • Loading branch information
4 people authored Sep 26, 2023
1 parent 3374342 commit 6e40478
Show file tree
Hide file tree
Showing 34 changed files with 781 additions and 336 deletions.
2 changes: 2 additions & 0 deletions docs/interactive_engine/neo4j/supported_cypher.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ Note that some Aggregator operators, such as `max()`, we listed here are impleme
| Branch | Use with `Project` and `Return` | CASE WHEN | CASE WHEN | <input type="checkbox" disabled />| planned |
| Scalar | Returns the length of a path | length() | length() | <input type="checkbox" disabled checked /> | |
| List | Fold expressions into a single list | [] | [] | <input type="checkbox" disabled checked /> | |
| Labels | Get label name of a vertex type | labels() | labels() | <input type="checkbox" disabled checked /> | |
| Type | Get label name of an edge type | type() | type() | <input type="checkbox" disabled checked /> | |



Expand Down
3 changes: 3 additions & 0 deletions flex/codegen/src/graph_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum class DataType {
kTime = 11,
kDate = 12,
kDateTime = 13,
kLabelId = 14
};

// a parameter const, the real data will be feed at runtime.
Expand Down Expand Up @@ -193,6 +194,8 @@ static std::string data_type_2_string(const codegen::DataType& data_type) {
return EDGE_ID_T;
case codegen::DataType::kDate:
return "Date";
case codegen::DataType::kLabelId:
return "LabelKey";
default:
// LOG(FATAL) << "unknown data type" << static_cast<int>(data_type);
throw std::runtime_error(
Expand Down
4 changes: 4 additions & 0 deletions flex/codegen/src/hqps/hqps_project_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ std::string project_variable_mapping_to_string(BuildingContext& ctx,
} else if (prop.item_case() == common::Property::kLen) {
prop_names.push_back("length");
data_types.push_back(codegen::DataType::kLength);
} else if (prop.item_case() == common::Property::kLabel) {
// return the label id.
prop_names.push_back("label");
data_types.push_back(codegen::DataType::kLabelId);
} else {
LOG(FATAL) << "Unknown property type" << prop.DebugString();
}
Expand Down
49 changes: 41 additions & 8 deletions flex/engines/hqps_db/core/operator/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,31 @@ class ProjectOp {

///////////////////Project implementation for all data structures.

/// Special case for project for labelKey
template <
typename T, typename NODE_T,
typename std::enable_if<std::is_same_v<T, LabelKey>>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph, NODE_T& node, const std::string& prop_name,
const std::vector<size_t>& repeat_array) {
auto size = node.Size();
auto label_vec = node.GetLabelVec();
std::vector<T> res_prop_vec;
CHECK(label_vec.size() == repeat_array.size())
<< "label size: " << label_vec.size()
<< " repeat size: " << repeat_array.size();
for (auto i = 0; i < repeat_array.size(); ++i) {
for (auto j = 0; j < repeat_array[i]; ++j) {
res_prop_vec.emplace_back(label_vec[i]);
}
}
return Collection<T>(std::move(res_prop_vec));
}

// single label vertex set.
template <typename T, typename LabelT, typename VID_T, typename... SET_T>
template <
typename T, typename LabelT, typename VID_T, typename... SET_T,
typename std::enable_if<(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph,
RowVertexSetImpl<LabelT, VID_T, SET_T...>& node,
Expand All @@ -315,8 +338,10 @@ class ProjectOp {
}

// single keyed label vertex set.
template <typename T, typename LabelT, typename KEY_T, typename VID_T,
typename... SET_T>
template <
typename T, typename LabelT, typename KEY_T, typename VID_T,
typename... SET_T,
typename std::enable_if<(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph,
KeyedRowVertexSetImpl<LabelT, KEY_T, VID_T, SET_T...>& node,
Expand All @@ -340,7 +365,9 @@ class ProjectOp {
}

// project for two label vertex set.
template <typename T, typename VID_T, typename LabelT, typename... SET_T>
template <
typename T, typename VID_T, typename LabelT, typename... SET_T,
typename std::enable_if<(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph,
TwoLabelVertexSetImpl<VID_T, LabelT, SET_T...>& node,
Expand Down Expand Up @@ -379,7 +406,9 @@ class ProjectOp {
}

// general vertex set.
template <typename T, typename VID_T, typename LabelT>
template <
typename T, typename VID_T, typename LabelT,
typename std::enable_if<(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph, GeneralVertexSet<VID_T, LabelT>& node,
const std::string& prop_name_, const std::vector<size_t>& repeat_array) {
Expand Down Expand Up @@ -419,8 +448,10 @@ class ProjectOp {
}

// single label edge set
template <typename T, typename NODE_T,
typename std::enable_if<NODE_T::is_edge_set>::type* = nullptr>
template <
typename T, typename NODE_T,
typename std::enable_if<NODE_T::is_edge_set &&
(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph, NODE_T& node, const std::string& prop_name,
const std::vector<size_t>& repeat_array) {
Expand Down Expand Up @@ -449,7 +480,9 @@ class ProjectOp {
}

/// Apply project on untyped edge set.
template <typename T, typename VID_T, typename LabelT, typename SUB_GRAPH_T>
template <
typename T, typename VID_T, typename LabelT, typename SUB_GRAPH_T,
typename std::enable_if<(!std::is_same_v<T, LabelKey>)>::type* = nullptr>
static auto apply_single_project_impl(
const GRAPH_INTERFACE& graph,
UnTypedEdgeSet<VID_T, LabelT, SUB_GRAPH_T>& node,
Expand Down
44 changes: 41 additions & 3 deletions flex/engines/hqps_db/core/operator/sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,11 @@ class SinkOp {
}
}

// sink collection of pod
// sink collection of pod, expect for LabelKey type
template <size_t Ind, size_t act_tag_id, typename T,
typename std::enable_if<(!gs::is_vector<T>::value) &&
(!gs::is_tuple<T>::value)>::type* = nullptr>
typename std::enable_if<
(!gs::is_vector<T>::value) && (!gs::is_tuple<T>::value) &&
(!std::is_same<T, LabelKey>::value)>::type* = nullptr>
static void sink_col_impl(results::CollectiveResults& results_vec,
const Collection<T>& collection,
const std::vector<size_t>& repeat_offsets,
Expand Down Expand Up @@ -417,6 +418,43 @@ class SinkOp {
}
}

// sink collection of LabelKey
template <size_t Ind, size_t act_tag_id>
static void sink_col_impl(results::CollectiveResults& results_vec,
const Collection<LabelKey>& collection,
const std::vector<size_t>& repeat_offsets,
int32_t tag_id) {
if (repeat_offsets.empty()) {
CHECK(collection.Size() == results_vec.results_size())
<< "size neq " << collection.Size() << " "
<< results_vec.results_size();
for (auto i = 0; i < collection.Size(); ++i) {
auto row = results_vec.mutable_results(i);
CHECK(row->record().columns_size() == Ind);
auto record = row->mutable_record();
auto new_col = record->add_columns();
new_col->mutable_name_or_id()->set_id(tag_id);
auto obj =
new_col->mutable_entry()->mutable_element()->mutable_object();
obj->set_i32(collection.Get(i).label_id);
}
} else {
CHECK(repeat_offsets.size() == collection.Size());
size_t cur_ind = 0;
for (auto i = 0; i < collection.Size(); ++i) {
for (auto j = 0; j < repeat_offsets[i]; ++j) {
auto row = results_vec.mutable_results(cur_ind++);
auto record = row->mutable_record();
auto new_col = record->add_columns();
new_col->mutable_name_or_id()->set_id(tag_id);
auto obj =
new_col->mutable_entry()->mutable_element()->mutable_object();
obj->set_i32(collection.Get(i).label_id);
}
}
}
}

// sinke for tuple with one element
template <size_t Ind, size_t act_tag_id, typename T,
typename std::enable_if<
Expand Down
7 changes: 7 additions & 0 deletions flex/engines/hqps_db/core/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ struct LengthKey {
using length_data_type = int32_t;
};

struct LabelKey {
using label_data_type = int32_t;
int32_t label_id;
LabelKey() = default;
LabelKey(int32_t id) : label_id(id) {}
};

template <typename T>
struct is_label_key_prop : std::false_type {};

Expand Down
7 changes: 7 additions & 0 deletions flex/engines/hqps_db/core/utils/hqps_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,13 @@ struct to_string_impl<std::string> {
}
};

template <>
struct to_string_impl<LabelKey> {
static inline std::string to_string(const LabelKey& label_key) {
return std::to_string(label_key.label_id);
}
};

template <>
struct to_string_impl<Direction> {
static inline std::string to_string(const Direction& opt) {
Expand Down
12 changes: 12 additions & 0 deletions flex/engines/hqps_db/structures/multi_edge_set/adj_edge_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ class AdjEdgeSet {
return builder_t(src_label_, dst_label_, edge_label_, prop_names_, dir_);
}

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> label_vec(Size());
std::fill(label_vec.begin(), label_vec.end(), {edge_label_});
return label_vec;
}

iterator begin() const { return iterator(vids_, adj_lists_, 0); }

iterator end() const { return iterator(vids_, adj_lists_, vids_.size()); }
Expand Down Expand Up @@ -414,6 +420,12 @@ class AdjEdgeSet<GI, VID_T, LabelT, grape::EmptyType> {

iterator end() const { return iterator(vids_, adj_lists_, vids_.size()); }

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> label_vec(Size());
std::fill(label_vec.begin(), label_vec.end(), {edge_label_});
return label_vec;
}

size_t Size() const { return size_; }

template <typename EXPR, size_t num_labels>
Expand Down
19 changes: 19 additions & 0 deletions flex/engines/hqps_db/structures/multi_edge_set/flat_edge_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ class FlatEdgeSet {

iterator end() const { return iterator(vec_, vec_.size()); }

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
res.reserve(vec_.size());
for (auto i = 0; i < vec_.size(); ++i) {
auto ind = label_triplet_ind_[i];
res.emplace_back(label_triplet_[ind][2]);
}
return res;
}

template <size_t col_ind, typename... index_ele_tuple_t_>
flat_t Flat(
std::vector<std::tuple<index_ele_tuple_t_...>>& index_ele_tuple) const {
Expand Down Expand Up @@ -498,6 +508,15 @@ class SingleLabelEdgeSet {

iterator end() const { return iterator(vec_, vec_.size()); }

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
res.reserve(vec_.size());
for (auto i = 0; i < vec_.size(); ++i) {
res.emplace_back(label_triplet_[2]);
}
return res;
}

template <size_t col_ind, typename... index_ele_tuple_t_>
flat_t Flat(
std::vector<std::tuple<index_ele_tuple_t_...>>& index_ele_tuple) const {
Expand Down
18 changes: 18 additions & 0 deletions flex/engines/hqps_db/structures/multi_edge_set/general_edge_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,15 @@ class GeneralEdgeSet<2, GI, VID_T, LabelT, std::tuple<T...>, std::tuple<T...>> {

iterator end() const { return iterator(vids_, adj_lists_, vids_.size()); }

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
res.reserve(Size());
for (auto i = 0; i < Size(); ++i) {
res.emplace_back(edge_label_);
}
return res;
}

size_t Size() const {
if (size_ == 0) {
for (auto i = 0; i < adj_lists_.size(); ++i) {
Expand Down Expand Up @@ -612,6 +621,15 @@ class GeneralEdgeSet<2, GI, VID_T, LabelT, std::tuple<grape::EmptyType>,
bitsets_.swap(other.bitsets_);
}

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
res.reserve(Size());
for (auto i = 0; i < Size(); ++i) {
res.emplace_back(edge_label_);
}
return res;
}

iterator begin() const { return iterator(vids_, adj_lists_, 0); }

iterator end() const { return iterator(vids_, adj_lists_, vids_.size()); }
Expand Down
20 changes: 20 additions & 0 deletions flex/engines/hqps_db/structures/multi_edge_set/untyped_edge_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,26 @@ class UnTypedEdgeSet {
src_vertices_.size());
}

std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
res.reserve(Size());
for (auto i = 0; i < src_vertices_.size(); ++i) {
auto label_ind = label_indices_[i];
auto label = src_labels_[label_ind];
if (adj_lists_.find(label) != adj_lists_.end()) {
auto& sub_graphs = adj_lists_.at(label);
for (auto& sub_graph : sub_graphs) {
auto edge_iters = sub_graph.get_edges(src_vertices_[i]);
auto edge_label = sub_graph.GetEdgeLabel();
for (auto j = 0; j < edge_iters.Size(); ++j) {
res.emplace_back(edge_label);
}
}
}
}
return res;
}

size_t Size() const {
if (size_ == 0) {
auto iter_vec = generate_iters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ auto general_project_vertices_impl(
break;
}
} else {
if (expr(eles)) {
if (expr(std::get<0>(eles))) {
res_bitsets[label_id].set_bit(res_vec.size());
res_vec.push_back(old_vec[i]);
break;
Expand Down Expand Up @@ -381,6 +381,20 @@ class GeneralVertexSet {

LabelT GetLabel(size_t i) const { return label_names_[i]; }

const std::vector<LabelKey> GetLabelVec() const {
std::vector<LabelKey> res;
// fill res with vertex labels
for (auto i = 0; i < vec_.size(); ++i) {
for (auto j = 0; j < bitsets_.size(); ++j) {
if (bitsets_[j].get_bit(i)) {
res.emplace_back(label_names_[j]);
break;
}
}
}
return res;
}

// generate label indices.
std::vector<uint8_t> GenerateLabelIndices() const {
std::vector<uint8_t> label_indices;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,16 @@ class KeyedRowVertexSetImpl {

LabelT GetLabel() const { return v_label_; }

const std::vector<LabelKey> GetLabelVec() {
std::vector<LabelKey> res;
// fill res with vertex labels
res.reserve(vids_.size());
for (auto i = 0; i < vids_.size(); ++i) {
res.emplace_back(v_label_);
}
return res;
}

const std::array<std::string, sizeof...(T)>& GetPropNames() const {
return prop_names_;
}
Expand Down Expand Up @@ -768,6 +778,16 @@ class KeyedRowVertexSetImpl<LabelT, KEY_T, VID_T, grape::EmptyType> {

LabelT GetLabel() const { return v_label_; }

const std::vector<LabelKey> GetLabelVec() {
std::vector<LabelKey> res;
// fill res with vertex labels
res.reserve(vids_.size());
for (auto i = 0; i < vids_.size(); ++i) {
res.emplace_back(v_label_);
}
return res;
}

const std::vector<lid_t>& GetVertices() const { return vids_; }

builder_t CreateBuilder() const { return builder_t(v_label_); }
Expand Down
Loading

0 comments on commit 6e40478

Please sign in to comment.