Skip to content
This repository has been archived by the owner on Sep 12, 2018. It is now read-only.

Commit

Permalink
Add fulltext algebrizing tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Newman committed Jun 14, 2017
1 parent 647d9d7 commit 8ff5583
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 3 deletions.
102 changes: 102 additions & 0 deletions query-algebrizer/tests/fulltext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

extern crate mentat_core;
extern crate mentat_query;
extern crate mentat_query_algebrizer;
extern crate mentat_query_parser;

use mentat_core::{
Attribute,
Entid,
Schema,
ValueType,
};

use mentat_query_parser::{
parse_find_string,
};

use mentat_query::{
NamespacedKeyword,
};

use mentat_query_algebrizer::{
ConjoiningClauses,
algebrize,
};


// These are helpers that tests use to build Schema instances.
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
schema.entid_map.insert(e, i.clone());
schema.ident_map.insert(i.clone(), e);
}

fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
schema.schema_map.insert(e, a);
}

fn prepopulated_schema() -> Schema {
let mut schema = Schema::default();
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
associate_ident(&mut schema, NamespacedKeyword::new("foo", "description"), 66);
associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67);
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
add_attribute(&mut schema, 65, Attribute {
value_type: ValueType::String,
multival: false,
..Default::default()
});
add_attribute(&mut schema, 66, Attribute {
value_type: ValueType::String,
fulltext: true,
multival: true,
..Default::default()
});
add_attribute(&mut schema, 67, Attribute {
value_type: ValueType::String,
multival: true,
..Default::default()
});
add_attribute(&mut schema, 68, Attribute {
value_type: ValueType::Long,
multival: false,
..Default::default()
});
add_attribute(&mut schema, 69, Attribute {
value_type: ValueType::Long,
multival: false,
..Default::default()
});
schema
}

fn alg(schema: &Schema, input: &str) -> ConjoiningClauses {
let parsed = parse_find_string(input).expect("query input to have parsed");
algebrize(schema.into(), parsed).expect("algebrizing to have succeeded").cc
}

#[test]
fn test_apply_fulltext() {
let schema = prepopulated_schema();

// If you use a non-FTS attribute, we will short-circuit.
let query = r#"[:find ?val
:where [(fulltext $ :foo/name "hello") [[?entity ?val _ _]]]]"#;
assert!(alg(&schema, query).is_known_empty());

// If you get a type mismatch, we will short-circuit.
let query = r#"[:find ?val
:where [(fulltext $ :foo/description "hello") [[?entity ?val ?tx ?score]]]
[?score :foo/bar _]]"#;
assert!(alg(&schema, query).is_known_empty());
}
65 changes: 62 additions & 3 deletions query-translator/tests/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ extern crate mentat_query_parser;
extern crate mentat_query_translator;
extern crate mentat_sql;

use std::collections::BTreeMap;

use std::rc::Rc;

use mentat_query::{
Expand Down Expand Up @@ -818,14 +820,71 @@ fn test_fulltext_inputs() {
// Bind ?entity. We expect the output to collide.
let query = r#"[:find ?val
:in ?entity
:where [(fulltext $ :foo/bar "hello") [[?entity ?val _ _]]]]"#;
let SQLQuery { sql, args } = translate(&schema, query);
:where [(fulltext $ :foo/fts "hello") [[?entity ?val _ _]]]]"#;
let mut types = BTreeMap::default();
types.insert(Variable::from_valid_name("?entity"), ValueType::Ref);
let inputs = QueryInputs::new(types, BTreeMap::default()).expect("valid inputs");

// Without binding the value. q_once will err if you try this!
let SQLQuery { sql, args } = translate_with_inputs(&schema, query, inputs);
assert_eq!(sql, "SELECT DISTINCT `fulltext_values00`.text AS `?val` \
FROM \
`fulltext_values` AS `fulltext_values00`, \
`datoms` AS `datoms01` \
WHERE `datoms01`.a = 99 \
WHERE `datoms01`.a = 100 \
AND `datoms01`.v = `fulltext_values00`.rowid \
AND `fulltext_values00`.text MATCH $v0");
assert_eq!(args, vec![make_arg("$v0", "hello"),]);

// With the value bound.
let inputs = QueryInputs::with_value_sequence(vec![(Variable::from_valid_name("?entity"), TypedValue::Ref(111))]);
let SQLQuery { sql, args } = translate_with_inputs(&schema, query, inputs);
assert_eq!(sql, "SELECT DISTINCT `fulltext_values00`.text AS `?val` \
FROM \
`fulltext_values` AS `fulltext_values00`, \
`datoms` AS `datoms01` \
WHERE `datoms01`.a = 100 \
AND `datoms01`.v = `fulltext_values00`.rowid \
AND `fulltext_values00`.text MATCH $v0 \
AND `datoms01`.e = 111");
assert_eq!(args, vec![make_arg("$v0", "hello"),]);

// Same again, but retrieving the entity.
let query = r#"[:find ?entity .
:in ?entity
:where [(fulltext $ :foo/fts "hello") [[?entity _ _]]]]"#;
let inputs = QueryInputs::with_value_sequence(vec![(Variable::from_valid_name("?entity"), TypedValue::Ref(111))]);
let SQLQuery { sql, args } = translate_with_inputs(&schema, query, inputs);
assert_eq!(sql, "SELECT 111 AS `?entity` FROM \
`fulltext_values` AS `fulltext_values00`, \
`datoms` AS `datoms01` \
WHERE `datoms01`.a = 100 \
AND `datoms01`.v = `fulltext_values00`.rowid \
AND `fulltext_values00`.text MATCH $v0 \
AND `datoms01`.e = 111 \
LIMIT 1");
assert_eq!(args, vec![make_arg("$v0", "hello"),]);

// A larger pattern.
let query = r#"[:find ?entity ?value ?friend
:in ?entity
:where
[(fulltext $ :foo/fts "hello") [[?entity ?value]]]
[?entity :foo/bar ?friend]]"#;
let inputs = QueryInputs::with_value_sequence(vec![(Variable::from_valid_name("?entity"), TypedValue::Ref(121))]);
let SQLQuery { sql, args } = translate_with_inputs(&schema, query, inputs);
assert_eq!(sql, "SELECT DISTINCT 121 AS `?entity`, \
`fulltext_values00`.text AS `?value`, \
`datoms02`.v AS `?friend` \
FROM \
`fulltext_values` AS `fulltext_values00`, \
`datoms` AS `datoms01`, \
`datoms` AS `datoms02` \
WHERE `datoms01`.a = 100 \
AND `datoms01`.v = `fulltext_values00`.rowid \
AND `fulltext_values00`.text MATCH $v0 \
AND `datoms01`.e = 121 \
AND `datoms02`.e = 121 \
AND `datoms02`.a = 99");
assert_eq!(args, vec![make_arg("$v0", "hello"),]);
}

0 comments on commit 8ff5583

Please sign in to comment.