use std::fmt::Write as _;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum PushdownApplicability {
NotApplicable,
Eligible {
index: &'static str,
prefix_len: usize,
},
Rejected(SecondaryOrderPushdownRejection),
}
impl PushdownApplicability {
#[must_use]
pub(crate) const fn is_eligible(&self) -> bool {
matches!(self, Self::Eligible { .. })
}
#[must_use]
pub(crate) fn diagnostic_label(&self) -> String {
match self {
Self::NotApplicable => "not_applicable".to_string(),
Self::Eligible { index, prefix_len } => {
format!("eligible(index={index},prefix_len={prefix_len})")
}
Self::Rejected(reason) => format!("rejected({})", reason.label()),
}
}
#[must_use]
pub(crate) const fn eligible_secondary_index(&self) -> Option<(&'static str, usize)> {
match self {
Self::Eligible { index, prefix_len } => Some((index, *prefix_len)),
Self::NotApplicable | Self::Rejected(_) => None,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SecondaryOrderPushdownRejection {
NoOrderBy,
AccessPathNotSingleIndexPrefix,
AccessPathIndexRangeUnsupported {
index: &'static str,
prefix_len: usize,
},
InvalidIndexPrefixBounds {
prefix_len: usize,
index_field_len: usize,
},
MissingPrimaryKeyTieBreak {
field: String,
},
PrimaryKeyDirectionNotAscending {
field: String,
},
MixedDirectionNotEligible {
field: String,
},
OrderFieldsDoNotMatchIndex {
index: &'static str,
prefix_len: usize,
expected_suffix: Vec<String>,
expected_full: Vec<String>,
actual: Vec<String>,
},
}
impl SecondaryOrderPushdownRejection {
#[must_use]
pub(crate) fn label(&self) -> String {
let mut out = String::new();
self.write_label(&mut out);
out
}
fn write_label(&self, out: &mut String) {
match self {
Self::NoOrderBy => out.push_str("NoOrderBy"),
Self::AccessPathNotSingleIndexPrefix => {
out.push_str("AccessPathNotSingleIndexPrefix");
}
Self::AccessPathIndexRangeUnsupported { index, prefix_len } => {
let _ = write!(
out,
"AccessPathIndexRangeUnsupported(index={index},prefix_len={prefix_len})",
);
}
Self::InvalidIndexPrefixBounds {
prefix_len,
index_field_len,
} => {
let _ = write!(
out,
"InvalidIndexPrefixBounds(prefix_len={prefix_len},index_field_len={index_field_len})",
);
}
Self::MissingPrimaryKeyTieBreak { field } => {
let _ = write!(out, "MissingPrimaryKeyTieBreak(field={field})");
}
Self::PrimaryKeyDirectionNotAscending { field } => {
let _ = write!(out, "PrimaryKeyDirectionNotAscending(field={field})");
}
Self::MixedDirectionNotEligible { field } => {
let _ = write!(out, "MixedDirectionNotEligible(field={field})");
}
Self::OrderFieldsDoNotMatchIndex {
index,
prefix_len,
expected_suffix,
expected_full,
actual,
} => {
let _ = write!(
out,
"OrderFieldsDoNotMatchIndex(index={index},prefix_len={prefix_len},expected_suffix={expected_suffix:?},expected_full={expected_full:?},actual={actual:?})",
);
}
}
}
}