Attempt to resolve `tasks` for a cloned collection. Returns `None` when the collection has no clone origin (fast path: zero overhead). Returns `Some(ResolveOutcome)` when resolution is required.
(
state: &Arc<SharedState>,
tasks: Vec<PhysicalTask>,
tenant_id: TenantId,
params: &CloneReadParams,
)
| 51 | /// Returns `None` when the collection has no clone origin (fast path: zero |
| 52 | /// overhead). Returns `Some(ResolveOutcome)` when resolution is required. |
| 53 | pub fn resolve_read( |
| 54 | state: &Arc<SharedState>, |
| 55 | tasks: Vec<PhysicalTask>, |
| 56 | tenant_id: TenantId, |
| 57 | params: &CloneReadParams, |
| 58 | ) -> crate::Result<Option<ResolveOutcome>> { |
| 59 | // Quick-check: do any tasks target a database other than the default? |
| 60 | // All tasks in a statement share the same database_id (single-database |
| 61 | // statements); use the first task's database_id. |
| 62 | let Some(first_task) = tasks.first() else { |
| 63 | return Ok(None); |
| 64 | }; |
| 65 | let db_id = first_task.database_id; |
| 66 | |
| 67 | // Retrieve catalog for lookup. |
| 68 | let catalog_arc = state.credentials.catalog(); |
| 69 | let Some(catalog) = catalog_arc.as_ref() else { |
| 70 | return Ok(None); |
| 71 | }; |
| 72 | |
| 73 | // Extract the collection name from the first read-type task. |
| 74 | let Some(raw_coll) = super::rewrite::extract_collection_from_plan(&first_task.plan) else { |
| 75 | return Ok(None); |
| 76 | }; |
| 77 | // Strip the database prefix that db_qualified() prepends, e.g. "1/users" → "users". |
| 78 | let coll_name = super::rewrite::strip_db_prefix(db_id, raw_coll); |
| 79 | |
| 80 | // Look up the stored collection descriptor. |
| 81 | let Some(desc) = catalog |
| 82 | .get_collection(db_id, tenant_id.as_u64(), coll_name) |
| 83 | .map_err(|e| crate::Error::Storage { |
| 84 | engine: "catalog".into(), |
| 85 | detail: format!("clone resolver: get_collection failed: {e}"), |
| 86 | })? |
| 87 | else { |
| 88 | return Ok(None); |
| 89 | }; |
| 90 | |
| 91 | // Short-circuit: not a clone or fully materialized. |
| 92 | let Some(ref origin) = desc.cloned_from else { |
| 93 | return Ok(None); |
| 94 | }; |
| 95 | match desc.clone_status { |
| 96 | CloneStatus::Materialized => return Ok(None), |
| 97 | CloneStatus::Shadowed | CloneStatus::Materializing { .. } => {} |
| 98 | } |
| 99 | |
| 100 | // Bitemporal correctness: check if T_lsn < clone_created_at. |
| 101 | if params.query_lsn < origin.clone_created_at { |
| 102 | return Ok(Some(ResolveOutcome::PreDatesClone( |
| 103 | ClonePredicatesNote::new(params.query_lsn, origin.clone_created_at), |
| 104 | ))); |
| 105 | } |
| 106 | |
| 107 | // Compute effective source LSN: min(T_lsn, as_of_lsn). |
| 108 | let effective_source_lsn = if params.query_lsn > origin.as_of_lsn { |
| 109 | origin.as_of_lsn |
| 110 | } else { |
no test coverage detected