use linkrs_core::value::ordered_codec::OrderedCodec;
use linkrs_core::{StorageError, Value};
use super::key_types::{
ByteKey, KEY_TYPE_EDGE_FORWARD, KEY_TYPE_EDGE_REVERSE, KEY_TYPE_VERTEX_FORWARD,
KEY_TYPE_VERTEX_REVERSE,
};
pub struct KeyBuilder;
pub fn codec() -> OrderedCodec {
OrderedCodec::new()
}
pub fn normalize_int_value(v: &Value) -> Value {
match v {
Value::BigInt(n) => {
if *n >= i16::MIN as i64 && *n <= i16::MAX as i64 {
return Value::SmallInt(*n as i16);
}
if *n >= i32::MIN as i64 && *n <= i32::MAX as i64 {
return Value::Int(*n as i32);
}
v.clone()
}
Value::Int(n) => {
if *n >= i16::MIN as i32 && *n <= i16::MAX as i32 {
return Value::SmallInt(*n as i16);
}
v.clone()
}
_ => v.clone(),
}
}
impl KeyBuilder {
pub fn build_vertex_index_key(
space_id: u64,
index_name: &str,
prop_value: &Value,
vertex_id: &Value,
) -> Result<ByteKey, StorageError> {
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_VERTEX_FORWARD);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
key.extend_from_slice(&encoded_value);
let encoded_entity = codec().encode(vertex_id)?;
key.extend_from_slice(&encoded_entity);
Ok(ByteKey(key))
}
pub fn build_vertex_index_prefix(space_id: u64, index_name: &str) -> ByteKey {
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_VERTEX_FORWARD);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
ByteKey(key)
}
pub fn build_vertex_index_value_prefix(
space_id: u64,
index_name: &str,
prop_value: &Value,
) -> Result<ByteKey, StorageError> {
let mut key = Self::build_vertex_index_prefix(space_id, index_name).0;
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
key.extend_from_slice(&encoded_value);
Ok(ByteKey(key))
}
pub fn build_vertex_reverse_key_v2(
space_id: u64,
vertex_id: &Value,
index_name: &str,
) -> Result<ByteKey, StorageError> {
let encoded_entity = codec().encode(vertex_id)?;
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_VERTEX_REVERSE);
key.extend_from_slice(&encoded_entity);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
Ok(ByteKey(key))
}
pub fn build_vertex_reverse_key_with_value(
space_id: u64,
vertex_id: &Value,
index_name: &str,
prop_value: &Value,
) -> Result<ByteKey, StorageError> {
let encoded_entity = codec().encode(vertex_id)?;
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_VERTEX_REVERSE);
key.extend_from_slice(&encoded_entity);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
key.extend_from_slice(&encoded_value);
Ok(ByteKey(key))
}
pub fn build_edge_index_key(
space_id: u64,
index_name: &str,
prop_value: &Value,
edge_src: &Value,
edge_dst: &Value,
edge_type: &str,
ranking: i64,
) -> Result<ByteKey, StorageError> {
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_EDGE_FORWARD);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
key.extend_from_slice(&encoded_value);
let encoded_src = codec().encode(edge_src)?;
key.extend_from_slice(&encoded_src);
let encoded_dst = codec().encode(edge_dst)?;
key.extend_from_slice(&encoded_dst);
let encoded_type = codec().encode(&Value::string(edge_type))?;
key.extend_from_slice(&encoded_type);
let encoded_rank = codec().encode(&Value::BigInt(ranking))?;
key.extend_from_slice(&encoded_rank);
Ok(ByteKey(key))
}
pub fn build_edge_index_prefix(space_id: u64, index_name: &str) -> ByteKey {
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_EDGE_FORWARD);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
ByteKey(key)
}
pub fn build_edge_index_value_prefix(
space_id: u64,
index_name: &str,
prop_value: &Value,
) -> Result<ByteKey, StorageError> {
let mut key = Self::build_edge_index_prefix(space_id, index_name).0;
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
key.extend_from_slice(&encoded_value);
Ok(ByteKey(key))
}
pub fn build_edge_reverse_key(
space_id: u64,
edge_src: &Value,
edge_dst: &Value,
edge_type: &str,
ranking: i64,
index_name: &str,
) -> Result<ByteKey, StorageError> {
let encoded_src = codec().encode(edge_src)?;
let encoded_dst = codec().encode(edge_dst)?;
let encoded_type = codec().encode(&Value::string(edge_type))?;
let encoded_rank = codec().encode(&Value::BigInt(ranking))?;
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_EDGE_REVERSE);
key.extend_from_slice(&encoded_src);
key.extend_from_slice(&encoded_dst);
key.extend_from_slice(&encoded_type);
key.extend_from_slice(&encoded_rank);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
Ok(ByteKey(key))
}
pub fn build_edge_reverse_key_with_value(
space_id: u64,
edge_src: &Value,
edge_dst: &Value,
edge_type: &str,
ranking: i64,
index_name: &str,
prop_value: &Value,
) -> Result<ByteKey, StorageError> {
let encoded_src = codec().encode(edge_src)?;
let encoded_dst = codec().encode(edge_dst)?;
let encoded_type = codec().encode(&Value::string(edge_type))?;
let encoded_rank = codec().encode(&Value::BigInt(ranking))?;
let encoded_value = codec().encode(&normalize_int_value(prop_value))?;
let mut key = Vec::new();
key.extend_from_slice(&space_id.to_le_bytes());
key.push(KEY_TYPE_EDGE_REVERSE);
key.extend_from_slice(&encoded_src);
key.extend_from_slice(&encoded_dst);
key.extend_from_slice(&encoded_type);
key.extend_from_slice(&encoded_rank);
key.extend_from_slice(&(index_name.len() as u32).to_le_bytes());
key.extend_from_slice(index_name.as_bytes());
key.extend_from_slice(&encoded_value);
Ok(ByteKey(key))
}
pub fn build_range_end(prefix: &ByteKey) -> ByteKey {
ByteKey(OrderedCodec::prefix_upper_bound(&prefix.0))
}
}
#[cfg(test)]
mod tests {
use super::*;
use linkrs_core::Value;
#[test]
fn test_build_vertex_index_key() {
let space_id = 1u64;
let index_name = "idx_test";
let prop_value = Value::string("test_value");
let vertex_id = Value::Int(123);
let key = KeyBuilder::build_vertex_index_key(space_id, index_name, &prop_value, &vertex_id)
.expect("build_vertex_index_key should succeed");
assert!(key.0.len() > 9);
assert_eq!(key.0[8], KEY_TYPE_VERTEX_FORWARD);
}
#[test]
fn test_build_vertex_reverse_key_v2() {
let space_id = 1u64;
let vertex_id = Value::Int(456);
let index_name = "idx_test";
let key = KeyBuilder::build_vertex_reverse_key_v2(space_id, &vertex_id, index_name)
.expect("build_vertex_reverse_key_v2 should succeed");
assert!(key.0.len() > 9);
assert_eq!(key.0[8], KEY_TYPE_VERTEX_REVERSE);
}
#[test]
fn test_build_range_end() {
let prefix = ByteKey(vec![1, 2, 3]);
let end = KeyBuilder::build_range_end(&prefix);
assert_eq!(end.0, vec![1, 2, 4]);
}
#[test]
fn test_build_range_end_overflow() {
let prefix = ByteKey(vec![1, 255, 255]);
let end = KeyBuilder::build_range_end(&prefix);
assert_eq!(end.0, vec![2, 0, 0]);
}
}