use crate::db::query::explain::ExplainExecutionNodeDescriptor;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum ExecutionNodeLayer {
Scan,
Pipeline,
Aggregate,
Terminal,
}
impl ExecutionNodeLayer {
#[must_use]
const fn as_str(self) -> &'static str {
match self {
Self::Scan => "scan",
Self::Pipeline => "pipeline",
Self::Aggregate => "aggregate",
Self::Terminal => "terminal",
}
}
#[must_use]
fn from_explain_label(label: &str) -> Self {
match label {
"scan" => Self::Scan,
"aggregate" => Self::Aggregate,
"terminal" => Self::Terminal,
_ => Self::Pipeline,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct ExecutionNodeIdentity {
node_id: u64,
node_type: &'static str,
layer: ExecutionNodeLayer,
}
impl ExecutionNodeIdentity {
#[must_use]
const fn new(node_id: u64, node_type: &'static str, layer: ExecutionNodeLayer) -> Self {
Self {
node_id,
node_type,
layer,
}
}
#[must_use]
fn from_explain_node(node_id: u64, node: &ExplainExecutionNodeDescriptor) -> Self {
Self {
node_id,
node_type: node.node_type().as_str(),
layer: ExecutionNodeLayer::from_explain_label(node.node_type().layer_label()),
}
}
#[must_use]
const fn node_id(self) -> u64 {
self.node_id
}
#[must_use]
const fn node_type(self) -> &'static str {
self.node_type
}
#[must_use]
const fn layer(self) -> ExecutionNodeLayer {
self.layer
}
}
#[must_use]
fn collect_execution_node_identities(
root: &ExplainExecutionNodeDescriptor,
) -> Vec<ExecutionNodeIdentity> {
let mut identities = Vec::new();
let mut next_node_id = 0_u64;
root.for_each_preorder(&mut |node| {
let node_id = next_node_id;
next_node_id = next_node_id.saturating_add(1);
identities.push(ExecutionNodeIdentity::from_explain_node(node_id, node));
});
identities
}
#[cfg(test)]
mod tests;