surrealdb_expr/val/value/
merge.rs1use anyhow::{Result, ensure};
2
3use crate::expr::Error;
4use crate::val::Value;
5use crate::val::value::every::ArrayBehaviour;
6
7impl Value {
8 pub fn merge(&mut self, val: Value) -> Result<()> {
9 ensure!(
11 val.is_object(),
12 Error::InvalidMerge {
13 value: val,
14 }
15 );
16 for k in val.every(None, true, ArrayBehaviour::Ignore).iter() {
18 let old = self.pick(k);
23 let new = val.pick(k);
24 if old.is_object() && new.is_object() {
25 continue;
26 }
27
28 match new {
29 Value::None => self.cut(k),
30 v => self.put(k, v),
31 }
32 }
33 Ok(())
34 }
35}
36
37#[cfg(test)]
38mod tests {
39
40 use super::*;
41 use crate::syn;
42
43 macro_rules! parse_val {
44 ($input:expr) => {
45 crate::val::convert_public_value_to_internal(syn::value($input).unwrap())
46 };
47 }
48
49 #[tokio::test]
50 async fn merge_none() {
51 let mut res = parse_val!(
52 "{
53 test: true,
54 name: {
55 first: 'Tobie',
56 last: 'Morgan Hitchcock',
57 initials: 'TMH',
58 },
59 }"
60 );
61 match res.merge(Value::NONE.clone()).unwrap_err().downcast() {
62 Ok(Error::InvalidMerge {
63 value,
64 }) => assert_eq!(value, Value::NONE),
65 Ok(error) => panic!("unexpected error: {error:?}"),
66 Err(error) => panic!("unexpected error: {error:?}"),
67 }
68 }
69
70 #[tokio::test]
71 async fn merge_empty() {
72 let mut res = parse_val!(
73 "{
74 test: true,
75 name: {
76 first: 'Tobie',
77 last: 'Morgan Hitchcock',
78 initials: 'TMH',
79 },
80 }"
81 );
82 let val = parse_val!(
83 "{
84 test: true,
85 name: {
86 first: 'Tobie',
87 last: 'Morgan Hitchcock',
88 initials: 'TMH',
89 },
90 }"
91 );
92 let mrg = Value::Object(Default::default());
93 res.merge(mrg).unwrap();
94 assert_eq!(res, val);
95 }
96
97 #[tokio::test]
98 async fn merge_basic() {
99 let mut res = parse_val!(
100 "{
101 test: true,
102 name: {
103 first: 'Tobie',
104 last: 'Morgan Hitchcock',
105 initials: 'TMH',
106 },
107 }"
108 );
109 let mrg = parse_val!(
110 "{
111 name: {
112 title: 'Mr',
113 initials: NONE,
114 },
115 tags: ['Rust', 'Golang', 'JavaScript'],
116 }"
117 );
118 let val = parse_val!(
119 "{
120 test: true,
121 name: {
122 title: 'Mr',
123 first: 'Tobie',
124 last: 'Morgan Hitchcock',
125 },
126 tags: ['Rust', 'Golang', 'JavaScript'],
127 }"
128 );
129 res.merge(mrg).unwrap();
130 assert_eq!(res, val);
131 }
132
133 #[tokio::test]
134 async fn merge_new_object() {
135 let mut res = parse_val!(
136 "{
137 test: true,
138 name: 'Tobie',
139 obj: {
140 a: 1,
141 b: 2,
142 }
143 }"
144 );
145 let mrg = parse_val!(
146 "{
147 name: {
148 title: 'Mr',
149 initials: NONE,
150 },
151 obj: {
152 a: 2,
153 b: NONE,
154 }
155 }"
156 );
157 let val = parse_val!(
158 "{
159 test: true,
160 name: {
161 title: 'Mr',
162 },
163 obj: {
164 a: 2,
165 },
166 }"
167 );
168 res.merge(mrg).unwrap();
169 assert_eq!(res, val);
170 }
171}