Skip to content

Commit

Permalink
refactor(interactive): Improve the code of checking if a given label …
Browse files Browse the repository at this point in the history
…sets contain all labels in the schema (#3374)

Improve the performance of checking if a given label sets contain all
labels in the schema
longbinlai authored Nov 23, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 4966d32 commit c237328
Showing 3 changed files with 69 additions and 83 deletions.
12 changes: 1 addition & 11 deletions interactive_engine/executor/ir/core/src/plan/ffi.rs
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ use prost::Message;

use crate::error::IrError;
use crate::plan::logical::{LogicalPlan, NodeId};
use crate::plan::meta::{set_schema_from_json, KeyType};
use crate::plan::meta::set_schema_from_json;
use crate::plan::physical::AsPhysical;

#[repr(i32)]
@@ -519,16 +519,6 @@ pub enum FfiKeyType {
Column = 2,
}

impl From<FfiKeyType> for KeyType {
fn from(t: FfiKeyType) -> Self {
match t {
FfiKeyType::Entity => KeyType::Entity,
FfiKeyType::Relation => KeyType::Relation,
FfiKeyType::Column => KeyType::Column,
}
}
}

/// Query entity/relation/property name by given id
#[no_mangle]
pub extern "C" fn get_key_name(key_id: i32, key_type: FfiKeyType) -> FfiResult {
24 changes: 13 additions & 11 deletions interactive_engine/executor/ir/core/src/plan/logical.rs
Original file line number Diff line number Diff line change
@@ -968,7 +968,7 @@ fn build_and_predicate(

fn get_table_id_from_pb(schema: &Schema, name: &common_pb::NameOrId) -> Option<KeyId> {
name.item.as_ref().and_then(|item| match item {
common_pb::name_or_id::Item::Name(name) => schema.get_table_id(name),
common_pb::name_or_id::Item::Name(name) => schema.get_entity_or_relation_id(name),
common_pb::name_or_id::Item::Id(id) => Some(*id),
})
}
@@ -1027,7 +1027,7 @@ fn preprocess_label(
common_pb::value::Item::Str(name) => {
let new_item = common_pb::value::Item::I32(
schema
.get_table_id(name)
.get_entity_or_relation_id(name)
.ok_or_else(|| IrError::TableNotExist(NameOrId::Str(name.to_string())))?,
);
debug!("table: {:?} -> {:?}", item, new_item);
@@ -1039,9 +1039,11 @@ fn preprocess_label(
.item
.iter()
.map(|name| {
schema.get_table_id(name).ok_or_else(|| {
IrError::TableNotExist(NameOrId::Str(name.to_string()))
})
schema
.get_entity_or_relation_id(name)
.ok_or_else(|| {
IrError::TableNotExist(NameOrId::Str(name.to_string()))
})
})
.collect::<IrResult<Vec<_>>>()?,
});
@@ -1502,7 +1504,7 @@ fn is_params_all_labels(params: &pb::QueryParams) -> bool {
.as_ref()
.and_then(|store_meta| store_meta.schema.as_ref())
{
let params_label_ids: BTreeSet<LabelId> = params
let mut params_label_ids: Vec<LabelId> = params
.tables
.iter()
.filter_map(|name_or_id| {
@@ -1515,11 +1517,11 @@ fn is_params_all_labels(params: &pb::QueryParams) -> bool {
}
})
.collect();
let meta_label_ids: BTreeSet<LabelId> = schema
.entity_labels_iter()
.map(|(_, label_id)| label_id)
.collect();
params_label_ids.eq(&meta_label_ids)

params_label_ids.sort();
params_label_ids.dedup();

schema.check_all_entity_labels(&params_label_ids)
} else {
false
}
116 changes: 55 additions & 61 deletions interactive_engine/executor/ir/core/src/plan/meta.rs
Original file line number Diff line number Diff line change
@@ -103,31 +103,22 @@ impl From<LabelMeta> for schema_pb::LabelMeta {
}
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum KeyType {
Entity = 0,
Relation = 1,
Column = 2,
}

impl Default for KeyType {
fn default() -> Self {
Self::Entity
}
}

#[derive(Clone, Debug, Default)]
pub struct Schema {
/// A map from table (Entity or Relation) name to its internally encoded id
/// In the concept of graph database, this is also known as label
table_name_to_id: BTreeMap<String, (KeyType, LabelId)>,
/// A map from entity name to its internally encoded id
/// In the concept of graph database, this is also known as vertex label
entity_name_to_id: BTreeMap<String, LabelId>,
/// A map from relation name to its internally encoded id
/// In the concept of graph database, this is also known as vertex label
relation_name_to_id: BTreeMap<String, LabelId>,
/// A map from column name to its store-encoded id
/// In the concept of graph database, this is also known as property
column_name_to_id: BTreeMap<String, KeyId>,
/// Record the primary keys of each table
primary_keys: BTreeMap<String, BTreeSet<String>>,
/// A reversed map of `id` to `name` mapping
id_to_name: BTreeMap<(KeyType, KeyId), String>,
/// A reversed map of `id` to `name` mapping.
/// 0, entity; 1, relation; 2, column
id_to_name: BTreeMap<(u8, KeyId), String>,
/// The entities' labels that are bound a certain type of relations
relation_bound_labels: BTreeMap<KeyId, Vec<(LabelMeta, LabelMeta)>>,
/// Is the table name mapped as id
@@ -151,55 +142,58 @@ impl Schema {
if schema.is_table_id {
for (name, id) in entities.into_iter() {
schema
.table_name_to_id
.insert(name.clone(), (KeyType::Entity, id));
schema
.id_to_name
.insert((KeyType::Entity, id), name);
.entity_name_to_id
.insert(name.clone(), id);
schema.id_to_name.insert((0, id), name);
}
for (name, id) in relations.into_iter() {
schema
.table_name_to_id
.insert(name.clone(), (KeyType::Relation, id));
schema
.id_to_name
.insert((KeyType::Relation, id), name);
.relation_name_to_id
.insert(name.clone(), id);
schema.id_to_name.insert((1, id), name);
}
}
if schema.is_column_id {
for (name, id) in columns.into_iter() {
schema
.column_name_to_id
.insert(name.clone(), id);
schema
.id_to_name
.insert((KeyType::Column, id), name);
schema.id_to_name.insert((2, id), name);
}
}

schema
}

pub fn get_table_id(&self, name: &str) -> Option<LabelId> {
self.table_name_to_id
pub fn get_entity_id(&self, name: &str) -> Option<LabelId> {
self.entity_name_to_id.get(name).map(|id| *id)
}

pub fn get_relation_id(&self, name: &str) -> Option<LabelId> {
self.relation_name_to_id.get(name).map(|id| *id)
}

pub fn get_entity_or_relation_id(&self, name: &str) -> Option<LabelId> {
self.entity_name_to_id
.get(name)
.map(|(_, id)| *id)
.map(|id| *id)
.or_else(|| self.relation_name_to_id.get(name).map(|id| *id))
}

pub fn get_column_id(&self, name: &str) -> Option<KeyId> {
self.column_name_to_id.get(name).cloned()
}

pub fn get_entity_name(&self, id: KeyId) -> Option<&String> {
self.id_to_name.get(&(KeyType::Entity, id))
self.id_to_name.get(&(0, id))
}

pub fn get_relation_name(&self, id: KeyId) -> Option<&String> {
self.id_to_name.get(&(KeyType::Relation, id))
self.id_to_name.get(&(1, id))
}

pub fn get_column_name(&self, id: KeyId) -> Option<&String> {
self.id_to_name.get(&(KeyType::Column, id))
self.id_to_name.get(&(2, id))
}

/// To get the entities' labels that are bound to a relation of given type
@@ -215,18 +209,18 @@ impl Schema {
self.is_table_id
}

pub fn entity_labels_iter(&self) -> DynIter<(String, LabelId)> {
Box::new(
self.table_name_to_id
.iter()
.filter_map(|(name, (key_type, label_id))| {
if let KeyType::Entity = key_type {
Some((name.clone(), *label_id))
} else {
None
}
}),
)
/// Check whether the given entity labels contain all entity labels in the schema
pub fn check_all_entity_labels(&self, label_ids: &Vec<LabelId>) -> bool {
if self.entity_name_to_id.len() != label_ids.len() {
false
} else {
for label_id in label_ids {
if !self.id_to_name.contains_key(&(0, *label_id)) {
return false;
}
}
true
}
}

/// Check whether a given table contains a given column as a primary key.
@@ -247,7 +241,7 @@ impl From<Schema> for schema_pb::Schema {
} else {
let mut entities = Vec::new();
for (&(ty, id), name) in &schema.id_to_name {
if ty == KeyType::Entity {
if ty == 0 {
entities.push(schema_pb::EntityMeta {
label: Some(schema_pb::LabelMeta { id, name: name.to_string() }),
columns: vec![],
@@ -262,7 +256,7 @@ impl From<Schema> for schema_pb::Schema {
} else {
let mut relations = Vec::new();
for (&(ty, id), name) in &schema.id_to_name {
if ty == KeyType::Relation {
if ty == 1 {
let mut relation_meta = schema_pb::RelationMeta {
label: Some(schema_pb::LabelMeta { id, name: name.to_string() }),
entity_pairs: vec![],
@@ -304,15 +298,15 @@ impl From<schema_pb::Schema> for Schema {
if schema_pb.is_table_id {
if let Some(label) = &entity.label {
if !schema
.table_name_to_id
.entity_name_to_id
.contains_key(&label.name)
{
schema
.table_name_to_id
.insert(label.name.clone(), (KeyType::Entity, label.id));
.entity_name_to_id
.insert(label.name.clone(), label.id);
schema
.id_to_name
.insert((KeyType::Entity, label.id), label.name.clone());
.insert((0, label.id), label.name.clone());
}
}
}
@@ -326,7 +320,7 @@ impl From<schema_pb::Schema> for Schema {
.insert(key.name.clone(), key.id);
schema
.id_to_name
.insert((KeyType::Column, key.id), key.name.clone());
.insert((2, key.id), key.name.clone());
}
}
if column.is_primary_key {
@@ -346,15 +340,15 @@ impl From<schema_pb::Schema> for Schema {
if schema_pb.is_table_id {
if let Some(label) = &rel.label {
if !schema
.table_name_to_id
.relation_name_to_id
.contains_key(&label.name)
{
schema
.table_name_to_id
.insert(label.name.clone(), (KeyType::Relation, label.id));
.relation_name_to_id
.insert(label.name.clone(), label.id);
schema
.id_to_name
.insert((KeyType::Relation, label.id), label.name.clone());
.insert((1, label.id), label.name.clone());
}
}
}
@@ -368,7 +362,7 @@ impl From<schema_pb::Schema> for Schema {
.insert(key.name.clone(), key.id);
schema
.id_to_name
.insert((KeyType::Column, key.id), key.name.clone());
.insert((2, key.id), key.name.clone());
}
}
if column.is_primary_key {

0 comments on commit c237328

Please sign in to comment.