use std::sync::Arc;
use uqa_execution::{PhysicalRow, RowSchema};
use uqa_storage::document_store::Document;
#[derive(Clone)]
pub(in crate::sql) struct RecheckDoc {
pub doc_id: uqa_core::DocId,
pub document: Option<Arc<Document>>,
}
pub(in crate::sql) struct RowLockRecheckPins {
targets: Vec<TargetPins>,
source_rows: Vec<SourceRowPin>,
}
struct TargetPins {
qualifier: String,
storage_name: String,
scan_qualifier: String,
identity_source: bool,
docs: Arc<Vec<RecheckDoc>>,
}
#[derive(Clone)]
pub(in crate::sql) struct RecheckSourceRow {
pub schema: RowSchema,
pub row: PhysicalRow,
pub qualifier: String,
}
struct SourceRowPin {
path: Box<[u8]>,
source: RecheckSourceRow,
}
impl RowLockRecheckPins {
pub(in crate::sql) fn new() -> Self {
Self {
targets: Vec::new(),
source_rows: Vec::new(),
}
}
pub(in crate::sql) fn pin_source_row(
&mut self,
path: Vec<u8>,
qualifier: String,
schema: RowSchema,
row: PhysicalRow,
) {
self.source_rows.push(SourceRowPin {
path: path.into_boxed_slice(),
source: RecheckSourceRow {
schema,
row,
qualifier,
},
});
}
pub(in crate::sql) fn source_row(&self, path: &[u8]) -> Option<RecheckSourceRow> {
self.source_rows
.iter()
.find(|pin| pin.path.as_ref() == path)
.map(|pin| pin.source.clone())
}
pub(in crate::sql) fn pin_target(
&mut self,
qualifier: &str,
storage_name: &str,
scan_qualifier: &str,
identity_source: bool,
docs: Vec<RecheckDoc>,
) {
if let Some(target) = self.targets.iter_mut().find(|target| {
target.qualifier == qualifier
&& target.storage_name == storage_name
&& target.scan_qualifier == scan_qualifier
&& target.identity_source == identity_source
}) {
for doc in docs {
if !target
.docs
.iter()
.any(|existing| existing.doc_id == doc.doc_id)
{
Arc::make_mut(&mut target.docs).push(doc);
}
}
return;
}
self.targets.push(TargetPins {
qualifier: qualifier.to_string(),
storage_name: storage_name.to_string(),
scan_qualifier: scan_qualifier.to_string(),
identity_source,
docs: Arc::new(docs),
});
}
pub(in crate::sql) fn docs_for_scan(
&self,
qualifier: &str,
storage_name: &str,
) -> Option<Arc<Vec<RecheckDoc>>> {
self.targets
.iter()
.find(|target| {
!target.identity_source
&& target.qualifier == qualifier
&& recheck_storage_names_match(&target.storage_name, storage_name)
})
.map(|target| Arc::clone(&target.docs))
}
pub(in crate::sql) fn storage_pins_for_identity_source(
&self,
qualifier: &str,
) -> Vec<(String, String, Arc<Vec<RecheckDoc>>)> {
self.targets
.iter()
.filter(|target| target.identity_source && target.qualifier == qualifier)
.map(|target| {
(
target.storage_name.clone(),
target.scan_qualifier.clone(),
Arc::clone(&target.docs),
)
})
.collect()
}
}
pub(in crate::sql) fn recheck_storage_names_match(left: &str, right: &str) -> bool {
if left == right {
return true;
}
match (left.rsplit_once('.'), right.rsplit_once('.')) {
(Some((_, left_local)), None) => left_local == right,
(None, Some((_, right_local))) => left == right_local,
(None, None) | (Some(_), Some(_)) => false,
}
}