Part 7: use RcCounter to implement aliasing in ConjoiningClauses.
This allows us to share a counter between templates produced from a CC.
This commit is contained in:
parent
2b61944f09
commit
e280811243
1 changed files with 30 additions and 18 deletions
|
@ -29,6 +29,8 @@ use mentat_core::{
|
||||||
ValueType,
|
ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use mentat_core::counter::RcCounter;
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
NamespacedKeyword,
|
||||||
NonIntegerConstant,
|
NonIntegerConstant,
|
||||||
|
@ -73,18 +75,6 @@ impl<T: Clone> RcCloned<T> for ::std::rc::Rc<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A thing that's capable of aliasing a table name for us.
|
|
||||||
/// This exists so that we can obtain predictable names in tests.
|
|
||||||
pub type TableAliaser = Box<FnMut(DatomsTable) -> TableAlias>;
|
|
||||||
|
|
||||||
pub fn default_table_aliaser() -> TableAliaser {
|
|
||||||
let mut i = -1;
|
|
||||||
Box::new(move |table| {
|
|
||||||
i += 1;
|
|
||||||
format!("{}{:02}", table.name(), i)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unit_type_set(t: ValueType) -> HashSet<ValueType> {
|
fn unit_type_set(t: ValueType) -> HashSet<ValueType> {
|
||||||
let mut s = HashSet::with_capacity(1);
|
let mut s = HashSet::with_capacity(1);
|
||||||
s.insert(t);
|
s.insert(t);
|
||||||
|
@ -145,8 +135,8 @@ pub struct ConjoiningClauses {
|
||||||
/// `Some` if this set of clauses cannot yield results in the context of the current schema.
|
/// `Some` if this set of clauses cannot yield results in the context of the current schema.
|
||||||
pub empty_because: Option<EmptyBecause>,
|
pub empty_because: Option<EmptyBecause>,
|
||||||
|
|
||||||
/// A function used to generate an alias for a table -- e.g., from "datoms" to "datoms123".
|
/// A data source used to generate an alias for a table -- e.g., from "datoms" to "datoms123".
|
||||||
aliaser: TableAliaser,
|
alias_counter: RcCounter,
|
||||||
|
|
||||||
/// A vector of source/alias pairs used to construct a SQL `FROM` list.
|
/// A vector of source/alias pairs used to construct a SQL `FROM` list.
|
||||||
pub from: Vec<SourceAlias>,
|
pub from: Vec<SourceAlias>,
|
||||||
|
@ -204,7 +194,7 @@ impl Default for ConjoiningClauses {
|
||||||
fn default() -> ConjoiningClauses {
|
fn default() -> ConjoiningClauses {
|
||||||
ConjoiningClauses {
|
ConjoiningClauses {
|
||||||
empty_because: None,
|
empty_because: None,
|
||||||
aliaser: default_table_aliaser(),
|
alias_counter: RcCounter::new(),
|
||||||
from: vec![],
|
from: vec![],
|
||||||
wheres: ColumnIntersection::default(),
|
wheres: ColumnIntersection::default(),
|
||||||
input_variables: BTreeSet::new(),
|
input_variables: BTreeSet::new(),
|
||||||
|
@ -231,10 +221,10 @@ impl ConjoiningClauses {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make a new CC populated with the relevant variable associations in this CC.
|
/// Make a new CC populated with the relevant variable associations in this CC.
|
||||||
/// Note that the CC's table aliaser is not yet usable. That's not a problem for templating for
|
/// The CC shares an alias count with all of its copies.
|
||||||
/// simple `or`.
|
|
||||||
fn use_as_template(&self, vars: &BTreeSet<Variable>) -> ConjoiningClauses {
|
fn use_as_template(&self, vars: &BTreeSet<Variable>) -> ConjoiningClauses {
|
||||||
let mut template = ConjoiningClauses::default();
|
let mut template = ConjoiningClauses::default();
|
||||||
|
template.alias_counter = self.alias_counter.clone(); // Rc ftw.
|
||||||
template.empty_because = self.empty_because.clone();
|
template.empty_because = self.empty_because.clone();
|
||||||
|
|
||||||
template.input_variables = self.input_variables.intersection(vars).cloned().collect();
|
template.input_variables = self.input_variables.intersection(vars).cloned().collect();
|
||||||
|
@ -586,6 +576,10 @@ impl ConjoiningClauses {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_alias_for_table(&mut self, table: DatomsTable) -> TableAlias {
|
||||||
|
format!("{}{:02}", table.name(), self.alias_counter.next())
|
||||||
|
}
|
||||||
|
|
||||||
/// Produce a (table, alias) pair to handle the provided pattern.
|
/// Produce a (table, alias) pair to handle the provided pattern.
|
||||||
/// This is a mutating method because it mutates the aliaser function!
|
/// This is a mutating method because it mutates the aliaser function!
|
||||||
/// Note that if this function decides that a pattern cannot match, it will flip
|
/// Note that if this function decides that a pattern cannot match, it will flip
|
||||||
|
@ -595,7 +589,7 @@ impl ConjoiningClauses {
|
||||||
.map_err(|reason| {
|
.map_err(|reason| {
|
||||||
self.mark_known_empty(reason);
|
self.mark_known_empty(reason);
|
||||||
})
|
})
|
||||||
.map(|table| SourceAlias(table, (self.aliaser)(table)))
|
.map(|table: DatomsTable| SourceAlias(table, self.next_alias_for_table(table)))
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,4 +728,22 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
pub fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
||||||
PatternNonValuePlace::Ident(::std::rc::Rc::new(NamespacedKeyword::new(ns, name)))
|
PatternNonValuePlace::Ident(::std::rc::Rc::new(NamespacedKeyword::new(ns, name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Our alias counter is shared between CCs.
|
||||||
|
#[test]
|
||||||
|
fn test_aliasing_through_template() {
|
||||||
|
let mut starter = ConjoiningClauses::default();
|
||||||
|
let alias_zero = starter.next_alias_for_table(DatomsTable::Datoms);
|
||||||
|
let mut first = starter.use_as_template(&BTreeSet::new());
|
||||||
|
let mut second = starter.use_as_template(&BTreeSet::new());
|
||||||
|
let alias_one = first.next_alias_for_table(DatomsTable::Datoms);
|
||||||
|
let alias_two = second.next_alias_for_table(DatomsTable::Datoms);
|
||||||
|
assert!(alias_zero != alias_one);
|
||||||
|
assert!(alias_one != alias_two);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue