pub(super) use crate::db::query::plan::planner::AccessCandidateScore as CandidateScore;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct AccessChoiceExplainSnapshot {
pub(in crate::db) chosen_reason: AccessChoiceSelectedReason,
pub(in crate::db) alternatives: Vec<&'static str>,
pub(in crate::db) rejected: Vec<String>,
}
impl AccessChoiceExplainSnapshot {
#[must_use]
pub(in crate::db) const fn non_index_access() -> Self {
Self {
chosen_reason: AccessChoiceSelectedReason::NonIndexAccess,
alternatives: Vec::new(),
rejected: Vec::new(),
}
}
#[must_use]
pub(in crate::db) const fn selected_index_not_projected() -> Self {
Self {
chosen_reason: AccessChoiceSelectedReason::SelectedIndexNotProjected,
alternatives: Vec::new(),
rejected: Vec::new(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum AccessChoiceRankingReason {
ExactMatchPreferred,
OrderCompatiblePreferred,
LexicographicTiebreak,
}
impl AccessChoiceRankingReason {
#[must_use]
pub(in crate::db) const fn code(self) -> &'static str {
match self {
Self::ExactMatchPreferred => "exact_match_preferred",
Self::OrderCompatiblePreferred => "order_compatible_preferred",
Self::LexicographicTiebreak => "lexicographic_tiebreak",
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum AccessChoiceSelectedReason {
NonIndexAccess,
SelectedIndexNotProjected,
SingleCandidate,
BestPrefixLen,
Ranked(AccessChoiceRankingReason),
}
impl AccessChoiceSelectedReason {
#[must_use]
pub(in crate::db) const fn code(self) -> &'static str {
match self {
Self::NonIndexAccess => "non_index_access",
Self::SelectedIndexNotProjected => "selected_index_not_projected",
Self::SingleCandidate => "single_candidate",
Self::BestPrefixLen => "best_prefix_len",
Self::Ranked(reason) => reason.code(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum AccessChoiceRejectedReason {
PredicateAbsent,
NonIndexAccess,
PredicateShapeNotPrefixEligible,
PredicateShapeNotMultiLookup,
PredicateShapeNotRangeEligible,
NonStrictCoercion,
OperatorNotPrefixEq,
OperatorNotMultiLookupIn,
OperatorNotRangeSupported,
OperatorNotSupported,
LeadingFieldMismatch,
LiteralIncompatible,
InLiteralNotList,
InLiteralEmpty,
InLiteralIncompatible,
SingleFieldRangeRequired,
StartsWithPrefixInvalid,
EqRangeConflict,
ConflictingEqConstraints,
NoEqConstraints,
LeadingFieldUnconstrained,
MissingContiguousPrefixOrRange,
NonContiguousRangeConstraints,
MissingRangeConstraint,
ShorterPrefix,
Ranked(AccessChoiceRankingReason),
}
impl AccessChoiceRejectedReason {
#[must_use]
pub(in crate::db) const fn code(self) -> &'static str {
match self {
Self::PredicateAbsent => "predicate_absent",
Self::NonIndexAccess => "non_index_access",
Self::PredicateShapeNotPrefixEligible => "predicate_shape_not_prefix_eligible",
Self::PredicateShapeNotMultiLookup => "predicate_shape_not_multi_lookup",
Self::PredicateShapeNotRangeEligible => "predicate_shape_not_range_eligible",
Self::NonStrictCoercion => "non_strict_coercion",
Self::OperatorNotPrefixEq => "operator_not_prefix_eq",
Self::OperatorNotMultiLookupIn => "operator_not_multi_lookup_in",
Self::OperatorNotRangeSupported => "operator_not_range_supported",
Self::OperatorNotSupported => "operator_not_supported",
Self::LeadingFieldMismatch => "leading_field_mismatch",
Self::LiteralIncompatible => "literal_incompatible",
Self::InLiteralNotList => "in_literal_not_list",
Self::InLiteralEmpty => "in_literal_empty",
Self::InLiteralIncompatible => "in_literal_incompatible",
Self::SingleFieldRangeRequired => "single_field_range_required",
Self::StartsWithPrefixInvalid => "startswith_prefix_invalid",
Self::EqRangeConflict => "eq_range_conflict",
Self::ConflictingEqConstraints => "conflicting_eq_constraints",
Self::NoEqConstraints => "no_eq_constraints",
Self::LeadingFieldUnconstrained => "leading_field_unconstrained",
Self::MissingContiguousPrefixOrRange => "missing_contiguous_prefix_or_range",
Self::NonContiguousRangeConstraints => "non_contiguous_range_constraints",
Self::MissingRangeConstraint => "missing_range_constraint",
Self::ShorterPrefix => "shorter_prefix",
Self::Ranked(reason) => reason.code(),
}
}
#[must_use]
pub(in crate::db) fn render_for_index(self, index_name: &'static str) -> String {
let reason = self.code();
let mut out = String::with_capacity("index:".len() + index_name.len() + 1 + reason.len());
out.push_str("index:");
out.push_str(index_name);
out.push('=');
out.push_str(reason);
out
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum AccessChoiceFamily {
NonIndex,
Prefix,
MultiLookup,
Range,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum RangeCompareKind {
StartsWith,
Ordered,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(super) struct RangeFieldConstraint {
pub(super) eq_value: Option<crate::value::Value>,
pub(super) has_range: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum CandidateEvaluation {
Eligible(CandidateScore),
Rejected(AccessChoiceRejectedReason),
}