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.
This commit is contained in:
2019-10-15 19:45:44 +02:00
parent 927feb0297
commit 661abbc9f4
6 changed files with 36 additions and 2 deletions

View File

@@ -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),

View File

@@ -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);

View File

@@ -15,6 +15,7 @@ impl Predictor for Projection {
impl Predictor for Bag {
fn predict(&self, db: &DataBase) -> Result<f64, String> {
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)?),

View File

@@ -135,7 +135,10 @@ Aggregations: symbols::Aggregation = {
//*********************************************************************/
// SELECTING / FILTERING DATA */
//*********************************************************************/
pub Filters = { Bags };
pub Filters: symbols::Bag = {
<Bags> =>
symbols::Bag::ViewPort(Box::new(<>))
};
// All these expressions generate bags.
Bags: symbols::Bag = {

View File

@@ -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<Bag>),
// Bags
Distinct(Box<Bag>),
Filter(Option<Predicate>, Box<Bag>),
Complement(Box<Bag>),
@@ -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<f64> {
}
}
impl From<&Vec<f64>> for LiteralPosition {
fn from(v: &Vec<f64>) -> 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<Ordering> {
let LiteralPosition(lh) = self;

View File

@@ -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(),