use super::types::{FragmentIdAllocator, PhysicalOperatorIdAllocator};
use crate::executor::base::ExecutionContext;
use crate::executor::streaming::parameters::ParameterSchema;
use crate::executor::streaming::slot::SlotLayout;
use crate::planning::plan::PartitionSpec;
use linkrs_core::error::QueryError;
#[derive(Debug, Clone)]
pub struct SchemaRef {
pub space_name: String,
pub layout_version: u64,
}
#[derive(Debug, Clone, Default)]
pub struct StatisticsSnapshot {
pub row_count_estimates: Vec<(String, u64)>,
pub per_node_row_estimates: std::collections::HashMap<i64, u64>,
}
#[derive(Debug, Clone)]
pub struct PlanningConfig {
pub max_partitions: usize,
pub enable_hash_join: bool,
pub optimizer_version: u64,
pub config_hash: u64,
}
impl Default for PlanningConfig {
fn default() -> Self {
Self {
max_partitions: 4,
enable_hash_join: true,
optimizer_version: 1,
config_hash: 0,
}
}
}
#[derive(Debug, Clone)]
pub struct PhysicalPlanBuildContext {
pub schema: Option<SchemaRef>,
pub statistics: StatisticsSnapshot,
pub config: PlanningConfig,
pub expected_output_layout: Option<SlotLayout>,
pub parameter_schema: ParameterSchema,
pub partition_spec: Option<PartitionSpec>,
pub parallel_fallback_reason: String,
pub cbo_notes: Vec<String>,
pub statistics_summary: String,
pub(crate) operator_id_alloc: PhysicalOperatorIdAllocator,
pub(crate) fragment_id_alloc: FragmentIdAllocator,
}
impl PhysicalPlanBuildContext {
pub fn from_execution_context(context: &ExecutionContext) -> Self {
Self {
schema: context.space_name.as_ref().map(|space_name| SchemaRef {
space_name: space_name.clone(),
layout_version: 0,
}),
statistics: StatisticsSnapshot::default(),
config: PlanningConfig {
max_partitions: context.max_workers,
..PlanningConfig::default()
},
expected_output_layout: None,
parameter_schema: ParameterSchema::default(),
partition_spec: None,
parallel_fallback_reason: String::new(),
cbo_notes: Vec::new(),
statistics_summary: String::new(),
operator_id_alloc: PhysicalOperatorIdAllocator::new(),
fragment_id_alloc: FragmentIdAllocator::new(),
}
}
pub fn new() -> Self {
Self {
schema: None,
statistics: StatisticsSnapshot::default(),
config: PlanningConfig::default(),
expected_output_layout: None,
parameter_schema: ParameterSchema::default(),
partition_spec: None,
parallel_fallback_reason: String::new(),
cbo_notes: Vec::new(),
statistics_summary: String::new(),
operator_id_alloc: PhysicalOperatorIdAllocator::new(),
fragment_id_alloc: FragmentIdAllocator::new(),
}
}
pub fn allocate_operator_id(
&mut self,
) -> crate::executor::streaming::plan::types::PhysicalOperatorId {
self.operator_id_alloc.allocate()
}
pub fn allocate_fragment_id(&mut self) -> crate::executor::streaming::plan::types::FragmentId {
self.fragment_id_alloc.allocate()
}
pub fn peek_operator_id(&self) -> crate::executor::streaming::plan::types::PhysicalOperatorId {
self.operator_id_alloc.peek()
}
pub fn validate(&self) -> Result<(), QueryError> {
Ok(())
}
}
impl Default for PhysicalPlanBuildContext {
fn default() -> Self {
Self::new()
}
}