use crate::{
MAX_INDEX_FIELDS,
db::{
access::{AccessPlan, SemanticIndexAccessContract},
index::IndexId,
registry::ExactPrefixCardinalityLifecycleStamp,
},
types::EntityTag,
value::Value,
};
use std::borrow::Cow;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum CardinalityTiebreakFamily {
Prefix,
MultiLookup,
BranchSet,
}
impl CardinalityTiebreakFamily {
#[must_use]
pub(in crate::db) const fn wire_tag(self) -> u8 {
match self {
Self::Prefix => 1,
Self::MultiLookup => 2,
Self::BranchSet => 3,
}
}
pub(in crate::db) const fn from_wire_tag(tag: u8) -> Option<Self> {
match tag {
1 => Some(Self::Prefix),
2 => Some(Self::MultiLookup),
3 => Some(Self::BranchSet),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) struct CardinalityTiebreakRoutePin {
index_id: IndexId,
family: CardinalityTiebreakFamily,
consumed_prefix_arity: u8,
}
impl CardinalityTiebreakRoutePin {
#[must_use]
pub(in crate::db) fn new(
index_id: IndexId,
family: CardinalityTiebreakFamily,
consumed_prefix_arity: usize,
) -> Option<Self> {
if consumed_prefix_arity == 0 || consumed_prefix_arity > MAX_INDEX_FIELDS {
return None;
}
Some(Self {
index_id,
family,
consumed_prefix_arity: u8::try_from(consumed_prefix_arity).ok()?,
})
}
#[must_use]
pub(in crate::db) const fn index_id(self) -> IndexId {
self.index_id
}
#[must_use]
pub(in crate::db) const fn family(self) -> CardinalityTiebreakFamily {
self.family
}
#[must_use]
pub(in crate::db) const fn consumed_prefix_arity(self) -> u8 {
self.consumed_prefix_arity
}
}
#[derive(Clone, Debug)]
pub(in crate::db) struct CardinalityTiebreakCandidate<'a> {
access: Cow<'a, AccessPlan<Value>>,
index: SemanticIndexAccessContract,
family: CardinalityTiebreakFamily,
consumed_prefix_arity: usize,
}
impl<'a> CardinalityTiebreakCandidate<'a> {
#[must_use]
pub(in crate::db::query) const fn new(
access: Cow<'a, AccessPlan<Value>>,
index: SemanticIndexAccessContract,
family: CardinalityTiebreakFamily,
consumed_prefix_arity: usize,
) -> Self {
Self {
access,
index,
family,
consumed_prefix_arity,
}
}
#[must_use]
pub(in crate::db) fn access(&self) -> &AccessPlan<Value> {
&self.access
}
#[must_use]
pub(in crate::db) fn into_replacement_access(self) -> Option<AccessPlan<Value>> {
match self.access {
Cow::Borrowed(_) => None,
Cow::Owned(access) => Some(access),
}
}
#[cfg(test)]
pub(in crate::db) fn into_owned(self) -> CardinalityTiebreakCandidate<'static> {
CardinalityTiebreakCandidate {
access: Cow::Owned(self.access.into_owned()),
index: self.index,
family: self.family,
consumed_prefix_arity: self.consumed_prefix_arity,
}
}
#[must_use]
pub(in crate::db) const fn index(&self) -> &SemanticIndexAccessContract {
&self.index
}
#[must_use]
pub(in crate::db) fn route_pin(
&self,
entity_tag: EntityTag,
) -> Option<CardinalityTiebreakRoutePin> {
CardinalityTiebreakRoutePin::new(
IndexId::new_with_generation(
entity_tag,
self.index.ordinal(),
self.index.physical_generation(),
),
self.family,
self.consumed_prefix_arity,
)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct CardinalityTiebreakCandidateEvidence {
index_name: String,
exact_prefix_entries: u64,
}
impl CardinalityTiebreakCandidateEvidence {
#[must_use]
pub(in crate::db) const fn new(index_name: String, exact_prefix_entries: u64) -> Self {
Self {
index_name,
exact_prefix_entries,
}
}
#[must_use]
pub(in crate::db) const fn index_name(&self) -> &str {
self.index_name.as_str()
}
#[must_use]
pub(in crate::db) const fn exact_prefix_entries(&self) -> u64 {
self.exact_prefix_entries
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct ExactCardinalityTiebreakEvidence {
route_pin: CardinalityTiebreakRoutePin,
candidates: Vec<CardinalityTiebreakCandidateEvidence>,
}
impl ExactCardinalityTiebreakEvidence {
#[must_use]
pub(in crate::db) const fn new(
route_pin: CardinalityTiebreakRoutePin,
candidates: Vec<CardinalityTiebreakCandidateEvidence>,
) -> Self {
Self {
route_pin,
candidates,
}
}
#[must_use]
pub(in crate::db) const fn route_pin(&self) -> CardinalityTiebreakRoutePin {
self.route_pin
}
#[must_use]
pub(in crate::db) const fn candidates(&self) -> &[CardinalityTiebreakCandidateEvidence] {
self.candidates.as_slice()
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(in crate::db) enum CardinalityTiebreakState {
#[default]
NotApplicable,
ExactAtSelection(ExactCardinalityTiebreakEvidence),
PinnedContinuation(CardinalityTiebreakRoutePin),
Unavailable {
lifecycle_stamp: ExactPrefixCardinalityLifecycleStamp,
route_pin: CardinalityTiebreakRoutePin,
},
PolicyFallback(CardinalityTiebreakRoutePin),
}
impl CardinalityTiebreakState {
#[must_use]
pub(in crate::db) const fn route_pin(&self) -> Option<CardinalityTiebreakRoutePin> {
match self {
Self::ExactAtSelection(evidence) => Some(evidence.route_pin()),
Self::PinnedContinuation(route_pin) | Self::PolicyFallback(route_pin) => {
Some(*route_pin)
}
Self::Unavailable { route_pin, .. } => Some(*route_pin),
Self::NotApplicable => None,
}
}
#[must_use]
pub(in crate::db) const fn unavailable_stamp(
&self,
) -> Option<ExactPrefixCardinalityLifecycleStamp> {
match self {
Self::Unavailable {
lifecycle_stamp, ..
} => Some(*lifecycle_stamp),
Self::NotApplicable
| Self::ExactAtSelection(_)
| Self::PinnedContinuation(_)
| Self::PolicyFallback(_) => None,
}
}
}
crate::retained::retained_fields!(CardinalityTiebreakCandidateEvidence {
Self{index_name,exact_prefix_entries} => [index_name,exact_prefix_entries],
});
crate::retained::retained_copy!(CardinalityTiebreakRoutePin);
crate::retained::retained_fields!(CardinalityTiebreakState {
Self::NotApplicable => [],
Self::ExactAtSelection(field_0) => [field_0],
Self::PinnedContinuation(field_0) => [field_0],
Self::Unavailable{lifecycle_stamp,route_pin} => [lifecycle_stamp,route_pin],
Self::PolicyFallback(field_0) => [field_0],
});
crate::retained::retained_fields!(ExactCardinalityTiebreakEvidence {
Self{route_pin,candidates} => [route_pin,candidates],
});