1use serde_json::{json, Map, Number, Value};
13
14use crate::local::filter;
15use crate::local::value::{self, get_path, remove_path, set_path};
16
17pub fn insert_one(rows: &mut Vec<Value>, doc: &Value) -> Result<Value, String> {
25 let doc = normalize_doc(doc)?;
26 if let Some(id) = doc.get("_id") {
27 if rows.iter().any(|r| id_equal(r, id)) {
28 return Err(format!("insertOne: _id 冲突({id})"));
29 }
30 }
31 rows.push(doc.clone());
32 Ok(doc)
33}
34
35pub fn insert_many(
40 rows: &mut Vec<Value>,
41 docs: &[Value],
42 upsert_by_id: bool,
43) -> Result<Value, String> {
44 let normalized = docs
45 .iter()
46 .map(normalize_doc)
47 .collect::<Result<Vec<_>, _>>()?;
48
49 if upsert_by_id {
50 for doc in normalized {
51 match doc.get("_id") {
52 Some(id) => match rows.iter_mut().find(|r| id_equal(r, id)) {
53 Some(slot) => *slot = doc,
54 None => rows.push(doc),
55 },
56 None => rows.push(doc),
57 }
58 }
59 return Ok(json!({ "insertedCount": docs.len() }));
60 }
61
62 for (i, doc) in normalized.iter().enumerate() {
63 if let Some(id) = doc.get("_id") {
64 if rows.iter().any(|r| id_equal(r, id)) {
65 return Err(format!("insertMany: _id 冲突({id})"));
66 }
67 if normalized[..i].iter().any(|prev| id_equal(prev, id)) {
68 return Err(format!("insertMany: 批内 _id 重复({id})"));
69 }
70 }
71 }
72 rows.extend(normalized);
73 Ok(json!({ "insertedCount": docs.len() }))
74}
75
76pub fn update_many(rows: &mut [Value], condition: &Value, update: &Value) -> Result<Value, String> {
84 let mut modified = 0_usize;
85 for row in rows.iter_mut() {
86 if filter::matches(row, condition)? {
87 let before = row.clone();
88 apply_update(row, update, false)?;
89 if !value::values_equal(&before, row) {
90 modified += 1;
91 }
92 }
93 }
94 Ok(json!({ "modifiedCount": modified }))
95}
96
97pub fn find_one_and_update(
102 rows: &mut Vec<Value>,
103 condition: &Value,
104 update: &Value,
105 options: &Value,
106) -> Result<Value, String> {
107 let upsert = options
108 .get("upsert")
109 .and_then(Value::as_bool)
110 .unwrap_or(false);
111 let return_before = options
112 .get("returnDocument")
113 .and_then(Value::as_str)
114 .map(|s| s == "before")
115 .unwrap_or(false);
116
117 if let Some(idx) = find_first(rows, condition)? {
118 let before = rows[idx].clone();
119 let mut doc = before.clone();
120 apply_update(&mut doc, update, false)?;
121 rows[idx] = doc.clone();
122 return Ok(if return_before { before } else { doc });
123 }
124 if !upsert {
125 return Ok(Value::Null);
126 }
127 let mut doc = build_upsert_base(condition);
128 apply_update(&mut doc, update, true)?;
129 rows.push(doc.clone());
130 Ok(if return_before { Value::Null } else { doc })
131}
132
133pub fn delete_many(rows: &mut Vec<Value>, condition: &Value) -> Result<Value, String> {
135 let mut kept = Vec::with_capacity(rows.len());
136 let mut deleted = 0_usize;
137 for row in rows.drain(..) {
138 if filter::matches(&row, condition)? {
139 deleted += 1;
140 } else {
141 kept.push(row);
142 }
143 }
144 *rows = kept;
145 Ok(json!({ "deletedCount": deleted }))
146}
147
148fn apply_update(doc: &mut Value, update: &Value, is_insert: bool) -> Result<(), String> {
154 let obj = update
155 .as_object()
156 .ok_or_else(|| format!("update 必须是对象,收到 {}", type_name(update)))?;
157 if obj.is_empty() {
158 return Err("没有提供要更新的字段".to_string());
159 }
160 if !doc.is_object() {
161 *doc = Value::Object(Map::new());
162 }
163 for (op, arg) in obj {
164 match op.as_str() {
165 "$set" => apply_set(doc, arg)?,
166 "$inc" => apply_inc(doc, arg)?,
167 "$unset" => apply_unset(doc, arg)?,
168 "$setOnInsert" => {
170 if is_insert {
171 apply_set(doc, arg)?;
172 }
173 }
174 other => {
175 return Err(format!(
176 "不支持的更新操作符: {other}(本地求值器仅支持 $set/$inc/$unset/$setOnInsert,拒绝静默)"
177 ));
178 }
179 }
180 }
181 Ok(())
182}
183
184fn apply_set(doc: &mut Value, arg: &Value) -> Result<(), String> {
186 let fields = arg
187 .as_object()
188 .ok_or_else(|| format!("$set 需要对象,收到 {}", type_name(arg)))?;
189 for (path, v) in fields {
190 set_path(doc, path, v.clone());
191 }
192 Ok(())
193}
194
195fn apply_inc(doc: &mut Value, arg: &Value) -> Result<(), String> {
197 let fields = arg
198 .as_object()
199 .ok_or_else(|| format!("$inc 需要对象,收到 {}", type_name(arg)))?;
200 for (path, inc) in fields {
201 if inc.as_f64().is_none() {
202 return Err(format!(
203 "$inc 的增量必须是数字,字段 \"{path}\" 收到 {}",
204 type_name(inc)
205 ));
206 }
207 let new = match get_path(doc, path) {
208 None => inc.clone(),
210 Some(cur) => {
211 let base = cur.as_f64().ok_or_else(|| {
212 format!(
213 "$inc 目标字段 \"{path}\" 非数值({}):Mongo 语义要求对数值字段自增",
214 type_name(cur)
215 )
216 })?;
217 let inc_f = inc.as_f64().unwrap_or(0.0);
218 match (cur.as_i64(), inc.as_i64()) {
219 (Some(a), Some(b)) => match a.checked_add(b) {
220 Some(s) => Value::from(s),
221 None => float_value(a as f64 + b as f64),
222 },
223 _ => float_value(base + inc_f),
224 }
225 }
226 };
227 set_path(doc, path, new);
228 }
229 Ok(())
230}
231
232fn apply_unset(doc: &mut Value, arg: &Value) -> Result<(), String> {
234 let fields = arg
235 .as_object()
236 .ok_or_else(|| format!("$unset 需要对象,收到 {}", type_name(arg)))?;
237 for path in fields.keys() {
238 remove_path(doc, path);
239 }
240 Ok(())
241}
242
243fn normalize_doc(v: &Value) -> Result<Value, String> {
249 match v {
250 Value::Object(_) => Ok(v.clone()),
251 Value::Null => Ok(Value::Object(Map::new())),
252 other => Err(format!(
253 "文档必须是对象,收到 {}(拒绝静默按空文档写入)",
254 type_name(other)
255 )),
256 }
257}
258
259fn id_equal(row: &Value, id: &Value) -> bool {
261 row.get("_id").map(|v| value::values_equal(v, id)).unwrap_or(false)
262}
263
264fn find_first(rows: &[Value], condition: &Value) -> Result<Option<usize>, String> {
266 for (i, row) in rows.iter().enumerate() {
267 if filter::matches(row, condition)? {
268 return Ok(Some(i));
269 }
270 }
271 Ok(None)
272}
273
274fn build_upsert_base(condition: &Value) -> Value {
276 let mut m = Map::new();
277 if let Some(o) = condition.as_object() {
278 for (k, v) in o {
279 if k.starts_with('$') {
280 continue;
281 }
282 match v {
283 Value::Object(inner) => {
284 if let Some(eq) = inner.get("$eq") {
285 m.insert(k.clone(), eq.clone());
286 }
287 }
288 other => {
289 m.insert(k.clone(), other.clone());
290 }
291 }
292 }
293 }
294 Value::Object(m)
295}
296
297fn float_value(f: f64) -> Value {
298 Number::from_f64(f).map(Value::Number).unwrap_or(Value::Null)
299}
300
301fn type_name(v: &Value) -> &'static str {
302 match v {
303 Value::Null => "null",
304 Value::Bool(_) => "bool",
305 Value::Number(_) => "number",
306 Value::String(_) => "string",
307 Value::Array(_) => "array",
308 Value::Object(_) => "object",
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315 use serde_json::json;
316
317 fn rows(v: Value) -> Vec<Value> {
318 v.as_array().cloned().expect("文档数组")
319 }
320
321 #[test]
322 fn insert_one_appends_and_conflicts() {
323 let mut r = rows(json!([]));
324 let out = insert_one(&mut r, &json!({ "_id": "a", "n": 1 })).unwrap();
325 assert_eq!(out, json!({ "_id": "a", "n": 1 }));
326 assert_eq!(r.len(), 1);
327 assert!(insert_one(&mut r, &json!({ "_id": "a", "n": 2 })).is_err());
329 assert_eq!(r.len(), 1);
330 assert_eq!(insert_one(&mut r, &Value::Null).unwrap(), json!({}));
332 assert!(insert_one(&mut r, &json!(5)).is_err());
334 }
335
336 #[test]
337 fn insert_many_plain_and_conflicts() {
338 let mut r = rows(json!([{ "_id": "a" }]));
339 assert!(insert_many(&mut r, &[json!({ "_id": "a" })], false).is_err());
341 assert!(insert_many(
343 &mut r,
344 &[json!({ "_id": "b" }), json!({ "_id": "b" })],
345 false
346 )
347 .is_err());
348 let out = insert_many(&mut r, &[json!({ "_id": "b" }), json!({ "_id": "c" })], false)
350 .unwrap();
351 assert_eq!(out, json!({ "insertedCount": 2 }));
352 assert_eq!(r.len(), 3);
353 }
354
355 #[test]
356 fn insert_many_upsert_by_id_is_idempotent() {
357 let mut r = rows(json!([{ "_id": "a", "n": 1 }]));
358 let out = insert_many(
360 &mut r,
361 &[json!({ "_id": "a", "n": 9 }), json!({ "_id": "z", "n": 5 })],
362 true,
363 )
364 .unwrap();
365 assert_eq!(out, json!({ "insertedCount": 2 }));
366 assert_eq!(
367 r,
368 rows(json!([{ "_id": "a", "n": 9 }, { "_id": "z", "n": 5 }]))
369 );
370 insert_many(&mut r, &[json!({ "_id": "a", "n": 9 })], true).unwrap();
372 assert_eq!(
373 r,
374 rows(json!([{ "_id": "a", "n": 9 }, { "_id": "z", "n": 5 }]))
375 );
376 }
377
378 #[test]
379 fn update_many_set_inc_unset() {
380 let mut r = rows(json!([
381 { "_id": 1, "s": "paid", "n": 1 },
382 { "_id": 2, "s": "open", "n": 2 }
383 ]));
384 let out = update_many(
385 &mut r,
386 &json!({ "s": "paid" }),
387 &json!({ "$set": { "tag": "x" }, "$inc": { "n": 10 }, "$unset": { "s": "" } }),
388 )
389 .unwrap();
390 assert_eq!(out, json!({ "modifiedCount": 1 }));
391 assert_eq!(r[0], json!({ "_id": 1, "n": 11, "tag": "x" }));
392 assert_eq!(r[1], json!({ "_id": 2, "s": "open", "n": 2 }));
393 let out2 = update_many(&mut r, &json!({ "_id": 1 }), &json!({ "$set": { "n": 11 } })).unwrap();
395 assert_eq!(out2, json!({ "modifiedCount": 0 }));
396 }
397
398 #[test]
399 fn update_inc_type_and_non_numeric_error() {
400 let mut r = rows(json!([{ "_id": 1, "i": 2 }, { "_id": 2, "s": "x" }]));
401 update_many(&mut r, &json!({ "_id": 1 }), &json!({ "$inc": { "i": 3 } })).unwrap();
403 assert_eq!(r[0]["i"], json!(5));
404 update_many(&mut r, &json!({ "_id": 1 }), &json!({ "$inc": { "gone": 1 } })).unwrap();
406 assert_eq!(r[0]["gone"], json!(1));
407 assert!(
409 update_many(&mut r, &json!({ "_id": 2 }), &json!({ "$inc": { "s": 1 } })).is_err()
410 );
411 }
412
413 #[test]
414 fn update_unknown_operator_errors() {
415 let mut r = rows(json!([{ "_id": 1 }]));
416 assert!(update_many(&mut r, &json!({}), &json!({ "$push": { "a": 1 } })).is_err());
417 assert!(update_many(&mut r, &json!({}), &json!({})).is_err());
418 }
419
420 #[test]
421 fn find_one_and_update_after_before_and_upsert() {
422 let mut r = rows(json!([{ "_id": 1, "n": 1 }, { "_id": 2, "n": 2 }]));
423 let out =
425 find_one_and_update(&mut r, &json!({ "_id": 1 }), &json!({ "$set": { "n": 7 } }), &json!({}))
426 .unwrap();
427 assert_eq!(out, json!({ "_id": 1, "n": 7 }));
428 let out2 = find_one_and_update(
430 &mut r,
431 &json!({ "_id": 1 }),
432 &json!({ "$set": { "n": 8 } }),
433 &json!({ "returnDocument": "before" }),
434 )
435 .unwrap();
436 assert_eq!(out2, json!({ "_id": 1, "n": 7 }));
437 assert_eq!(r[0], json!({ "_id": 1, "n": 8 }));
438 let miss = find_one_and_update(&mut r, &json!({ "_id": 99 }), &json!({ "$set": { "n": 1 } }), &json!({}))
440 .unwrap();
441 assert_eq!(miss, Value::Null);
442 assert_eq!(r.len(), 2);
443 let up = find_one_and_update(
445 &mut r,
446 &json!({ "_id": 3 }),
447 &json!({ "$set": { "n": 3 }, "$setOnInsert": { "_id": 3, "createdAt": 100 } }),
448 &json!({ "upsert": true }),
449 )
450 .unwrap();
451 assert_eq!(up, json!({ "_id": 3, "n": 3, "createdAt": 100 }));
452 assert_eq!(r.len(), 3);
453 }
454
455 #[test]
456 fn delete_many_counts() {
457 let mut r = rows(json!([
458 { "_id": 1, "s": "a" },
459 { "_id": 2, "s": "b" },
460 { "_id": 3, "s": "a" }
461 ]));
462 let out = delete_many(&mut r, &json!({ "s": "a" })).unwrap();
463 assert_eq!(out, json!({ "deletedCount": 2 }));
464 assert_eq!(r, rows(json!([{ "_id": 2, "s": "b" }])));
465 assert_eq!(
467 delete_many(&mut r, &json!({ "s": "nope" })).unwrap(),
468 json!({ "deletedCount": 0 })
469 );
470 }
471}