Support tx places in queries

This commit is contained in:
Emily Toop 2017-06-21 11:42:44 +01:00
parent d1ad3c47f7
commit 9c677a5bb1
3 changed files with 80 additions and 7 deletions

View file

@ -615,8 +615,10 @@ impl ConjoiningClauses {
/// present.
fn constrain_to_tx(&mut self, tx: &PatternNonValuePlace) {
match *tx {
PatternNonValuePlace::Placeholder => (),
_ => unimplemented!(), // TODO: #440.
PatternNonValuePlace::Variable(ref v) => self.constrain_var_to_type(v.clone(), ValueType::Ref),
PatternNonValuePlace::Placeholder |
PatternNonValuePlace::Entid(_) |
PatternNonValuePlace::Ident(_) => (),
}
}

View file

@ -81,7 +81,7 @@ impl ConjoiningClauses {
// Sorry for the duplication; Rust makes it a pain to abstract this.
// The transaction part of a pattern must be an entid, variable, or placeholder.
self.constrain_to_tx(&pattern.tx); // See #440.
self.constrain_to_tx(&pattern.tx);
self.constrain_to_ref(&pattern.entity);
self.constrain_to_ref(&pattern.attribute);
@ -238,9 +238,29 @@ impl ConjoiningClauses {
if value_type.is_none() {
self.wheres.add_intersection(ColumnConstraint::HasType(col.clone(), typed_value_type));
}
},
}
// TODO pattern.tx -> like handling entity place
// carefully read Datomic query doc to check for correct handling
match pattern.tx {
PatternNonValuePlace::Placeholder => (),
PatternNonValuePlace::Variable(ref v) => {
self.bind_column_to_var(schema, col.clone(), DatomsColumn::Tx, v.clone());
},
PatternNonValuePlace::Entid(entid) => {
self.constrain_column_to_entity(col.clone(), DatomsColumn::Tx, entid);
},
PatternNonValuePlace::Ident(ref ident) => {
if let Some(entid) = self.entid_for_ident(schema, ident.as_ref()) {
self.constrain_column_to_entity(col.clone(), DatomsColumn::Tx, entid)
} else {
// A resolution failure means we're done here.
self.mark_known_empty(EmptyBecause::UnresolvedIdent(ident.cloned()));
return;
}
}
}
}
pub fn apply_pattern<'s, 'p>(&mut self, schema: &'s Schema, pattern: Pattern) {

View file

@ -232,11 +232,9 @@ fn test_instants_and_uuids() {
conn.transact(&mut c, r#"[
[:db/add "u" :foo/uuid #uuid "cf62d552-6569-4d1b-b667-04703041dfc4"]
]"#).unwrap();
// We don't yet support getting the tx from a pattern (#440), so run wild.
let r = conn.q_once(&mut c,
r#"[:find [?x ?u ?when]
:where [?x :foo/uuid ?u]
:where [?x :foo/uuid ?u ?tx]
[?tx :db/txInstant ?when]]"#, None);
match r {
Result::Ok(QueryResults::Tuple(Some(vals))) => {
@ -257,6 +255,59 @@ fn test_instants_and_uuids() {
}
}
#[test]
fn test_tx() {
let mut c = new_connection("").expect("Couldn't open conn.");
let mut conn = Conn::connect(&mut c).expect("Couldn't open DB.");
conn.transact(&mut c, r#"[
[:db/add "s" :db/ident :foo/uuid]
[:db/add "s" :db/valueType :db.type/uuid]
[:db/add "s" :db/cardinality :db.cardinality/one]
]"#).unwrap();
let t = conn.transact(&mut c, r#"[
[:db/add "u" :foo/uuid #uuid "cf62d552-6569-4d1b-b667-04703041dfc4"]
]"#).unwrap();
let r = conn.q_once(&mut c,
r#"[:find ?tx
:where [?x :foo/uuid #uuid "cf62d552-6569-4d1b-b667-04703041dfc4" ?tx]]"#, None);
match r {
Result::Ok(QueryResults::Rel(ref v)) => {
assert_eq!(*v, vec![
vec![TypedValue::Ref(t.tx_id),]
]);
},
_ => panic!("Expected query to work."),
}
}
#[test]
fn test_tx_as_input() {
let mut c = new_connection("").expect("Couldn't open conn.");
let mut conn = Conn::connect(&mut c).expect("Couldn't open DB.");
conn.transact(&mut c, r#"[
[:db/add "s" :db/ident :foo/uuid]
[:db/add "s" :db/valueType :db.type/uuid]
[:db/add "s" :db/cardinality :db.cardinality/one]
]"#).unwrap();
let t = conn.transact(&mut c, r#"[
[:db/add "u" :foo/uuid #uuid "cf62d552-6569-4d1b-b667-04703041dfc4"]
]"#).unwrap();
let tx = (Variable::from_valid_name("?tx"), TypedValue::Ref(t.tx_id));
let inputs = QueryInputs::with_value_sequence(vec![tx]);
let r = conn.q_once(&mut c,
r#"[:find ?uuid
:in ?tx
:where [?x :foo/uuid ?uuid ?tx]]"#, inputs);
match r {
Result::Ok(QueryResults::Rel(ref v)) => {
assert_eq!(*v, vec![
vec![TypedValue::Uuid(Uuid::from_str("cf62d552-6569-4d1b-b667-04703041dfc4").unwrap()),]
]);
},
_ => panic!("Expected query to work."),
}
}
#[test]
fn test_fulltext() {
let mut c = new_connection("").expect("Couldn't open conn.");