Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(interactive): Support labels and type Functions in Cypher Queries #3255

Merged
merged 9 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading