1use std::{collections::HashSet, sync::Arc};
21
22use datafusion::{
23 common::{DataFusionError, Result as DataFusionResult},
24 execution::context::TaskContext,
25 physical_plan::{ExecutionPlan, metrics::ExecutionPlanMetricsSet},
26};
27#[cfg(test)]
28use query_engine::exec::admit_query_plan;
29#[cfg(test)]
30use query_planning::{admission::AdmittedPlan, plan::QueryPlan};
31pub use query_planning::{
32 capability::{AggregateStrategyExecutionOptions, KeyedHashJoinStrategyOptions},
33 chunk::SourceChunkPlanningOptions,
34 correlation::{QueryId, TraceId},
35 dynamic_filter::DynamicFilterExecutionOptions,
36 execution_contracts::SourceChunkPlanningMode,
37 mode::StatisticalAggregateExecutionMode,
38 policy::PlanningPolicy,
39};
40pub use query_runtime::{
41 observability::{RuntimeObservationConfig, RuntimeObservationLimits},
42 runtime::{LakehouseCacheFillConfig, S3SourceStorageProfile, SourceSchedulerPolicy},
43};
44
45#[cfg(test)]
46use crate::error::Result;
47use crate::error::{Error, ErrorCode};
48
49#[cfg(test)]
51pub(crate) fn admit_for_test(
52 plan: &QueryPlan,
53 execution_config: &AlgeonNativeExecutionConfig,
54) -> Result<Arc<AdmittedPlan>> {
55 admit_query_plan(plan, execution_config.statistical_aggregate_execution_mode(), execution_config.planning_policy())
56 .map_err(|error| {
57 Error::from_native("algeon_datafusion.native_exec.test_admission", "test plan is not admissible", error)
58 })
59}
60
61#[cfg(test)]
62mod adapter_tests;
63pub(crate) mod admission;
64pub(crate) mod child_inputs;
65mod common;
66mod composed;
67mod config;
68mod fragment;
69pub(crate) mod graph;
70pub(crate) mod lakehouse;
71mod metrics;
72mod native_node;
73mod occurrence;
74mod producer;
75pub(crate) mod relation_function;
76mod shared_resident;
77
78pub(crate) use common::{NativeHostOutputCursor, native_host_output_stream, run_gpu_execution_task};
79
80#[cfg(feature = "cugraph")]
81#[cfg(feature = "cugraph")]
82pub(crate) use self::composed::composed_admission_capability_evidence;
83pub(crate) use self::{
84 admission::{QueryAdmissionSource, plan_is_query_admission_wrapped},
85 composed::producer_bound_capability_evidence,
86 fragment::NativeOutput,
87 metrics::{
88 AlgeonNativeMetrics, GraphClaimCalibrationCapture, NativeExecutionMetricsCapture, SealedAttemptMetricsTarget,
89 },
90 occurrence::{GpuFunctionHostOccurrenceExec, gpu_function_occurrence_from_task_context},
91 producer::{
92 GpuResidentProducer, execute_gpu_resident_producer_with_context, gpu_resident_producer,
93 gpu_resident_producer_hard_output_row_upper_bound, gpu_resident_producer_input_name,
94 gpu_resident_producer_unique_output_key, prepare_gpu_resident_producer_for_execution,
95 prepared_gpu_resident_producer_admission_tickets, rewrite_gpu_resident_producer_for_subsumed_composed_consumer,
96 },
97};
98pub use self::{
99 config::{AlgeonNativeExecutionConfig, LakehouseByteCache, LakehouseByteCacheFill, SourceChunking},
100 fragment::AlgeonNativeExec,
101 metrics::{
102 GraphClaimCalibrationExecution, GraphClaimCalibrationNonPhysicalReason, NATIVE_ALGEON_DATAFUSION_METRIC_NAMES,
103 SERVER_CAPTURE_LOSS_METRIC_NAME, SealedAttemptGraphClaimCalibrationSnapshot,
104 },
105};
106
107pub fn below_native_admission(plan: &Arc<dyn ExecutionPlan>) -> &Arc<dyn ExecutionPlan> {
110 match native_node::native_node(plan.as_ref()) {
111 Some(native_node::NativeNode::Admission(node)) => node.input(),
112 _ => plan,
113 }
114}
115
116pub(crate) fn transparent_root_wrapper_input(plan: &dyn ExecutionPlan) -> Option<&Arc<dyn ExecutionPlan>> {
119 native_node::native_node(plan).and_then(|node| node.transparent_root_wrapper_input())
120}
121
122pub(crate) fn validate_host_wrapped_gpu_execution(
125 plan: &dyn ExecutionPlan,
126 task_context: &TaskContext,
127) -> DataFusionResult<()> {
128 let ticket = admission::invocation_admission_ticket(task_context)
129 .filter(|ticket| ticket.has_execution_manifest())
130 .ok_or_else(|| {
131 DataFusionError::from(
132 Error::new(
133 ErrorCode::InvalidExecutionPlan,
134 "algeon_datafusion.native_exec.host_input_staging",
135 "host staging cannot execute a GPU descendant without a final-plan occurrence manifest",
136 )
137 .with_log_safe_fact("reason", "host_wrapped_gpu_occurrence_manifest_missing"),
138 )
139 })?;
140
141 fn validate(plan: &dyn ExecutionPlan, ticket: &Arc<admission::QueryAdmissionTicket>) -> DataFusionResult<bool> {
142 if let Some(producer) = gpu_resident_producer(plan) {
143 let host_plan = producer.host_result_query_plan()?.ok_or_else(|| {
144 DataFusionError::from(
145 Error::new(
146 ErrorCode::InvalidExecutionPlan,
147 "algeon_datafusion.native_exec.host_input_staging",
148 "a host-wrapped GPU producer does not expose its host execution identity",
149 )
150 .with_log_safe_fact("reason", "host_wrapped_gpu_occurrence_identity_missing")
151 .with_log_safe_fact("occurrence_id", producer.gpu_result_input_name()),
152 )
153 })?;
154 ticket.validate_host_occurrence(producer.gpu_result_input_name(), &host_plan)?.ok_or_else(|| {
155 DataFusionError::from(
156 Error::new(
157 ErrorCode::InvalidExecutionPlan,
158 "algeon_datafusion.native_exec.host_input_staging",
159 "a host-wrapped GPU producer is not covered by the final-plan occurrence manifest",
160 )
161 .with_log_safe_fact("reason", "host_wrapped_gpu_occurrence_not_admitted")
162 .with_log_safe_fact("occurrence_id", producer.gpu_result_input_name()),
163 )
164 })?;
165 return Ok(true);
166 }
167 let mut found = false;
168 for child in plan.children() {
169 found |= validate(child.as_ref(), ticket)?;
170 }
171 Ok(found)
172 }
173
174 if !validate(plan, &ticket)? {
175 return Err(Error::new(
176 ErrorCode::InvalidExecutionPlan,
177 "algeon_datafusion.native_exec.host_input_staging",
178 "a host-wrapped native subtree has no admitted GPU function occurrence",
179 )
180 .with_log_safe_fact("reason", "host_wrapped_gpu_occurrence_identity_missing")
181 .into());
182 }
183 Ok(())
184}
185
186pub(crate) fn sealed_attempt_metrics_target(plan: &dyn ExecutionPlan) -> Option<SealedAttemptMetricsTarget> {
192 if let Some(exec) = plan.downcast_ref::<AlgeonNativeExec>()
193 && exec.materializes_host()
194 {
195 return Some(exec.sealed_attempt_metrics_target());
196 }
197 if let Some(exec) = graph::graph_execution_plan(plan) {
198 return Some(exec.sealed_attempt_metrics_target());
199 }
200 if let Some(input) = transparent_root_wrapper_input(plan) {
201 return sealed_attempt_metrics_target(input.as_ref());
202 }
203 let descendant = plan.children().into_iter().find_map(|child| sealed_attempt_metrics_target(child.as_ref()));
204 if let Some(metrics) = gpu_resident_producer(plan).and_then(GpuResidentProducer::execution_metrics) {
209 let captures = descendant.iter().flat_map(SealedAttemptMetricsTarget::graph_claim_calibration_captures);
210 return Some(
211 SealedAttemptMetricsTarget::new(metrics, GraphClaimCalibrationCapture::default())
212 .with_graph_claim_calibration_captures(captures),
213 );
214 }
215 descendant
216}
217
218pub(crate) fn native_execution_metrics(plan: &dyn ExecutionPlan) -> Vec<ExecutionPlanMetricsSet> {
224 fn visit(plan: &dyn ExecutionPlan, seen: &mut HashSet<*const ()>, sets: &mut Vec<ExecutionPlanMetricsSet>) {
225 if !seen.insert(std::ptr::from_ref(plan).cast::<()>()) {
227 return;
228 }
229 sets.extend(native_execution_wrapper_metrics(plan).cloned());
230 for child in plan.children() {
231 visit(child.as_ref(), seen, sets);
232 }
233 }
234
235 let mut sets = Vec::new();
236 visit(plan, &mut HashSet::new(), &mut sets);
237 sets
238}
239
240#[cfg(feature = "server")]
242pub(crate) fn contains_native_execution_wrapper(plan: &dyn ExecutionPlan) -> bool {
243 native_execution_wrapper_metrics(plan).is_some()
244 || plan.children().into_iter().any(|child| contains_native_execution_wrapper(child.as_ref()))
245}
246
247fn native_execution_wrapper_metrics(plan: &dyn ExecutionPlan) -> Option<&ExecutionPlanMetricsSet> {
248 if let Some(exec) = plan.downcast_ref::<AlgeonNativeExec>() {
249 return Some(exec.execution_metrics());
250 }
251 gpu_resident_producer(plan).and_then(GpuResidentProducer::execution_metrics)
252}