diff --git a/src/executors.rs b/src/executors.rs index 1d99978..8633292 100644 --- a/src/executors.rs +++ b/src/executors.rs @@ -40,6 +40,18 @@ fn complement_helper( } } +fn view_port(core_id: &str, parameters: &CoreQueryParameters, bag: &Bag) -> mercator_db::ResultSet { + if let Some((low, high)) = parameters.view_port { + let vp = Bag::Inside(Shape::HyperRectangle( + bag.space().clone(), + vec![low.into(), high.into()], + )); + intersection(core_id, parameters, &vp, bag) + } else { + bag.execute(core_id, parameters) + } +} + fn distinct(core_id: &str, parameters: &CoreQueryParameters, bag: &Bag) -> mercator_db::ResultSet { match bag.execute(core_id, parameters) { e @ Err(_) => e, @@ -282,6 +294,7 @@ impl Executor for Bag { let core = parameters.db.core(core_id)?; match self { + Bag::ViewPort(bag) => view_port(core_id, parameters, bag), Bag::Distinct(bag) => distinct(core_id, parameters, bag), Bag::Filter(predicate, bag) => filter(core_id, parameters, predicate, bag), Bag::Complement(bag) => complement(core_id, parameters, core, bag), diff --git a/src/main.rs b/src/main.rs index 37eb6ba..b287394 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ fn main() { db: &db, output_space: None, threshold_volume: None, + view_port: &None, resolution: None, }; let parser = QueryParser::new(); @@ -51,7 +52,7 @@ fn main() { } info_time!("Interpretation"); - let mut parse; + let parse; { info_time!("Parsing"); parse = parser.parse(&input); diff --git a/src/predictors.rs b/src/predictors.rs index 706e890..e1d0109 100644 --- a/src/predictors.rs +++ b/src/predictors.rs @@ -15,6 +15,7 @@ impl Predictor for Projection { impl Predictor for Bag { fn predict(&self, db: &DataBase) -> Result { match self { + Bag::ViewPort(bag) => bag.predict(db), Bag::Distinct(bag) => bag.predict(db), Bag::Filter(_, bag) => bag.predict(db), Bag::Complement(bag) => Ok(db.space(bag.space())?.volume() - bag.predict(db)?), diff --git a/src/queries.lalrpop b/src/queries.lalrpop index 9c42795..b54fbc2 100644 --- a/src/queries.lalrpop +++ b/src/queries.lalrpop @@ -135,7 +135,10 @@ Aggregations: symbols::Aggregation = { //*********************************************************************/ // SELECTING / FILTERING DATA */ //*********************************************************************/ -pub Filters = { Bags }; +pub Filters: symbols::Bag = { + => + symbols::Bag::ViewPort(Box::new(<>)) +}; // All these expressions generate bags. Bags: symbols::Bag = { diff --git a/src/symbols.rs b/src/symbols.rs index 5d9cfd4..24094c1 100644 --- a/src/symbols.rs +++ b/src/symbols.rs @@ -57,6 +57,9 @@ struct Transform { /**********************************************************************/ #[derive(Clone, Debug)] pub enum Bag { + // This is an implicit operator, inserted by the parser. Never to be used directly. + ViewPort(Box), + // Bags Distinct(Box), Filter(Option, Box), Complement(Box), @@ -72,6 +75,7 @@ pub enum Bag { impl Bag { pub fn space(&self) -> &String { match self { + Bag::ViewPort(bag) => bag.space(), Bag::Distinct(bag) => bag.space(), Bag::Filter(_, bag) => bag.space(), Bag::Complement(bag) => bag.space(), @@ -333,6 +337,17 @@ impl From<&LiteralPosition> for Vec { } } +impl From<&Vec> for LiteralPosition { + fn from(v: &Vec) -> Self { + let mut lv = Vec::with_capacity(v.len()); + for value in v { + lv.push(LiteralNumber::Float(*value)); + } + + LiteralPosition(lv) + } +} + impl PartialOrd for LiteralPosition { fn partial_cmp(&self, other: &LiteralPosition) -> Option { let LiteralPosition(lh) = self; diff --git a/src/validators.rs b/src/validators.rs index 69cfcc1..3b63858 100644 --- a/src/validators.rs +++ b/src/validators.rs @@ -54,6 +54,7 @@ impl Validator for Bag { } match self { + Bag::ViewPort(bag) => bag.validate(), Bag::Distinct(bag) => bag.validate(), Bag::Filter(_, bag) => bag.validate(), Bag::Complement(bag) => bag.validate(),