From 661abbc9f4a98aef40214ee37cd4b9afd3b3a5e9 Mon Sep 17 00:00:00 2001 From: Lionel Sambuc Date: Tue, 15 Oct 2019 19:45:44 +0200 Subject: [PATCH] Add a new symbol, ViewPort This is used to wrap the filters within an implicit bounding box, which corresponds to the view port optionally provided by the users. The intersection is automatically computed between the query results and the ViewPort, whenever it is specified. --- src/executors.rs | 13 +++++++++++++ src/main.rs | 3 ++- src/predictors.rs | 1 + src/queries.lalrpop | 5 ++++- src/symbols.rs | 15 +++++++++++++++ src/validators.rs | 1 + 6 files changed, 36 insertions(+), 2 deletions(-) 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(),