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
  • Loading branch information
longbinlai committed Nov 23, 2023
1 parent 4966d32 commit c237328
Show file tree
Hide file tree
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
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down
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
Expand Up @@ -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),
})
}
Expand Down Expand Up @@ -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);
Expand All @@ -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<_>>>()?,
});
Expand Down Expand Up @@ -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| {
Expand All @@ -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
}
Expand Down
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
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand All @@ -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![],
Expand All @@ -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![],
Expand Down Expand Up @@ -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());
}
}
}
Expand All @@ -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 {
Expand All @@ -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());
}
}
}
Expand All @@ -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 {
Expand Down

0 comments on commit c237328

Please sign in to comment.