use super::support::{CompiledBoundedPipelineSupport, compiled_bounded_query_plan_support};
use crate::{
backend::AnalysisContext,
capability::Rejection,
error::Result,
pipeline::{CompiledPipeline, PipelineCompilation, compile_pipeline_outcome},
plan::QueryPlan,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum CapabilityFirstCandidateStatus {
Admitted,
Rejected,
}
#[derive(Debug, Clone)]
pub(super) struct CapabilityFirstPipelineAdmission {
pipeline: Option<CompiledPipeline>,
rejection: Option<Rejection>,
candidate_status: CapabilityFirstCandidateStatus,
}
impl CapabilityFirstPipelineAdmission {
pub(super) fn candidate_status(&self) -> CapabilityFirstCandidateStatus {
self.candidate_status
}
pub(super) fn rejection(&self) -> Option<&Rejection> {
self.rejection.as_ref()
}
pub(super) fn into_pipeline(self) -> Option<CompiledPipeline> {
self.pipeline
}
fn admitted(pipeline: CompiledPipeline) -> Self {
Self { pipeline: Some(pipeline), rejection: None, candidate_status: CapabilityFirstCandidateStatus::Admitted }
}
fn rejected(pipeline: Option<CompiledPipeline>, rejection: Rejection) -> Self {
Self { pipeline, rejection: Some(rejection), candidate_status: CapabilityFirstCandidateStatus::Rejected }
}
}
pub(super) fn capability_first_bounded_pipeline_admission(
plan: &QueryPlan,
ctx: AnalysisContext<'_>,
) -> Result<CapabilityFirstPipelineAdmission> {
let analysis = plan.capability_analysis(ctx);
if let Some(rejection) = analysis.first_rejection() {
return Ok(CapabilityFirstPipelineAdmission::rejected(None, rejection));
}
let pipeline = match compile_pipeline_outcome(plan, &analysis)? {
PipelineCompilation::Compiled(pipeline) => pipeline,
PipelineCompilation::Rejected(rejection) => {
return Ok(CapabilityFirstPipelineAdmission::rejected(None, rejection));
},
};
match compiled_bounded_query_plan_support(plan, &analysis, &pipeline)? {
CompiledBoundedPipelineSupport::Supported => Ok(CapabilityFirstPipelineAdmission::admitted(pipeline)),
CompiledBoundedPipelineSupport::Unsupported(rejection) => {
Ok(CapabilityFirstPipelineAdmission::rejected(Some(pipeline), rejection))
},
}
}