2017-02-22 03:57:00 +00:00
// 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 ;
extern crate mentat_query_translator ;
extern crate mentat_sql ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
use std ::rc ::Rc ;
2017-02-22 03:57:00 +00:00
use mentat_query ::NamespacedKeyword ;
use mentat_core ::{
Attribute ,
Entid ,
Schema ,
ValueType ,
} ;
use mentat_query_parser ::parse_find_string ;
use mentat_query_algebrizer ::algebrize ;
use mentat_query_translator ::{
2017-03-06 22:40:10 +00:00
query_to_select ,
2017-02-22 03:57:00 +00:00
} ;
use mentat_sql ::SQLQuery ;
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 ) ;
}
2017-03-07 04:18:38 +00:00
fn translate < T : Into < Option < u64 > > > ( schema : & Schema , input : & 'static str , limit : T ) -> SQLQuery {
let parsed = parse_find_string ( input ) . expect ( " parse failed " ) ;
2017-03-16 19:23:48 +00:00
let mut algebrized = algebrize ( schema , parsed ) . expect ( " algebrize failed " ) ;
2017-03-07 04:18:38 +00:00
algebrized . apply_limit ( limit . into ( ) ) ;
let select = query_to_select ( algebrized ) ;
select . query . to_sql_query ( ) . unwrap ( )
}
2017-04-04 21:54:08 +00:00
fn prepopulated_typed_schema ( foo_type : ValueType ) -> Schema {
2017-03-06 22:40:10 +00:00
let mut schema = Schema ::default ( ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " foo " , " bar " ) , 99 ) ;
add_attribute ( & mut schema , 99 , Attribute {
2017-04-04 21:54:08 +00:00
value_type : foo_type ,
2017-03-06 22:40:10 +00:00
.. Default ::default ( )
} ) ;
2017-03-22 21:02:00 +00:00
schema
}
2017-04-04 21:54:08 +00:00
fn prepopulated_schema ( ) -> Schema {
prepopulated_typed_schema ( ValueType ::String )
}
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
fn make_arg ( name : & 'static str , value : & 'static str ) -> ( String , Rc < String > ) {
( name . to_string ( ) , Rc ::new ( value . to_string ( ) ) )
}
2017-03-22 21:02:00 +00:00
#[ test ]
fn test_scalar ( ) {
let schema = prepopulated_schema ( ) ;
let input = r # "[:find ?x . :where [?x :foo/bar "yyy"]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v = $v0 LIMIT 1 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " yyy " ) ] ) ;
2017-03-22 21:02:00 +00:00
}
#[ test ]
fn test_tuple ( ) {
let schema = prepopulated_schema ( ) ;
let input = r # "[:find [?x] :where [?x :foo/bar "yyy"]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v = $v0 LIMIT 1 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " yyy " ) ] ) ;
2017-03-22 21:02:00 +00:00
}
#[ test ]
fn test_coll ( ) {
let schema = prepopulated_schema ( ) ;
2017-03-06 22:40:10 +00:00
let input = r # "[:find [?x ...] :where [?x :foo/bar "yyy"]]"# ;
2017-03-07 04:18:38 +00:00
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v = $v0 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " yyy " ) ] ) ;
2017-03-06 22:40:10 +00:00
}
#[ test ]
fn test_rel ( ) {
2017-03-22 21:02:00 +00:00
let schema = prepopulated_schema ( ) ;
2017-02-22 03:57:00 +00:00
let input = r # "[:find ?x :where [?x :foo/bar "yyy"]]"# ;
2017-03-07 04:18:38 +00:00
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v = $v0 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " yyy " ) ] ) ;
2017-02-22 03:57:00 +00:00
}
2017-03-07 00:27:13 +00:00
#[ test ]
fn test_limit ( ) {
2017-03-22 21:02:00 +00:00
let schema = prepopulated_schema ( ) ;
2017-03-07 00:27:13 +00:00
let input = r # "[:find ?x :where [?x :foo/bar "yyy"]]"# ;
2017-03-07 04:18:38 +00:00
let SQLQuery { sql , args } = translate ( & schema , input , 5 ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v = $v0 LIMIT 5 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " yyy " ) ] ) ;
2017-03-07 00:27:13 +00:00
}
2017-03-07 04:18:38 +00:00
#[ test ]
fn test_unknown_attribute_keyword_value ( ) {
let schema = Schema ::default ( ) ;
let input = r # "[:find ?x :where [?x _ :ab/yyy]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
// Only match keywords, not strings: tag = 13.
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.v = $v0 AND `datoms00`.value_type_tag = 13 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " :ab/yyy " ) ] ) ;
2017-03-07 04:18:38 +00:00
}
#[ test ]
fn test_unknown_attribute_string_value ( ) {
let schema = Schema ::default ( ) ;
let input = r # "[:find ?x :where [?x _ "horses"]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
// We expect all_datoms because we're querying for a string. Magic, that.
// We don't want keywords etc., so tag = 10.
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `all_datoms00`.e AS `?x` FROM `all_datoms` AS `all_datoms00` WHERE `all_datoms00`.v = $v0 AND `all_datoms00`.value_type_tag = 10 " ) ;
Use Rc for TypedValue, Variable, and query Ident keywords. (#395) r=nalexander
Part 1, core: use Rc for String and Keyword.
Part 2, query: use Rc for Variable.
Part 3, sql: use Rc for args in SQLiteQueryBuilder.
Part 4, query-algebrizer: use Rc.
Part 5, db: use Rc.
Part 6, query-parser: use Rc.
Part 7, query-projector: use Rc.
Part 8, query-translator: use Rc.
Part 9, top level: use Rc.
Part 10: intern Ident and IdentOrKeyword.
2017-03-29 20:18:17 +00:00
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " horses " ) ] ) ;
2017-03-07 04:18:38 +00:00
}
#[ test ]
fn test_unknown_attribute_double_value ( ) {
let schema = Schema ::default ( ) ;
let input = r # "[:find ?x :where [?x _ 9.95]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
// In general, doubles _could_ be 1.0, which might match a boolean or a ref. Set tag = 5 to
// make sure we only match numbers.
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.v = 9.95 AND `datoms00`.value_type_tag = 5 " ) ;
2017-03-07 04:18:38 +00:00
assert_eq! ( args , vec! [ ] ) ;
}
#[ test ]
fn test_unknown_attribute_integer_value ( ) {
let schema = Schema ::default ( ) ;
let negative = r # "[:find ?x :where [?x _ -1]]"# ;
let zero = r # "[:find ?x :where [?x _ 0]]"# ;
let one = r # "[:find ?x :where [?x _ 1]]"# ;
let two = r # "[:find ?x :where [?x _ 2]]"# ;
// Can't match boolean; no need to filter it out.
let SQLQuery { sql , args } = translate ( & schema , negative , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.v = -1 " ) ;
2017-03-07 04:18:38 +00:00
assert_eq! ( args , vec! [ ] ) ;
// Excludes booleans.
let SQLQuery { sql , args } = translate ( & schema , zero , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE (`datoms00`.v = 0 AND `datoms00`.value_type_tag <> 1) " ) ;
2017-03-07 04:18:38 +00:00
assert_eq! ( args , vec! [ ] ) ;
// Excludes booleans.
let SQLQuery { sql , args } = translate ( & schema , one , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE (`datoms00`.v = 1 AND `datoms00`.value_type_tag <> 1) " ) ;
2017-03-07 04:18:38 +00:00
assert_eq! ( args , vec! [ ] ) ;
// Can't match boolean; no need to filter it out.
let SQLQuery { sql , args } = translate ( & schema , two , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.v = 2 " ) ;
2017-03-07 04:18:38 +00:00
assert_eq! ( args , vec! [ ] ) ;
}
#[ test ]
fn test_unknown_ident ( ) {
let schema = Schema ::default ( ) ;
let impossible = r # "[:find ?x :where [?x :db/ident :no/exist]]"# ;
let parsed = parse_find_string ( impossible ) . expect ( " parse failed " ) ;
2017-03-16 19:23:48 +00:00
let algebrized = algebrize ( & schema , parsed ) . expect ( " algebrize failed " ) ;
2017-03-07 04:18:38 +00:00
// This query cannot return results: the ident doesn't resolve for a ref-typed attribute.
assert! ( algebrized . is_known_empty ( ) ) ;
// If you insist…
let select = query_to_select ( algebrized ) ;
let sql = select . query . to_sql_query ( ) . unwrap ( ) . sql ;
assert_eq! ( " SELECT 1 LIMIT 0 " , sql ) ;
}
2017-03-16 19:23:48 +00:00
#[ test ]
fn test_numeric_less_than_unknown_attribute ( ) {
let schema = Schema ::default ( ) ;
let input = r # "[:find ?x :where [?x _ ?y] [(< ?y 10)]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
2017-03-20 14:11:32 +00:00
// Although we infer numericness from numeric predicates, we've already assigned a table to the
// first pattern, and so this is _still_ `all_datoms`.
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `all_datoms00`.e AS `?x` FROM `all_datoms` AS `all_datoms00` WHERE `all_datoms00`.v < 10 " ) ;
2017-03-16 19:23:48 +00:00
assert_eq! ( args , vec! [ ] ) ;
}
#[ test ]
fn test_numeric_gte_known_attribute ( ) {
2017-04-04 21:54:08 +00:00
let schema = prepopulated_typed_schema ( ValueType ::Double ) ;
2017-03-16 19:23:48 +00:00
let input = r # "[:find ?x :where [?x :foo/bar ?y] [(>= ?y 12.9)]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v >= 12.9 " ) ;
2017-03-16 19:23:48 +00:00
assert_eq! ( args , vec! [ ] ) ;
}
#[ test ]
fn test_numeric_not_equals_known_attribute ( ) {
2017-04-04 21:54:08 +00:00
let schema = prepopulated_typed_schema ( ValueType ::Long ) ;
2017-03-22 21:02:00 +00:00
let input = r # "[:find ?x . :where [?x :foo/bar ?y] [(!= ?y 12)]]"# ;
2017-03-16 19:23:48 +00:00
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
2017-03-22 21:02:00 +00:00
assert_eq! ( sql , " SELECT `datoms00`.e AS `?x` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 AND `datoms00`.v <> 12 LIMIT 1 " ) ;
2017-03-16 19:23:48 +00:00
assert_eq! ( args , vec! [ ] ) ;
2017-04-04 21:54:08 +00:00
}
#[ test ]
fn test_simple_or_join ( ) {
let mut schema = Schema ::default ( ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " url " ) , 97 ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " title " ) , 98 ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " description " ) , 99 ) ;
for x in 97 .. 100 {
add_attribute ( & mut schema , x , Attribute {
value_type : ValueType ::String ,
.. Default ::default ( )
} ) ;
}
let input = r #" [:find [?url ?description]
:where
( or - join [ ? page ]
[ ? page :page / url " http://foo.com/ " ]
[ ? page :page / title " Foo " ] )
[ ? page :page / url ? url ]
[ ? page :page / description ? description ] ] " #;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT `datoms01`.v AS `?url`, `datoms02`.v AS `?description` FROM `datoms` AS `datoms00`, `datoms` AS `datoms01`, `datoms` AS `datoms02` WHERE ((`datoms00`.a = 97 AND `datoms00`.v = $v0) OR (`datoms00`.a = 98 AND `datoms00`.v = $v1)) AND `datoms01`.a = 97 AND `datoms02`.a = 99 AND `datoms00`.e = `datoms01`.e AND `datoms00`.e = `datoms02`.e LIMIT 1 " ) ;
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " http://foo.com/ " ) , make_arg ( " $v1 " , " Foo " ) ] ) ;
}
2017-04-11 17:31:31 +00:00
#[ test ]
fn test_complex_or_join ( ) {
let mut schema = Schema ::default ( ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " save " ) , 95 ) ;
add_attribute ( & mut schema , 95 , Attribute {
value_type : ValueType ::Ref ,
.. Default ::default ( )
} ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " save " , " title " ) , 96 ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " url " ) , 97 ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " title " ) , 98 ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " description " ) , 99 ) ;
for x in 96 .. 100 {
add_attribute ( & mut schema , x , Attribute {
value_type : ValueType ::String ,
.. Default ::default ( )
} ) ;
}
let input = r #" [:find [?url ?description]
:where
( or - join [ ? page ]
[ ? page :page / url " http://foo.com/ " ]
[ ? page :page / title " Foo " ]
( and
[ ? page :page / save ? save ]
[ ? save :save / title " Foo " ] ) )
[ ? page :page / url ? url ]
[ ? page :page / description ? description ] ] " #;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT `datoms04`.v AS `?url`, \
` datoms05 ` . v AS ` ? description ` \
FROM ( SELECT ` datoms00 ` . e AS ` ? page ` \
FROM ` datoms ` AS ` datoms00 ` \
WHERE ` datoms00 ` . a = 97 \
AND ` datoms00 ` . v = $v0 \
UNION \
SELECT ` datoms01 ` . e AS ` ? page ` \
FROM ` datoms ` AS ` datoms01 ` \
WHERE ` datoms01 ` . a = 98 \
AND ` datoms01 ` . v = $v1 \
UNION \
SELECT ` datoms02 ` . e AS ` ? page ` \
FROM ` datoms ` AS ` datoms02 ` , \
` datoms ` AS ` datoms03 ` \
WHERE ` datoms02 ` . a = 95 \
AND ` datoms03 ` . a = 96 \
AND ` datoms03 ` . v = $v2 \
AND ` datoms02 ` . v = ` datoms03 ` . e ) AS ` c00 ` , \
` datoms ` AS ` datoms04 ` , \
` datoms ` AS ` datoms05 ` \
WHERE ` datoms04 ` . a = 97 \
AND ` datoms05 ` . a = 99 \
AND ` c00 ` . ` ? page ` = ` datoms04 ` . e \
AND ` c00 ` . ` ? page ` = ` datoms05 ` . e \
LIMIT 1 " );
assert_eq! ( args , vec! [ make_arg ( " $v0 " , " http://foo.com/ " ) ,
make_arg ( " $v1 " , " Foo " ) ,
make_arg ( " $v2 " , " Foo " ) ] ) ;
}
#[ test ]
fn test_complex_or_join_type_projection ( ) {
let mut schema = Schema ::default ( ) ;
associate_ident ( & mut schema , NamespacedKeyword ::new ( " page " , " title " ) , 98 ) ;
add_attribute ( & mut schema , 98 , Attribute {
value_type : ValueType ::String ,
.. Default ::default ( )
} ) ;
let input = r #" [:find [?y]
:where
( or
[ 6 :page / title ? y ]
[ 5 _ ? y ] ) ] " #;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT `c00`.`?y` AS `?y`, \
` c00 ` . ` ? y_value_type_tag ` AS ` ? y_value_type_tag ` \
FROM ( SELECT ` datoms00 ` . v AS ` ? y ` , \
10 AS ` ? y_value_type_tag ` \
FROM ` datoms ` AS ` datoms00 ` \
WHERE ` datoms00 ` . e = 6 \
AND ` datoms00 ` . a = 98 \
UNION \
SELECT ` all_datoms01 ` . v AS ` ? y ` , \
` all_datoms01 ` . value_type_tag AS ` ? y_value_type_tag ` \
FROM ` all_datoms ` AS ` all_datoms01 ` \
WHERE ` all_datoms01 ` . e = 5 ) AS ` c00 ` \
LIMIT 1 " );
assert_eq! ( args , vec! [ ] ) ;
}
2017-04-13 18:45:38 +00:00
#[ test ]
fn test_with_without_aggregate ( ) {
let schema = prepopulated_schema ( ) ;
// Known type.
let input = r # "[:find ?x :with ?y :where [?x :foo/bar ?y]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT DISTINCT `datoms00`.e AS `?x`, `datoms00`.v AS `?y` FROM `datoms` AS `datoms00` WHERE `datoms00`.a = 99 " ) ;
assert_eq! ( args , vec! [ ] ) ;
// Unknown type.
let input = r # "[:find ?x :with ?y :where [?x _ ?y]]"# ;
let SQLQuery { sql , args } = translate ( & schema , input , None ) ;
assert_eq! ( sql , " SELECT DISTINCT `all_datoms00`.e AS `?x`, `all_datoms00`.v AS `?y`, `all_datoms00`.value_type_tag AS `?y_value_type_tag` FROM `all_datoms` AS `all_datoms00` " ) ;
assert_eq! ( args , vec! [ ] ) ;
}