parent
d63f80d8e6
commit
bec3d49b6d
4 changed files with 89 additions and 19 deletions
|
@ -28,7 +28,7 @@ impl<'a> Document<'a> {
|
|||
}
|
||||
}
|
||||
// Loop over every field in the document
|
||||
for fd in self.current.every().iter() {
|
||||
for fd in self.current.every(true).iter() {
|
||||
if !keys.contains(fd) {
|
||||
match fd {
|
||||
fd if fd.is_id() => continue,
|
||||
|
|
|
@ -3,28 +3,31 @@ use crate::sql::part::Part;
|
|||
use crate::sql::value::Value;
|
||||
|
||||
impl Value {
|
||||
pub fn every(&self) -> Vec<Idiom> {
|
||||
self._every(Idiom::default())
|
||||
pub fn every(&self, split: bool) -> Vec<Idiom> {
|
||||
self._every(split, Idiom::default())
|
||||
}
|
||||
fn _every(&self, prev: Idiom) -> Vec<Idiom> {
|
||||
fn _every(&self, split: bool, prev: Idiom) -> Vec<Idiom> {
|
||||
match self {
|
||||
// Current path part is an object
|
||||
Value::Object(v) => v
|
||||
.iter()
|
||||
.flat_map(|(k, v)| {
|
||||
let p = Part::from(k.to_owned());
|
||||
v._every(prev.clone().push(p))
|
||||
v._every(split, prev.clone().push(p))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
// Current path part is an array
|
||||
Value::Array(v) => v
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, v)| {
|
||||
let p = Part::from(i.to_owned());
|
||||
v._every(prev.clone().push(p))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
Value::Array(v) => match split {
|
||||
true => v
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, v)| {
|
||||
let p = Part::from(i.to_owned());
|
||||
v._every(split, prev.clone().push(p))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
false => vec![prev],
|
||||
},
|
||||
// Process everything else
|
||||
_ => vec![prev],
|
||||
}
|
||||
|
@ -39,7 +42,14 @@ mod tests {
|
|||
use crate::sql::test::Parse;
|
||||
|
||||
#[test]
|
||||
fn every() {
|
||||
fn every_without_array_indexes() {
|
||||
let val = Value::parse("{ test: { something: [{ age: 34, tags: ['code', 'databases'] }, { age: 36, tags: ['design', 'operations'] }] } }");
|
||||
let res = vec![Idiom::parse("test.something")];
|
||||
assert_eq!(res, val.every(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_including_array_indexes() {
|
||||
let val = Value::parse("{ test: { something: [{ age: 34, tags: ['code', 'databases'] }, { age: 36, tags: ['design', 'operations'] }] } }");
|
||||
let res = vec![
|
||||
Idiom::parse("test.something[0].age"),
|
||||
|
@ -49,6 +59,6 @@ mod tests {
|
|||
Idiom::parse("test.something[1].tags[0]"),
|
||||
Idiom::parse("test.something[1].tags[1]"),
|
||||
];
|
||||
assert_eq!(res, val.every());
|
||||
assert_eq!(res, val.every(true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::ctx::Context;
|
|||
use crate::dbs::Options;
|
||||
use crate::dbs::Transaction;
|
||||
use crate::err::Error;
|
||||
use crate::sql::part::Part;
|
||||
use crate::sql::value::Value;
|
||||
|
||||
impl Value {
|
||||
|
@ -14,9 +13,13 @@ impl Value {
|
|||
val: Value,
|
||||
) -> Result<(), Error> {
|
||||
match val {
|
||||
Value::Object(v) => {
|
||||
for (k, v) in v {
|
||||
self.set(ctx, opt, txn, &[Part::from(k)], v).await?;
|
||||
v if v.is_object() => {
|
||||
for k in v.every(false).iter() {
|
||||
println!("{}", k);
|
||||
match v.get(ctx, opt, txn, &k.0).await? {
|
||||
Value::None => self.del(ctx, opt, txn, &k.0).await?,
|
||||
v => self.set(ctx, opt, txn, &k.0, v).await?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
57
lib/tests/merge.rs
Normal file
57
lib/tests/merge.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
use surrealdb::sql::Value;
|
||||
use surrealdb::Datastore;
|
||||
use surrealdb::Error;
|
||||
use surrealdb::Session;
|
||||
|
||||
#[tokio::test]
|
||||
async fn merge_record() -> Result<(), Error> {
|
||||
let sql = "
|
||||
UPDATE person:test SET name.initials = 'TMH', name.first = 'Tobie', name.last = 'Morgan Hitchcock';
|
||||
UPDATE person:test MERGE {
|
||||
name: {
|
||||
title: 'Mr',
|
||||
initials: NONE,
|
||||
suffix: ['BSc', 'MSc'],
|
||||
}
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: {
|
||||
initials: 'TMH',
|
||||
first: 'Tobie',
|
||||
last: 'Morgan Hitchcock',
|
||||
}
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: {
|
||||
title: 'Mr',
|
||||
first: 'Tobie',
|
||||
last: 'Morgan Hitchcock',
|
||||
suffix: ['BSc', 'MSc'],
|
||||
}
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue