use std::ops::RangeBounds;
use selene_core::{DbString, Value};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum IndexTarget {
Node,
Edge,
}
pub trait IndexCatalog: Send + Sync {
fn typed_index(
&self,
target: IndexTarget,
label: DbString,
property: DbString,
) -> Option<TypedIndexLookup>;
fn label_index(&self, target: IndexTarget, label: DbString) -> Option<IndexHandle>;
fn composite_index(
&self,
target: IndexTarget,
label: DbString,
properties: &[DbString],
) -> Option<CompositeIndexHandle>;
fn total_rows(&self, target: IndexTarget) -> Option<u64> {
let _ = target;
None
}
fn label_cardinality(&self, target: IndexTarget, label: DbString) -> Option<u64> {
let _ = (target, label);
None
}
fn equality_cardinality(
&self,
target: IndexTarget,
label: DbString,
property: DbString,
value: &Value,
) -> Option<u64> {
let _ = (target, label, property, value);
None
}
fn range_cardinality(
&self,
target: IndexTarget,
label: DbString,
property: DbString,
range: (std::ops::Bound<Value>, std::ops::Bound<Value>),
) -> Option<u64> {
let _ = (target, label, property, range);
None
}
fn typed_avg_bucket(
&self,
target: IndexTarget,
label: DbString,
property: DbString,
) -> Option<u64> {
let _ = (target, label, property);
None
}
fn composite_cardinality(
&self,
target: IndexTarget,
label: DbString,
properties: &[DbString],
keys: &[Value],
) -> Option<u64> {
let _ = (target, label, properties, keys);
None
}
fn composite_avg_bucket(
&self,
target: IndexTarget,
label: DbString,
properties: &[DbString],
) -> Option<u64> {
let _ = (target, label, properties);
None
}
}
pub(crate) type ValueRange = (std::ops::Bound<Value>, std::ops::Bound<Value>);
const _: fn() = || {
fn _assert<R: RangeBounds<Value>>() {}
_assert::<ValueRange>();
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct IndexHandle(u64);
impl IndexHandle {
#[must_use]
pub const fn new(raw: u64) -> Self {
Self(raw)
}
#[must_use]
pub const fn raw(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct TypedIndexLookup {
pub handle: IndexHandle,
pub kind: IndexKind,
}
impl TypedIndexLookup {
#[must_use]
pub const fn new(handle: IndexHandle, kind: IndexKind) -> Self {
Self { handle, kind }
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct CompositeIndexHandle {
pub handle: IndexHandle,
pub properties: Vec<(DbString, IndexKind)>,
}
impl CompositeIndexHandle {
#[must_use]
pub fn new(handle: IndexHandle, properties: Vec<(DbString, IndexKind)>) -> Self {
Self { handle, properties }
}
#[must_use]
pub fn property_keys(&self) -> Vec<DbString> {
self.properties.iter().map(|(key, _)| key.clone()).collect()
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum IndexKind {
Boolean,
Integer,
UnsignedInteger,
Integer128,
UnsignedInteger128,
Decimal,
Float32,
Float,
String,
Date,
LocalDateTime,
ZonedDateTime,
LocalTime,
ZonedTime,
Duration,
Uuid,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct EmptyIndexCatalog;
impl IndexCatalog for EmptyIndexCatalog {
fn typed_index(
&self,
_target: IndexTarget,
_label: DbString,
_property: DbString,
) -> Option<TypedIndexLookup> {
None
}
fn label_index(&self, _target: IndexTarget, _label: DbString) -> Option<IndexHandle> {
None
}
fn composite_index(
&self,
_target: IndexTarget,
_label: DbString,
_properties: &[DbString],
) -> Option<CompositeIndexHandle> {
None
}
}