1use std::borrow::Cow;
22use std::sync::Arc;
23
24use fsqlite_error::{FrankenError, Result};
25use fsqlite_func::{
26 ColumnContext, FunctionRegistry, IndexInfo, ScalarFunction, VirtualTable, VirtualTableCursor,
27};
28use fsqlite_types::{SqliteValue, cx::Cx};
29use serde_json::{Map, Number, Value};
30
31const JSON_VALID_DEFAULT_FLAGS: u8 = 0x01;
32const JSON_VALID_RFC_8259_FLAG: u8 = 0x01;
33const JSON_VALID_JSON5_FLAG: u8 = 0x02;
34const JSON_VALID_JSONB_SUPERFICIAL_FLAG: u8 = 0x04;
35const JSON_VALID_JSONB_STRICT_FLAG: u8 = 0x08;
36const JSON_PRETTY_DEFAULT_INDENT_WIDTH: usize = 4;
37pub const JSON_TABLE_COLUMN_NAMES: [&str; 8] = [
39 "key", "value", "type", "atom", "id", "parent", "fullkey", "path",
40];
41
42const JSONB_NULL_TYPE: u8 = 0x0;
43const JSONB_TRUE_TYPE: u8 = 0x1;
44const JSONB_FALSE_TYPE: u8 = 0x2;
45const JSONB_INT_TYPE: u8 = 0x3;
46const JSONB_FLOAT_TYPE: u8 = 0x5;
47const JSONB_TEXT_TYPE: u8 = 0x7;
48const JSONB_TEXT_JSON_TYPE: u8 = 0x8;
49const JSONB_ARRAY_TYPE: u8 = 0xB;
50const JSONB_OBJECT_TYPE: u8 = 0xC;
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53enum PathSegment {
54 Key(String),
55 Index(usize),
56 Append,
57 FromEnd(usize),
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61enum EditMode {
62 Set,
63 Insert,
64 Replace,
65}
66
67pub fn json(input: &str) -> Result<String> {
71 let value = parse_json_text(input)?;
72 encode_json_text("json serialize failed", &value)
73}
74
75#[must_use]
83pub fn json_valid(input: &str, flags: Option<u8>) -> i64 {
84 json_valid_blob(input.as_bytes(), flags)
85}
86
87#[must_use]
89pub fn json_valid_blob(input: &[u8], flags: Option<u8>) -> i64 {
90 let effective_flags = flags.unwrap_or(JSON_VALID_DEFAULT_FLAGS);
91 if effective_flags == 0 {
92 return 0;
93 }
94
95 let allow_json = effective_flags & JSON_VALID_RFC_8259_FLAG != 0;
96 let allow_json5 = effective_flags & JSON_VALID_JSON5_FLAG != 0;
97 let allow_jsonb_superficial = effective_flags & JSON_VALID_JSONB_SUPERFICIAL_FLAG != 0;
98 let allow_jsonb_strict = effective_flags & JSON_VALID_JSONB_STRICT_FLAG != 0;
99
100 if allow_json || allow_json5 {
101 if let Ok(text) = std::str::from_utf8(input) {
102 if allow_json && parse_json_text(text).is_ok() {
103 return 1;
104 }
105 if allow_json5 && parse_json5_text(text).is_ok() {
106 return 1;
107 }
108 }
109 }
110
111 if allow_jsonb_strict && decode_jsonb_root(input).is_ok() {
112 return 1;
113 }
114 if allow_jsonb_superficial && is_superficially_valid_jsonb(input) {
115 return 1;
116 }
117
118 0
119}
120
121pub fn jsonb(input: &str) -> Result<Vec<u8>> {
123 let value = parse_json_text(input)?;
124 encode_jsonb_root(&value)
125}
126
127pub fn json_from_jsonb(input: &[u8]) -> Result<String> {
129 let value = decode_jsonb_root(input)?;
130 encode_json_text("json_from_jsonb encode failed", &value)
131}
132
133fn encode_json_text(context: &str, value: &Value) -> Result<String> {
134 serde_json::to_string(value)
135 .map_err(|error| FrankenError::function_error(format!("{context}: {error}")))
136}
137
138fn parse_json_input_blob(input: &[u8]) -> Result<Value> {
139 match decode_jsonb_root(input) {
140 Ok(value) => Ok(value),
141 Err(jsonb_error) => match std::str::from_utf8(input) {
142 Ok(text) => parse_json_text(text),
143 Err(_) => Err(jsonb_error),
144 },
145 }
146}
147
148fn json_type_value(root: &Value, path: Option<&str>) -> Result<Option<&'static str>> {
149 let target = match path {
150 Some(path_expr) => resolve_path(root, path_expr)?,
151 None => Some(root),
152 };
153 Ok(target.map(json_type_name))
154}
155
156fn json_extract_value(root: &Value, paths: &[&str]) -> Result<SqliteValue> {
157 if paths.is_empty() {
158 return Err(FrankenError::function_error(
159 "json_extract requires at least one path",
160 ));
161 }
162
163 if paths.len() == 1 {
164 let selected = resolve_path(root, paths[0])?;
165 return Ok(selected.map_or(SqliteValue::Null, json_to_sqlite_scalar));
166 }
167
168 let mut out = Vec::with_capacity(paths.len());
169 for path_expr in paths {
170 let selected = resolve_path(root, path_expr)?;
171 out.push(selected.cloned().unwrap_or(Value::Null));
172 }
173
174 let encoded = encode_json_text("json_extract array encode failed", &Value::Array(out))?;
175 Ok(SqliteValue::Text(Arc::from(encoded)))
176}
177
178fn jsonb_extract_value(root: &Value, paths: &[&str]) -> Result<Vec<u8>> {
179 if paths.is_empty() {
180 return Err(FrankenError::function_error(
181 "jsonb_extract requires at least one path",
182 ));
183 }
184
185 let output = if paths.len() == 1 {
186 resolve_path(root, paths[0])?
187 .cloned()
188 .unwrap_or(Value::Null)
189 } else {
190 let mut values = Vec::with_capacity(paths.len());
191 for path_expr in paths {
192 values.push(
193 resolve_path(root, path_expr)?
194 .cloned()
195 .unwrap_or(Value::Null),
196 );
197 }
198 Value::Array(values)
199 };
200
201 encode_jsonb_root(&output)
202}
203
204fn json_arrow_value(root: &Value, path: &str) -> Result<SqliteValue> {
205 let selected = resolve_path(root, path)?;
206 let Some(value) = selected else {
207 return Ok(SqliteValue::Null);
208 };
209 let encoded = encode_json_text("json_arrow encode failed", value)?;
210 Ok(SqliteValue::Text(Arc::from(encoded)))
211}
212
213fn json_array_length_value(root: &Value, path: Option<&str>) -> Result<Option<usize>> {
214 let target = match path {
215 Some(path_expr) => resolve_path(root, path_expr)?,
216 None => Some(root),
217 };
218 Ok(target.and_then(Value::as_array).map(Vec::len))
219}
220
221fn json_error_position_blob(input: &[u8]) -> usize {
222 if decode_jsonb_root(input).is_ok() {
223 return 0;
224 }
225 match std::str::from_utf8(input) {
226 Ok(text) => json_error_position(text),
227 Err(_) => 1,
228 }
229}
230
231fn json_pretty_value(root: &Value, indent: Option<&str>) -> Result<String> {
232 let indent_unit = match indent {
233 Some(indent) => indent.to_owned(),
234 None => " ".repeat(JSON_PRETTY_DEFAULT_INDENT_WIDTH),
235 };
236 let mut out = String::new();
237 write_pretty_value(root, &indent_unit, 0, &mut out)?;
238 Ok(out)
239}
240
241fn edit_json_paths_value(
242 root: &Value,
243 pairs: &[(&str, SqliteValue)],
244 mode: EditMode,
245) -> Result<Value> {
246 let mut edited = root.clone();
247 for (path, value) in pairs {
248 let segments = parse_path(path)?;
249 let replacement = sqlite_to_json(value)?;
250 apply_edit(&mut edited, &segments, replacement, mode);
251 }
252 Ok(edited)
253}
254
255fn json_remove_value(root: &Value, paths: &[&str]) -> Result<Value> {
256 let mut edited = root.clone();
257 for path in paths {
258 let segments = parse_path(path)?;
259 remove_at_path(&mut edited, &segments);
260 }
261 Ok(edited)
262}
263
264fn json_patch_value(root: &Value, patch: &Value) -> Value {
265 merge_patch(root.clone(), patch.clone())
266}
267
268pub fn json_type(input: &str, path: Option<&str>) -> Result<Option<&'static str>> {
272 let root = parse_json_text(input)?;
273 json_type_value(&root, path)
274}
275
276pub fn json_extract(input: &str, paths: &[&str]) -> Result<SqliteValue> {
281 let root = parse_json_text(input)?;
282 json_extract_value(&root, paths)
283}
284
285pub fn jsonb_extract(input: &str, paths: &[&str]) -> Result<Vec<u8>> {
289 let root = parse_json_text(input)?;
290 jsonb_extract_value(&root, paths)
291}
292
293pub fn json_arrow(input: &str, path: &str) -> Result<SqliteValue> {
297 let root = parse_json_text(input)?;
298 json_arrow_value(&root, path)
299}
300
301pub fn json_double_arrow(input: &str, path: &str) -> Result<SqliteValue> {
303 json_extract(input, &[path])
304}
305
306pub fn json_array_length(input: &str, path: Option<&str>) -> Result<Option<usize>> {
308 let root = parse_json_text(input)?;
309 json_array_length_value(&root, path)
310}
311
312#[must_use]
314pub fn json_error_position(input: &str) -> usize {
315 match serde_json::from_str::<Value>(input) {
316 Ok(_) => 0,
317 Err(error) => {
318 let line = error.line();
319 let column = error.column();
320 if line == 0 || column == 0 {
321 return 1;
322 }
323
324 let mut current_line = 1usize;
325 let mut current_col = 1usize;
326 let mut char_pos = 1usize;
327 for (_idx, ch) in input.char_indices() {
328 if current_line == line && current_col == column {
329 return char_pos;
330 }
331 if ch == '\n' {
332 current_line += 1;
333 current_col = 1;
334 } else {
335 current_col += 1;
336 }
337 char_pos += 1;
338 }
339 char_pos
340 }
341 }
342}
343
344pub fn json_pretty(input: &str, indent: Option<&str>) -> Result<String> {
346 let root = parse_json_text(input)?;
347 json_pretty_value(&root, indent)
348}
349
350pub fn json_quote(value: &SqliteValue) -> Result<String> {
352 match value {
353 SqliteValue::Null => Ok("null".to_owned()),
354 SqliteValue::Integer(i) => Ok(i.to_string()),
355 v @ SqliteValue::Float(f) => {
356 if f.is_finite() {
357 Ok(v.to_text())
358 } else {
359 Ok("null".to_owned())
360 }
361 }
362 SqliteValue::Text(text) => {
363 Ok(serde_json::to_string(text).unwrap_or_else(|_| "\"\"".to_owned()))
364 }
365 SqliteValue::Blob(_) => Err(FrankenError::function_error("JSON cannot hold BLOB values")),
366 }
367}
368
369pub fn json_array(values: &[SqliteValue]) -> Result<String> {
371 let mut out = Vec::with_capacity(values.len());
372 for value in values {
373 out.push(sqlite_to_json(value)?);
374 }
375 serde_json::to_string(&Value::Array(out))
376 .map_err(|error| FrankenError::function_error(format!("json_array encode failed: {error}")))
377}
378
379pub fn json_object(args: &[SqliteValue]) -> Result<String> {
383 if args.len() % 2 != 0 {
384 return Err(FrankenError::function_error(
385 "json_object requires an even number of arguments",
386 ));
387 }
388
389 let mut map = Map::with_capacity(args.len() / 2);
390 let mut idx = 0;
391 while idx < args.len() {
392 let key = match &args[idx] {
393 SqliteValue::Text(text) => text.to_string(),
394 _ => {
395 return Err(FrankenError::function_error(
396 "json_object keys must be text",
397 ));
398 }
399 };
400 let value = sqlite_to_json(&args[idx + 1])?;
401 map.insert(key, value);
402 idx += 2;
403 }
404
405 serde_json::to_string(&Value::Object(map)).map_err(|error| {
406 FrankenError::function_error(format!("json_object encode failed: {error}"))
407 })
408}
409
410pub fn jsonb_array(values: &[SqliteValue]) -> Result<Vec<u8>> {
412 let json_text = json_array(values)?;
413 jsonb(&json_text)
414}
415
416pub fn jsonb_object(args: &[SqliteValue]) -> Result<Vec<u8>> {
418 let json_text = json_object(args)?;
419 jsonb(&json_text)
420}
421
422pub fn json_group_array(values: &[SqliteValue]) -> Result<String> {
424 json_array(values)
425}
426
427pub fn jsonb_group_array(values: &[SqliteValue]) -> Result<Vec<u8>> {
429 let json_text = json_group_array(values)?;
430 jsonb(&json_text)
431}
432
433pub fn json_group_object(entries: &[(SqliteValue, SqliteValue)]) -> Result<String> {
437 let mut map = Map::with_capacity(entries.len());
438 for (key_value, value) in entries {
439 let key = match key_value {
440 SqliteValue::Text(text) => text.to_string(),
441 _ => {
442 return Err(FrankenError::function_error(
443 "json_group_object keys must be text",
444 ));
445 }
446 };
447 map.insert(key, sqlite_to_json(value)?);
448 }
449 serde_json::to_string(&Value::Object(map)).map_err(|error| {
450 FrankenError::function_error(format!("json_group_object encode failed: {error}"))
451 })
452}
453
454pub fn jsonb_group_object(entries: &[(SqliteValue, SqliteValue)]) -> Result<Vec<u8>> {
456 let json_text = json_group_object(entries)?;
457 jsonb(&json_text)
458}
459
460pub fn json_set(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<String> {
462 let root = parse_json_text(input)?;
463 let edited = edit_json_paths_value(&root, pairs, EditMode::Set)?;
464 encode_json_text("json edit encode failed", &edited)
465}
466
467pub fn jsonb_set(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<Vec<u8>> {
469 let root = parse_json_text(input)?;
470 let edited = edit_json_paths_value(&root, pairs, EditMode::Set)?;
471 encode_jsonb_root(&edited)
472}
473
474pub fn json_insert(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<String> {
476 let root = parse_json_text(input)?;
477 let edited = edit_json_paths_value(&root, pairs, EditMode::Insert)?;
478 encode_json_text("json edit encode failed", &edited)
479}
480
481pub fn jsonb_insert(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<Vec<u8>> {
483 let root = parse_json_text(input)?;
484 let edited = edit_json_paths_value(&root, pairs, EditMode::Insert)?;
485 encode_jsonb_root(&edited)
486}
487
488pub fn json_replace(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<String> {
490 let root = parse_json_text(input)?;
491 let edited = edit_json_paths_value(&root, pairs, EditMode::Replace)?;
492 encode_json_text("json edit encode failed", &edited)
493}
494
495pub fn jsonb_replace(input: &str, pairs: &[(&str, SqliteValue)]) -> Result<Vec<u8>> {
497 let root = parse_json_text(input)?;
498 let edited = edit_json_paths_value(&root, pairs, EditMode::Replace)?;
499 encode_jsonb_root(&edited)
500}
501
502pub fn json_remove(input: &str, paths: &[&str]) -> Result<String> {
504 let root = parse_json_text(input)?;
505 let edited = json_remove_value(&root, paths)?;
506 encode_json_text("json_remove encode failed", &edited)
507}
508
509pub fn jsonb_remove(input: &str, paths: &[&str]) -> Result<Vec<u8>> {
511 let root = parse_json_text(input)?;
512 let edited = json_remove_value(&root, paths)?;
513 encode_jsonb_root(&edited)
514}
515
516pub fn json_patch(input: &str, patch: &str) -> Result<String> {
518 let root = parse_json_text(input)?;
519 let patch_value = parse_json_text(patch)?;
520 let merged = json_patch_value(&root, &patch_value);
521 encode_json_text("json_patch encode failed", &merged)
522}
523
524pub fn jsonb_patch(input: &str, patch: &str) -> Result<Vec<u8>> {
526 let root = parse_json_text(input)?;
527 let patch_value = parse_json_text(patch)?;
528 let merged = json_patch_value(&root, &patch_value);
529 encode_jsonb_root(&merged)
530}
531
532#[derive(Debug, Clone, PartialEq, Eq)]
534pub struct JsonTableRow {
535 pub key: SqliteValue,
537 pub value: SqliteValue,
539 pub type_name: &'static str,
541 pub atom: SqliteValue,
543 pub id: i64,
545 pub parent: SqliteValue,
547 pub fullkey: String,
549 pub path: String,
551}
552
553pub fn json_each(input: &str, path: Option<&str>) -> Result<Vec<JsonTableRow>> {
555 let root = parse_json_text(input)?;
556 json_each_value(&root, path)
557}
558
559fn json_each_value(root: &Value, path: Option<&str>) -> Result<Vec<JsonTableRow>> {
560 let base_path = path.unwrap_or("$");
561 let target = match path {
562 Some(path_expr) => resolve_path(root, path_expr)?,
563 None => Some(root),
564 };
565 let Some(target) = target else {
566 return Ok(Vec::new());
567 };
568
569 let mut rows = Vec::new();
570 let mut next_id = 1_i64;
571
572 match target {
573 Value::Array(array) => {
574 for (index, item) in array.iter().enumerate() {
575 let index_i64 = i64::try_from(index).map_err(|error| {
576 FrankenError::function_error(format!("json_each index overflow: {error}"))
577 })?;
578 let fullkey = append_array_path(base_path, index);
579 rows.push(JsonTableRow {
580 key: SqliteValue::Integer(index_i64),
581 value: json_value_column(item)?,
582 type_name: json_type_name(item),
583 atom: json_atom_column(item),
584 id: next_id,
585 parent: SqliteValue::Null,
586 fullkey,
587 path: base_path.to_owned(),
588 });
589 next_id += 1;
590 }
591 }
592 Value::Object(object) => {
593 for (key, item) in object {
594 let fullkey = append_object_path(base_path, key);
595 rows.push(JsonTableRow {
596 key: SqliteValue::Text(Arc::from(key.as_str())),
597 value: json_value_column(item)?,
598 type_name: json_type_name(item),
599 atom: json_atom_column(item),
600 id: next_id,
601 parent: SqliteValue::Null,
602 fullkey,
603 path: base_path.to_owned(),
604 });
605 next_id += 1;
606 }
607 }
608 scalar => {
609 rows.push(JsonTableRow {
610 key: SqliteValue::Null,
611 value: json_value_column(scalar)?,
612 type_name: json_type_name(scalar),
613 atom: json_atom_column(scalar),
614 id: next_id,
615 parent: SqliteValue::Null,
616 fullkey: base_path.to_owned(),
617 path: base_path.to_owned(),
618 });
619 }
620 }
621
622 Ok(rows)
623}
624
625pub fn json_tree(input: &str, path: Option<&str>) -> Result<Vec<JsonTableRow>> {
627 let root = parse_json_text(input)?;
628 json_tree_value(&root, path)
629}
630
631fn json_tree_value(root: &Value, path: Option<&str>) -> Result<Vec<JsonTableRow>> {
632 let base_path = path.unwrap_or("$");
633 let target = match path {
634 Some(path_expr) => resolve_path(root, path_expr)?,
635 None => Some(root),
636 };
637 let Some(target) = target else {
638 return Ok(Vec::new());
639 };
640
641 let mut rows = Vec::new();
642 let mut next_id = 0_i64;
643 append_tree_rows(
644 &mut rows,
645 target,
646 SqliteValue::Null,
647 None,
648 base_path,
649 base_path,
650 &mut next_id,
651 )?;
652 Ok(rows)
653}
654
655pub struct JsonEachVtab;
657
658#[derive(Default)]
660pub struct JsonEachCursor {
661 rows: Vec<JsonTableRow>,
662 pos: usize,
663}
664
665impl VirtualTable for JsonEachVtab {
666 type Cursor = JsonEachCursor;
667
668 fn connect(_cx: &Cx, _args: &[&str]) -> Result<Self> {
669 Ok(Self)
670 }
671
672 fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
673 info.estimated_cost = 100.0;
674 info.estimated_rows = 100;
675 Ok(())
676 }
677
678 fn open(&self) -> Result<Self::Cursor> {
679 Ok(JsonEachCursor::default())
680 }
681}
682
683impl VirtualTableCursor for JsonEachCursor {
684 fn filter(
685 &mut self,
686 _cx: &Cx,
687 _idx_num: i32,
688 _idx_str: Option<&str>,
689 args: &[SqliteValue],
690 ) -> Result<()> {
691 let (input, path) = parse_json_table_filter_args(args)?;
692 self.rows = json_each_value(&input, path)?;
693 self.pos = 0;
694 Ok(())
695 }
696
697 fn next(&mut self, _cx: &Cx) -> Result<()> {
698 if self.pos < self.rows.len() {
699 self.pos += 1;
700 }
701 Ok(())
702 }
703
704 fn eof(&self) -> bool {
705 self.pos >= self.rows.len()
706 }
707
708 fn column(&self, ctx: &mut ColumnContext, col: i32) -> Result<()> {
709 let row = self.rows.get(self.pos).ok_or_else(|| {
710 FrankenError::function_error("json_each cursor is out of bounds for column read")
711 })?;
712 write_json_table_column(row, ctx, col)
713 }
714
715 fn rowid(&self) -> Result<i64> {
716 self.rows.get(self.pos).map(|row| row.id).ok_or_else(|| {
717 FrankenError::function_error("json_each cursor is out of bounds for rowid")
718 })
719 }
720}
721
722pub struct JsonTreeVtab;
724
725#[derive(Default)]
727pub struct JsonTreeCursor {
728 rows: Vec<JsonTableRow>,
729 pos: usize,
730}
731
732impl VirtualTable for JsonTreeVtab {
733 type Cursor = JsonTreeCursor;
734
735 fn connect(_cx: &Cx, _args: &[&str]) -> Result<Self> {
736 Ok(Self)
737 }
738
739 fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
740 info.estimated_cost = 200.0;
741 info.estimated_rows = 1_000;
742 Ok(())
743 }
744
745 fn open(&self) -> Result<Self::Cursor> {
746 Ok(JsonTreeCursor::default())
747 }
748}
749
750impl VirtualTableCursor for JsonTreeCursor {
751 fn filter(
752 &mut self,
753 _cx: &Cx,
754 _idx_num: i32,
755 _idx_str: Option<&str>,
756 args: &[SqliteValue],
757 ) -> Result<()> {
758 let (input, path) = parse_json_table_filter_args(args)?;
759 self.rows = json_tree_value(&input, path)?;
760 self.pos = 0;
761 Ok(())
762 }
763
764 fn next(&mut self, _cx: &Cx) -> Result<()> {
765 if self.pos < self.rows.len() {
766 self.pos += 1;
767 }
768 Ok(())
769 }
770
771 fn eof(&self) -> bool {
772 self.pos >= self.rows.len()
773 }
774
775 fn column(&self, ctx: &mut ColumnContext, col: i32) -> Result<()> {
776 let row = self.rows.get(self.pos).ok_or_else(|| {
777 FrankenError::function_error("json_tree cursor is out of bounds for column read")
778 })?;
779 write_json_table_column(row, ctx, col)
780 }
781
782 fn rowid(&self) -> Result<i64> {
783 self.rows.get(self.pos).map(|row| row.id).ok_or_else(|| {
784 FrankenError::function_error("json_tree cursor is out of bounds for rowid")
785 })
786 }
787}
788
789fn parse_json_text(input: &str) -> Result<Value> {
790 serde_json::from_str::<Value>(input)
791 .map_err(|error| FrankenError::function_error(format!("invalid JSON input: {error}")))
792}
793
794fn parse_json5_text(input: &str) -> Result<Value> {
795 json5::from_str::<Value>(input)
796 .map_err(|error| FrankenError::function_error(format!("invalid JSON5 input: {error}")))
797}
798
799fn encode_jsonb_root(value: &Value) -> Result<Vec<u8>> {
800 let mut out = Vec::new();
801 encode_jsonb_value(value, &mut out)?;
802 Ok(out)
803}
804
805fn encode_jsonb_value(value: &Value, out: &mut Vec<u8>) -> Result<()> {
806 match value {
807 Value::Null => append_jsonb_node(JSONB_NULL_TYPE, &[], out),
808 Value::Bool(true) => append_jsonb_node(JSONB_TRUE_TYPE, &[], out),
809 Value::Bool(false) => append_jsonb_node(JSONB_FALSE_TYPE, &[], out),
810 Value::Number(number) => {
811 if let Some(i) = number.as_i64() {
812 append_jsonb_node(JSONB_INT_TYPE, &i.to_be_bytes(), out)
813 } else if let Some(u) = number.as_u64() {
814 if let Ok(i) = i64::try_from(u) {
815 append_jsonb_node(JSONB_INT_TYPE, &i.to_be_bytes(), out)
816 } else {
817 let float = u as f64;
818 append_jsonb_node(JSONB_FLOAT_TYPE, &float.to_bits().to_be_bytes(), out)
819 }
820 } else {
821 let float = number.as_f64().ok_or_else(|| {
822 FrankenError::function_error("failed to encode non-finite JSON number")
823 })?;
824 append_jsonb_node(JSONB_FLOAT_TYPE, &float.to_bits().to_be_bytes(), out)
825 }
826 }
827 Value::String(text) => append_jsonb_node(JSONB_TEXT_TYPE, text.as_bytes(), out),
828 Value::Array(array) => {
829 let mut payload = Vec::new();
830 for item in array {
831 encode_jsonb_value(item, &mut payload)?;
832 }
833 append_jsonb_node(JSONB_ARRAY_TYPE, &payload, out)
834 }
835 Value::Object(object) => {
836 let mut payload = Vec::new();
837 for (key, item) in object {
838 append_jsonb_node(JSONB_TEXT_JSON_TYPE, key.as_bytes(), &mut payload)?;
839 encode_jsonb_value(item, &mut payload)?;
840 }
841 append_jsonb_node(JSONB_OBJECT_TYPE, &payload, out)
842 }
843 }
844}
845
846fn append_jsonb_node(node_type: u8, payload: &[u8], out: &mut Vec<u8>) -> Result<()> {
847 let (len_size, len_bytes) = encode_jsonb_payload_len(payload.len())?;
848 let len_size_u8 = u8::try_from(len_size).map_err(|error| {
849 FrankenError::function_error(format!("jsonb length-size conversion failed: {error}"))
850 })?;
851 let header = (len_size_u8 << 4) | node_type;
853 out.push(header);
854 out.extend_from_slice(&len_bytes[..len_size]);
855 out.extend_from_slice(payload);
856 Ok(())
857}
858
859fn encode_jsonb_payload_len(payload_len: usize) -> Result<(usize, [u8; 8])> {
860 if payload_len == 0 {
861 return Ok((0, [0; 8]));
862 }
863
864 let payload_u64 = u64::try_from(payload_len).map_err(|error| {
865 FrankenError::function_error(format!("jsonb payload too large: {error}"))
866 })?;
867 let len_size = if u8::try_from(payload_u64).is_ok() {
868 1
869 } else if u16::try_from(payload_u64).is_ok() {
870 2
871 } else if u32::try_from(payload_u64).is_ok() {
872 4
873 } else {
874 8
875 };
876
877 let raw = payload_u64.to_be_bytes();
878 let mut out = [0u8; 8];
879 out[..len_size].copy_from_slice(&raw[8 - len_size..]);
880 Ok((len_size, out))
881}
882
883fn decode_jsonb_root(input: &[u8]) -> Result<Value> {
884 let (value, consumed) = decode_jsonb_value(input)?;
885 if consumed != input.len() {
886 return Err(FrankenError::function_error(
887 "invalid JSONB: trailing bytes",
888 ));
889 }
890 Ok(value)
891}
892
893fn decode_jsonb_value(input: &[u8]) -> Result<(Value, usize)> {
894 let (node_type, payload, consumed) = decode_jsonb_node(input)?;
895 let value = match node_type {
896 JSONB_NULL_TYPE => {
897 if !payload.is_empty() {
898 return Err(FrankenError::function_error("invalid JSONB null payload"));
899 }
900 Value::Null
901 }
902 JSONB_TRUE_TYPE => {
903 if !payload.is_empty() {
904 return Err(FrankenError::function_error("invalid JSONB true payload"));
905 }
906 Value::Bool(true)
907 }
908 JSONB_FALSE_TYPE => {
909 if !payload.is_empty() {
910 return Err(FrankenError::function_error("invalid JSONB false payload"));
911 }
912 Value::Bool(false)
913 }
914 JSONB_INT_TYPE => {
915 if payload.len() != 8 {
916 return Err(FrankenError::function_error(
917 "invalid JSONB integer payload size",
918 ));
919 }
920 let mut raw = [0u8; 8];
921 raw.copy_from_slice(payload);
922 Value::Number(Number::from(i64::from_be_bytes(raw)))
923 }
924 JSONB_FLOAT_TYPE => {
925 if payload.len() != 8 {
926 return Err(FrankenError::function_error(
927 "invalid JSONB float payload size",
928 ));
929 }
930 let mut raw = [0u8; 8];
931 raw.copy_from_slice(payload);
932 let float = f64::from_bits(u64::from_be_bytes(raw));
933 let number = Number::from_f64(float).ok_or_else(|| {
934 FrankenError::function_error("invalid non-finite JSONB float payload")
935 })?;
936 Value::Number(number)
937 }
938 JSONB_TEXT_TYPE | JSONB_TEXT_JSON_TYPE => {
939 let text = String::from_utf8(payload.to_vec()).map_err(|error| {
940 FrankenError::function_error(format!("invalid JSONB text payload: {error}"))
941 })?;
942 Value::String(text)
943 }
944 JSONB_ARRAY_TYPE => {
945 let mut cursor = 0usize;
946 let mut values = Vec::new();
947 while cursor < payload.len() {
948 let (item, used) = decode_jsonb_value(&payload[cursor..])?;
949 values.push(item);
950 cursor += used;
951 }
952 Value::Array(values)
953 }
954 JSONB_OBJECT_TYPE => {
955 let mut cursor = 0usize;
956 let mut map = Map::new();
957 while cursor < payload.len() {
958 let (key_node, key_used) = decode_jsonb_value(&payload[cursor..])?;
959 cursor += key_used;
960 let Value::String(key) = key_node else {
961 return Err(FrankenError::function_error(
962 "invalid JSONB object key payload",
963 ));
964 };
965 if cursor >= payload.len() {
966 return Err(FrankenError::function_error(
967 "invalid JSONB object missing value",
968 ));
969 }
970 let (item, used) = decode_jsonb_value(&payload[cursor..])?;
971 cursor += used;
972 map.insert(key, item);
973 }
974 Value::Object(map)
975 }
976 _ => {
977 return Err(FrankenError::function_error("invalid JSONB node type"));
978 }
979 };
980
981 Ok((value, consumed))
982}
983
984fn decode_jsonb_node(input: &[u8]) -> Result<(u8, &[u8], usize)> {
985 if input.is_empty() {
986 return Err(FrankenError::function_error("invalid JSONB: empty payload"));
987 }
988
989 let header = input[0];
990 let node_type = header & 0x0f;
992 let len_size = usize::from(header >> 4);
993 if !matches!(len_size, 0 | 1 | 2 | 4 | 8) {
994 return Err(FrankenError::function_error(
995 "invalid JSONB length-size nibble",
996 ));
997 }
998 if !matches!(
999 node_type,
1000 JSONB_NULL_TYPE
1001 | JSONB_TRUE_TYPE
1002 | JSONB_FALSE_TYPE
1003 | JSONB_INT_TYPE
1004 | JSONB_FLOAT_TYPE
1005 | JSONB_TEXT_TYPE
1006 | JSONB_TEXT_JSON_TYPE
1007 | JSONB_ARRAY_TYPE
1008 | JSONB_OBJECT_TYPE
1009 ) {
1010 return Err(FrankenError::function_error("invalid JSONB node type"));
1011 }
1012
1013 if input.len() < 1 + len_size {
1014 return Err(FrankenError::function_error(
1015 "invalid JSONB: truncated payload length",
1016 ));
1017 }
1018
1019 let len_end = 1 + len_size;
1020 let payload_len = decode_jsonb_payload_len(&input[1..len_end])?;
1021 let total = 1 + len_size + payload_len;
1022 if input.len() < total {
1023 return Err(FrankenError::function_error(
1024 "invalid JSONB: truncated payload",
1025 ));
1026 }
1027
1028 Ok((node_type, &input[1 + len_size..total], total))
1029}
1030
1031fn decode_jsonb_payload_len(bytes: &[u8]) -> Result<usize> {
1032 if bytes.is_empty() {
1033 return Ok(0);
1034 }
1035 if !matches!(bytes.len(), 1 | 2 | 4 | 8) {
1036 return Err(FrankenError::function_error(
1037 "invalid JSONB length encoding size",
1038 ));
1039 }
1040
1041 let mut raw = [0u8; 8];
1042 raw[8 - bytes.len()..].copy_from_slice(bytes);
1043 let payload_len = u64::from_be_bytes(raw);
1044 usize::try_from(payload_len).map_err(|error| {
1045 FrankenError::function_error(format!("JSONB payload length overflow: {error}"))
1046 })
1047}
1048
1049fn is_superficially_valid_jsonb(input: &[u8]) -> bool {
1050 if input.is_empty() {
1051 return false;
1052 }
1053 let header = input[0];
1054 let node_type = header & 0x0f;
1056 let len_size = usize::from(header >> 4);
1057 if !matches!(len_size, 0 | 1 | 2 | 4 | 8) {
1058 return false;
1059 }
1060 if !matches!(
1061 node_type,
1062 JSONB_NULL_TYPE
1063 | JSONB_TRUE_TYPE
1064 | JSONB_FALSE_TYPE
1065 | JSONB_INT_TYPE
1066 | JSONB_FLOAT_TYPE
1067 | JSONB_TEXT_TYPE
1068 | JSONB_TEXT_JSON_TYPE
1069 | JSONB_ARRAY_TYPE
1070 | JSONB_OBJECT_TYPE
1071 ) {
1072 return false;
1073 }
1074 if input.len() < 1 + len_size {
1075 return false;
1076 }
1077 let len_end = 1 + len_size;
1078 let Ok(payload_len) = decode_jsonb_payload_len(&input[1..len_end]) else {
1079 return false;
1080 };
1081 1 + len_size + payload_len == input.len()
1082}
1083
1084#[allow(clippy::too_many_lines)]
1085fn parse_path(path: &str) -> Result<Vec<PathSegment>> {
1086 let bytes = path.as_bytes();
1087 if bytes.first().copied() != Some(b'$') {
1088 return Err(FrankenError::function_error(format!(
1089 "invalid json path `{path}`: must start with `$`"
1090 )));
1091 }
1092
1093 let mut idx = 1;
1094 let mut segments = Vec::new();
1095 while idx < bytes.len() {
1096 match bytes[idx] {
1097 b'.' => {
1098 idx += 1;
1099 if idx >= bytes.len() {
1100 return Err(FrankenError::function_error(format!(
1101 "invalid json path `{path}`: empty key segment"
1102 )));
1103 }
1104 if bytes[idx] == b'"' {
1107 let quoted_start = idx;
1108 idx += 1;
1109 let mut escaped = false;
1110 while idx < bytes.len() {
1111 let byte = bytes[idx];
1112 if escaped {
1113 escaped = false;
1114 idx += 1;
1115 continue;
1116 }
1117 if byte == b'\\' {
1118 escaped = true;
1119 idx += 1;
1120 continue;
1121 }
1122 if byte == b'"' {
1123 break;
1124 }
1125 idx += 1;
1126 }
1127 if idx >= bytes.len() {
1128 return Err(FrankenError::function_error(format!(
1129 "invalid json path `{path}`: missing closing quote in key segment"
1130 )));
1131 }
1132 let quoted_key = &path[quoted_start..=idx];
1133 let key = serde_json::from_str::<String>(quoted_key).map_err(|error| {
1134 FrankenError::function_error(format!(
1135 "invalid json path `{path}` quoted key `{quoted_key}`: {error}"
1136 ))
1137 })?;
1138 idx += 1; segments.push(PathSegment::Key(key));
1140 } else {
1141 let start = idx;
1142 while idx < bytes.len() && bytes[idx] != b'.' && bytes[idx] != b'[' {
1143 idx += 1;
1144 }
1145 if start == idx {
1146 return Err(FrankenError::function_error(format!(
1147 "invalid json path `{path}`: empty key segment"
1148 )));
1149 }
1150 segments.push(PathSegment::Key(path[start..idx].to_owned()));
1151 }
1152 }
1153 b'[' => {
1154 idx += 1;
1155 let start = idx;
1156 let mut escaped = false;
1157 while idx < bytes.len() {
1158 let byte = bytes[idx];
1159 if escaped {
1160 escaped = false;
1161 idx += 1;
1162 continue;
1163 }
1164 if byte == b'\\' {
1165 escaped = true;
1166 idx += 1;
1167 continue;
1168 }
1169 if byte == b']' {
1170 break;
1171 }
1172 idx += 1;
1173 }
1174 if idx >= bytes.len() {
1175 return Err(FrankenError::function_error(format!(
1176 "invalid json path `{path}`: missing closing `]`"
1177 )));
1178 }
1179 let segment_text = &path[start..idx];
1180 idx += 1;
1181
1182 if segment_text == "#" {
1183 segments.push(PathSegment::Append);
1184 } else if let Some(rest) = segment_text.strip_prefix("#-") {
1185 let from_end = rest.parse::<usize>().map_err(|error| {
1186 FrankenError::function_error(format!(
1187 "invalid json path `{path}` from-end index `{segment_text}`: {error}"
1188 ))
1189 })?;
1190 if from_end == 0 {
1191 return Err(FrankenError::function_error(format!(
1192 "invalid json path `{path}`: from-end index must be >= 1"
1193 )));
1194 }
1195 segments.push(PathSegment::FromEnd(from_end));
1196 } else {
1197 let index = segment_text.parse::<usize>().map_err(|error| {
1198 FrankenError::function_error(format!(
1199 "invalid json path `{path}` array index `{segment_text}`: {error}"
1200 ))
1201 })?;
1202 segments.push(PathSegment::Index(index));
1203 }
1204 }
1205 _ => {
1206 return Err(FrankenError::function_error(format!(
1207 "invalid json path `{path}` at byte offset {idx}"
1208 )));
1209 }
1210 }
1211 }
1212
1213 Ok(segments)
1214}
1215
1216fn resolve_path<'a>(root: &'a Value, path: &str) -> Result<Option<&'a Value>> {
1217 let segments = parse_path(path)?;
1218 let mut cursor = root;
1219
1220 for segment in segments {
1221 match segment {
1222 PathSegment::Key(key) => {
1223 let Some(next) = cursor.get(&key) else {
1224 return Ok(None);
1225 };
1226 cursor = next;
1227 }
1228 PathSegment::Index(index) => {
1229 let Some(array) = cursor.as_array() else {
1230 return Ok(None);
1231 };
1232 let Some(next) = array.get(index) else {
1233 return Ok(None);
1234 };
1235 cursor = next;
1236 }
1237 PathSegment::FromEnd(from_end) => {
1238 let Some(array) = cursor.as_array() else {
1239 return Ok(None);
1240 };
1241 if from_end > array.len() {
1242 return Ok(None);
1243 }
1244 let index = array.len() - from_end;
1245 cursor = &array[index];
1246 }
1247 PathSegment::Append => return Ok(None),
1248 }
1249 }
1250
1251 Ok(Some(cursor))
1252}
1253
1254fn append_object_path(base: &str, key: &str) -> String {
1255 if key.contains(|c: char| matches!(c, '.' | '[' | ']' | '"' | '\'') || c.is_whitespace()) {
1258 format!("{base}.\"{}\"", key.replace('"', "\\\""))
1259 } else {
1260 format!("{base}.{key}")
1261 }
1262}
1263
1264fn append_array_path(base: &str, index: usize) -> String {
1265 format!("{base}[{index}]")
1266}
1267
1268fn json_value_column(value: &Value) -> Result<SqliteValue> {
1269 match value {
1270 Value::Array(_) | Value::Object(_) => serde_json::to_string(value)
1271 .map(|s| SqliteValue::Text(Arc::from(s)))
1272 .map_err(|error| {
1273 FrankenError::function_error(format!("json table value encode failed: {error}"))
1274 }),
1275 _ => Ok(json_to_sqlite_scalar(value)),
1276 }
1277}
1278
1279fn json_atom_column(value: &Value) -> SqliteValue {
1280 match value {
1281 Value::Array(_) | Value::Object(_) => SqliteValue::Null,
1282 _ => json_to_sqlite_scalar(value),
1283 }
1284}
1285
1286fn append_tree_rows(
1287 rows: &mut Vec<JsonTableRow>,
1288 value: &Value,
1289 key: SqliteValue,
1290 parent_id: Option<i64>,
1291 fullkey: &str,
1292 path: &str,
1293 next_id: &mut i64,
1294) -> Result<()> {
1295 let current_id = *next_id;
1296 *next_id += 1;
1297
1298 rows.push(JsonTableRow {
1299 key,
1300 value: json_value_column(value)?,
1301 type_name: json_type_name(value),
1302 atom: json_atom_column(value),
1303 id: current_id,
1304 parent: parent_id.map_or(SqliteValue::Null, SqliteValue::Integer),
1305 fullkey: fullkey.to_owned(),
1306 path: path.to_owned(),
1307 });
1308
1309 match value {
1310 Value::Array(array) => {
1311 for (index, item) in array.iter().enumerate() {
1312 let index_i64 = i64::try_from(index).map_err(|error| {
1313 FrankenError::function_error(format!("json_tree index overflow: {error}"))
1314 })?;
1315 let child_fullkey = append_array_path(fullkey, index);
1316 append_tree_rows(
1317 rows,
1318 item,
1319 SqliteValue::Integer(index_i64),
1320 Some(current_id),
1321 &child_fullkey,
1322 fullkey,
1323 next_id,
1324 )?;
1325 }
1326 }
1327 Value::Object(object) => {
1328 for (child_key, item) in object {
1329 let child_fullkey = append_object_path(fullkey, child_key);
1330 append_tree_rows(
1331 rows,
1332 item,
1333 SqliteValue::Text(Arc::from(child_key.as_str())),
1334 Some(current_id),
1335 &child_fullkey,
1336 fullkey,
1337 next_id,
1338 )?;
1339 }
1340 }
1341 _ => {}
1342 }
1343
1344 Ok(())
1345}
1346
1347fn parse_json_table_filter_args(args: &[SqliteValue]) -> Result<(Value, Option<&str>)> {
1348 let Some(input_arg) = args.first() else {
1349 return Err(FrankenError::function_error(
1350 "json table-valued functions require JSON input argument",
1351 ));
1352 };
1353 let input_value = match input_arg {
1354 SqliteValue::Text(input_text) => parse_json_text(input_text)?,
1355 SqliteValue::Blob(input_blob) => parse_json_input_blob(input_blob)?,
1356 _ => {
1357 return Err(FrankenError::function_error(
1358 "json table-valued input must be TEXT or BLOB JSON",
1359 ));
1360 }
1361 };
1362
1363 let path = match args.get(1) {
1364 None | Some(SqliteValue::Null) => None,
1365 Some(SqliteValue::Text(path)) => Some(&**path),
1366 Some(_) => {
1367 return Err(FrankenError::function_error(
1368 "json table-valued PATH argument must be TEXT or NULL",
1369 ));
1370 }
1371 };
1372
1373 Ok((input_value, path))
1374}
1375
1376fn write_json_table_column(row: &JsonTableRow, ctx: &mut ColumnContext, col: i32) -> Result<()> {
1377 let value = match col {
1378 0 => row.key.clone(),
1379 1 => row.value.clone(),
1380 2 => SqliteValue::Text(Arc::from(row.type_name)),
1381 3 => row.atom.clone(),
1382 4 => SqliteValue::Integer(row.id),
1383 5 => row.parent.clone(),
1384 6 => SqliteValue::Text(Arc::from(row.fullkey.as_str())),
1385 7 => SqliteValue::Text(Arc::from(row.path.as_str())),
1386 _ => {
1387 return Err(FrankenError::function_error(format!(
1388 "json table-valued invalid column index {col}"
1389 )));
1390 }
1391 };
1392 ctx.set_value(value);
1393 Ok(())
1394}
1395
1396fn json_type_name(value: &Value) -> &'static str {
1397 match value {
1398 Value::Null => "null",
1399 Value::Bool(true) => "true",
1400 Value::Bool(false) => "false",
1401 Value::Number(number) => {
1402 if number.is_i64() || number.is_u64() {
1403 "integer"
1404 } else {
1405 "real"
1406 }
1407 }
1408 Value::String(_) => "text",
1409 Value::Array(_) => "array",
1410 Value::Object(_) => "object",
1411 }
1412}
1413
1414fn json_to_sqlite_scalar(value: &Value) -> SqliteValue {
1415 match value {
1416 Value::Null => SqliteValue::Null,
1417 Value::Bool(true) => SqliteValue::Integer(1),
1418 Value::Bool(false) => SqliteValue::Integer(0),
1419 Value::Number(number) => {
1420 if let Some(i) = number.as_i64() {
1421 SqliteValue::Integer(i)
1422 } else if let Some(u) = number.as_u64() {
1423 if let Ok(i) = i64::try_from(u) {
1424 SqliteValue::Integer(i)
1425 } else {
1426 SqliteValue::Float(u as f64)
1427 }
1428 } else {
1429 SqliteValue::Float(number.as_f64().unwrap_or(0.0))
1430 }
1431 }
1432 Value::String(text) => SqliteValue::Text(Arc::from(text.as_str())),
1433 Value::Array(_) | Value::Object(_) => {
1434 let encoded = serde_json::to_string(value).unwrap_or_else(|_| "null".to_owned());
1435 SqliteValue::Text(Arc::from(encoded))
1436 }
1437 }
1438}
1439
1440fn sqlite_to_json(value: &SqliteValue) -> Result<Value> {
1441 match value {
1442 SqliteValue::Null => Ok(Value::Null),
1443 SqliteValue::Integer(i) => Ok(Value::Number(Number::from(*i))),
1444 SqliteValue::Float(f) => {
1445 if !f.is_finite() {
1446 return Err(FrankenError::function_error(
1447 "non-finite float is not representable in JSON",
1448 ));
1449 }
1450 Number::from_f64(*f).map(Value::Number).ok_or_else(|| {
1451 FrankenError::function_error("failed to convert floating-point value to JSON")
1452 })
1453 }
1454 SqliteValue::Text(text) => Ok(Value::String(text.to_string())),
1455 SqliteValue::Blob(_) => Err(FrankenError::function_error("JSON cannot hold BLOB values")),
1456 }
1457}
1458
1459fn write_pretty_value(value: &Value, indent: &str, depth: usize, out: &mut String) -> Result<()> {
1460 match value {
1461 Value::Array(array) => {
1462 if array.is_empty() {
1463 out.push_str("[]");
1464 return Ok(());
1465 }
1466
1467 out.push('[');
1468 out.push('\n');
1469 for (idx, item) in array.iter().enumerate() {
1470 out.push_str(&indent.repeat(depth + 1));
1471 write_pretty_value(item, indent, depth + 1, out)?;
1472 if idx + 1 < array.len() {
1473 out.push(',');
1474 }
1475 out.push('\n');
1476 }
1477 out.push_str(&indent.repeat(depth));
1478 out.push(']');
1479 Ok(())
1480 }
1481 Value::Object(object) => {
1482 if object.is_empty() {
1483 out.push_str("{}");
1484 return Ok(());
1485 }
1486
1487 out.push('{');
1488 out.push('\n');
1489 for (idx, (key, item)) in object.iter().enumerate() {
1490 out.push_str(&indent.repeat(depth + 1));
1491 let key_quoted = serde_json::to_string(key).map_err(|error| {
1492 FrankenError::function_error(format!(
1493 "json_pretty key-encode failed for `{key}`: {error}"
1494 ))
1495 })?;
1496 out.push_str(&key_quoted);
1497 out.push_str(": ");
1498 write_pretty_value(item, indent, depth + 1, out)?;
1499 if idx + 1 < object.len() {
1500 out.push(',');
1501 }
1502 out.push('\n');
1503 }
1504 out.push_str(&indent.repeat(depth));
1505 out.push('}');
1506 Ok(())
1507 }
1508 _ => {
1509 let encoded = serde_json::to_string(value).map_err(|error| {
1510 FrankenError::function_error(format!("json_pretty value-encode failed: {error}"))
1511 })?;
1512 out.push_str(&encoded);
1513 Ok(())
1514 }
1515 }
1516}
1517
1518fn apply_edit(root: &mut Value, segments: &[PathSegment], new_value: Value, mode: EditMode) {
1519 if segments.is_empty() {
1520 match mode {
1521 EditMode::Set | EditMode::Replace => *root = new_value,
1522 EditMode::Insert => {}
1523 }
1524 return;
1525 }
1526 if !matches!(root, Value::Object(_) | Value::Array(_)) {
1527 return;
1530 }
1531
1532 let original = root.clone();
1533 let (parent_segments, last) = segments.split_at(segments.len() - 1);
1534 let Some(last_segment) = last.first() else {
1535 return;
1536 };
1537 let Some(parent) = resolve_parent_for_edit(root, parent_segments, Some(last_segment), mode)
1538 else {
1539 *root = original;
1540 return;
1541 };
1542
1543 let applied = match (parent, last_segment) {
1544 (Value::Object(object), PathSegment::Key(key)) => {
1545 let exists = object.contains_key(key);
1546 match mode {
1547 EditMode::Set => {
1548 object.insert(key.clone(), new_value);
1549 true
1550 }
1551 EditMode::Insert => {
1552 if exists {
1553 false
1554 } else {
1555 object.insert(key.clone(), new_value);
1556 true
1557 }
1558 }
1559 EditMode::Replace => {
1560 if exists {
1561 object.insert(key.clone(), new_value);
1562 true
1563 } else {
1564 false
1565 }
1566 }
1567 }
1568 }
1569 (Value::Array(array), PathSegment::Index(index)) => {
1570 apply_array_edit(array, *index, new_value, mode)
1571 }
1572 (Value::Array(array), PathSegment::Append) => {
1573 if matches!(mode, EditMode::Set | EditMode::Insert) {
1574 array.push(new_value);
1575 true
1576 } else {
1577 false
1578 }
1579 }
1580 (Value::Array(array), PathSegment::FromEnd(from_end)) => {
1581 if *from_end == 0 || *from_end > array.len() {
1582 false
1583 } else {
1584 let index = array.len() - *from_end;
1585 apply_array_edit(array, index, new_value, mode)
1586 }
1587 }
1588 _ => false,
1589 };
1590
1591 if !applied {
1592 *root = original;
1593 }
1594}
1595
1596fn apply_array_edit(
1597 array: &mut Vec<Value>,
1598 index: usize,
1599 new_value: Value,
1600 mode: EditMode,
1601) -> bool {
1602 if index > array.len() {
1603 return false;
1604 }
1605
1606 if index == array.len() {
1607 if matches!(mode, EditMode::Set | EditMode::Insert) {
1608 array.push(new_value);
1609 return true;
1610 }
1611 return false;
1612 }
1613
1614 match mode {
1615 EditMode::Set | EditMode::Replace => {
1616 array[index] = new_value;
1617 true
1618 }
1619 EditMode::Insert => false,
1620 }
1621}
1622
1623fn remove_at_path(root: &mut Value, segments: &[PathSegment]) {
1624 if segments.is_empty() {
1625 *root = Value::Null;
1626 return;
1627 }
1628
1629 let (parent_segments, last) = segments.split_at(segments.len() - 1);
1630 let Some(last_segment) = last.first() else {
1631 return;
1632 };
1633 let Some(parent) = resolve_path_mut(root, parent_segments) else {
1634 return;
1635 };
1636
1637 match (parent, last_segment) {
1638 (Value::Object(object), PathSegment::Key(key)) => {
1639 object.remove(key);
1640 }
1641 (Value::Array(array), PathSegment::Index(index)) => {
1642 if *index < array.len() {
1643 array.remove(*index);
1644 }
1645 }
1646 (Value::Array(array), PathSegment::FromEnd(from_end)) => {
1647 if *from_end == 0 || *from_end > array.len() {
1648 return;
1649 }
1650 let index = array.len() - *from_end;
1651 array.remove(index);
1652 }
1653 _ => {}
1654 }
1655}
1656
1657fn resolve_path_mut<'a>(root: &'a mut Value, segments: &[PathSegment]) -> Option<&'a mut Value> {
1658 let mut cursor = root;
1659
1660 for segment in segments {
1661 match segment {
1662 PathSegment::Key(key) => {
1663 let next = cursor.as_object_mut()?.get_mut(key)?;
1664 cursor = next;
1665 }
1666 PathSegment::Index(index) => {
1667 let next = cursor.as_array_mut()?.get_mut(*index)?;
1668 cursor = next;
1669 }
1670 PathSegment::FromEnd(from_end) => {
1671 let array = cursor.as_array_mut()?;
1672 if *from_end == 0 || *from_end > array.len() {
1673 return None;
1674 }
1675 let index = array.len() - *from_end;
1676 let next = array.get_mut(index)?;
1677 cursor = next;
1678 }
1679 PathSegment::Append => return None,
1680 }
1681 }
1682
1683 Some(cursor)
1684}
1685
1686fn resolve_parent_for_edit<'a>(
1687 root: &'a mut Value,
1688 segments: &[PathSegment],
1689 tail_hint: Option<&PathSegment>,
1690 mode: EditMode,
1691) -> Option<&'a mut Value> {
1692 fn scaffold_for_next_segment(next: Option<&PathSegment>) -> Value {
1693 match next {
1694 Some(PathSegment::Index(_) | PathSegment::Append | PathSegment::FromEnd(_)) => {
1695 Value::Array(Vec::new())
1696 }
1697 _ => Value::Object(Map::new()),
1698 }
1699 }
1700
1701 let mut cursor = root;
1702
1703 for (idx, segment) in segments.iter().enumerate() {
1704 let next_segment = segments.get(idx + 1).or_else(|| {
1705 if idx + 1 == segments.len() {
1706 tail_hint
1707 } else {
1708 None
1709 }
1710 });
1711 match segment {
1712 PathSegment::Key(key) => {
1713 if cursor.is_null() {
1714 if matches!(mode, EditMode::Set | EditMode::Insert) {
1715 *cursor = Value::Object(Map::new());
1716 } else {
1717 return None;
1718 }
1719 }
1720
1721 let object = match cursor {
1722 Value::Object(o) => o,
1723 _ => return None,
1724 };
1725
1726 if !object.contains_key(key) {
1727 if !matches!(mode, EditMode::Set | EditMode::Insert) {
1728 return None;
1729 }
1730 object.insert(key.clone(), scaffold_for_next_segment(next_segment));
1731 }
1732 cursor = object.get_mut(key).expect("just inserted or checked");
1733 }
1734 PathSegment::Index(index) => {
1735 if cursor.is_null() {
1736 if matches!(mode, EditMode::Set | EditMode::Insert) {
1737 *cursor = Value::Array(Vec::new());
1738 } else {
1739 return None;
1740 }
1741 }
1742 let array = match cursor {
1743 Value::Array(a) => a,
1744 _ => return None,
1745 };
1746 if *index > array.len() {
1747 return None;
1748 }
1749 if *index == array.len() {
1750 if !matches!(mode, EditMode::Set | EditMode::Insert) {
1751 return None;
1752 }
1753 array.push(scaffold_for_next_segment(next_segment));
1754 }
1755 cursor = array.get_mut(*index).expect("just pushed or checked");
1756 }
1757 PathSegment::Append => {
1758 if cursor.is_null() {
1759 if matches!(mode, EditMode::Set | EditMode::Insert) {
1760 *cursor = Value::Array(Vec::new());
1761 } else {
1762 return None;
1763 }
1764 }
1765 let array = match cursor {
1766 Value::Array(a) => a,
1767 _ => return None,
1768 };
1769 if !matches!(mode, EditMode::Set | EditMode::Insert) {
1770 return None;
1771 }
1772 array.push(scaffold_for_next_segment(next_segment));
1773 cursor = array.last_mut().expect("just pushed");
1774 }
1775 PathSegment::FromEnd(from_end) => {
1776 let array = match cursor {
1777 Value::Array(a) => a,
1778 _ => return None,
1779 };
1780 if *from_end == 0 || *from_end > array.len() {
1781 return None;
1782 }
1783 let index = array.len() - *from_end;
1784 cursor = array.get_mut(index).expect("checked length");
1785 }
1786 }
1787 }
1788
1789 Some(cursor)
1790}
1791
1792fn merge_patch(target: Value, patch: Value) -> Value {
1793 match patch {
1794 Value::Object(patch_map) => {
1795 let mut target_map = match target {
1796 Value::Object(map) => map,
1797 _ => Map::new(),
1798 };
1799
1800 for (key, patch_value) in patch_map {
1801 if patch_value.is_null() {
1802 target_map.remove(&key);
1803 continue;
1804 }
1805 if let Some(prior) = target_map.get_mut(&key) {
1806 let old_val = std::mem::replace(prior, Value::Null);
1807 *prior = merge_patch(old_val, patch_value);
1808 } else {
1809 target_map.insert(key, merge_patch(Value::Null, patch_value));
1810 }
1811 }
1812
1813 Value::Object(target_map)
1814 }
1815 other => other,
1816 }
1817}
1818
1819fn invalid_arity(name: &str, expected: &str, got: usize) -> FrankenError {
1824 FrankenError::function_error(format!("{name} expects {expected}; got {got} argument(s)"))
1825}
1826
1827fn text_arg<'a>(name: &str, args: &'a [SqliteValue], index: usize) -> Result<&'a str> {
1828 match args.get(index) {
1829 Some(SqliteValue::Text(text)) => Ok(&**text),
1830 Some(other) => Err(FrankenError::function_error(format!(
1831 "{name} argument {} must be TEXT, got {}",
1832 index + 1,
1833 other.typeof_str()
1834 ))),
1835 None => Err(FrankenError::function_error(format!(
1836 "{name} missing argument {}",
1837 index + 1
1838 ))),
1839 }
1840}
1841
1842fn json_arg_value(name: &str, args: &[SqliteValue], index: usize) -> Result<Value> {
1843 match args.get(index) {
1844 Some(SqliteValue::Text(text)) => parse_json_text(text),
1845 Some(SqliteValue::Blob(bytes)) => parse_json_input_blob(bytes),
1846 Some(other) => Err(FrankenError::function_error(format!(
1847 "{name} argument {} must be TEXT or BLOB, got {}",
1848 index + 1,
1849 other.typeof_str()
1850 ))),
1851 None => Err(FrankenError::function_error(format!(
1852 "{name} missing argument {}",
1853 index + 1
1854 ))),
1855 }
1856}
1857
1858fn optional_flags_arg(name: &str, args: &[SqliteValue], index: usize) -> Result<Option<u8>> {
1859 let Some(value) = args.get(index) else {
1860 return Ok(None);
1861 };
1862 let raw = value.to_integer();
1863 let flags = u8::try_from(raw).map_err(|_| {
1864 FrankenError::function_error(format!("{name} flags out of range for u8: {raw}"))
1865 })?;
1866 Ok(Some(flags))
1867}
1868
1869fn usize_to_i64(name: &str, value: usize) -> Result<i64> {
1870 i64::try_from(value).map_err(|_| {
1871 FrankenError::function_error(format!("{name} result does not fit in i64: {value}"))
1872 })
1873}
1874
1875fn collect_path_args<'a>(
1876 name: &str,
1877 args: &'a [SqliteValue],
1878 start: usize,
1879) -> Result<Vec<&'a str>> {
1880 let mut out = Vec::with_capacity(args.len().saturating_sub(start));
1881 for idx in start..args.len() {
1882 out.push(text_arg(name, args, idx)?);
1883 }
1884 Ok(out)
1885}
1886
1887fn normalize_arrow_path_arg<'a>(
1888 name: &str,
1889 value: &'a SqliteValue,
1890 index: usize,
1891) -> Result<Cow<'a, str>> {
1892 match value {
1893 SqliteValue::Text(path) => {
1894 if path.starts_with('$') || path.is_empty() {
1895 Ok(Cow::Borrowed(&**path))
1896 } else {
1897 let quoted = serde_json::to_string(path).map_err(|error| {
1898 FrankenError::function_error(format!(
1899 "{name} argument {} key encoding failed: {error}",
1900 index + 1
1901 ))
1902 })?;
1903 Ok(Cow::Owned(format!("$.{quoted}")))
1904 }
1905 }
1906 SqliteValue::Integer(index_value) => {
1907 if *index_value >= 0 {
1908 Ok(Cow::Owned(format!("$[{index_value}]")))
1909 } else {
1910 Ok(Cow::Owned(format!("$[#-{}]", index_value.unsigned_abs())))
1911 }
1912 }
1913 other => Err(FrankenError::function_error(format!(
1914 "{name} argument {} must be TEXT or INTEGER, got {}",
1915 index + 1,
1916 other.typeof_str()
1917 ))),
1918 }
1919}
1920
1921fn invoke_json_arrow(name: &str, args: &[SqliteValue], double_arrow: bool) -> Result<SqliteValue> {
1922 if args.len() != 2 {
1923 return Err(invalid_arity(name, "exactly 2 arguments", args.len()));
1924 }
1925 if args.iter().any(SqliteValue::is_null) {
1926 return Ok(SqliteValue::Null);
1927 }
1928
1929 let input = json_arg_value(name, args, 0)?;
1930 let path = normalize_arrow_path_arg(name, &args[1], 1)?;
1931 if double_arrow {
1932 json_extract_value(&input, &[path.as_ref()])
1933 } else {
1934 json_arrow_value(&input, path.as_ref())
1935 }
1936}
1937
1938fn collect_path_value_pairs(
1939 name: &str,
1940 args: &[SqliteValue],
1941 start: usize,
1942) -> Result<Vec<(String, SqliteValue)>> {
1943 let mut pairs = Vec::with_capacity((args.len().saturating_sub(start)) / 2);
1944 let mut idx = start;
1945 while idx < args.len() {
1946 let path = text_arg(name, args, idx)?.to_owned();
1947 let value = args[idx + 1].clone();
1948 pairs.push((path, value));
1949 idx += 2;
1950 }
1951 Ok(pairs)
1952}
1953
1954pub struct JsonFunc;
1955
1956impl ScalarFunction for JsonFunc {
1957 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
1958 if args.len() != 1 {
1959 return Err(invalid_arity(self.name(), "exactly 1 argument", args.len()));
1960 }
1961 if matches!(args[0], SqliteValue::Null) {
1962 return Ok(SqliteValue::Null);
1963 }
1964 let input = json_arg_value(self.name(), args, 0)?;
1965 let encoded = encode_json_text("json serialize failed", &input)?;
1966 Ok(SqliteValue::Text(Arc::from(encoded)))
1967 }
1968
1969 fn num_args(&self) -> i32 {
1970 1
1971 }
1972
1973 fn name(&self) -> &'static str {
1974 "json"
1975 }
1976}
1977
1978pub struct JsonbFunc;
1979
1980impl ScalarFunction for JsonbFunc {
1981 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
1982 if args.len() != 1 {
1983 return Err(invalid_arity(self.name(), "exactly 1 argument", args.len()));
1984 }
1985 if matches!(args[0], SqliteValue::Null) {
1986 return Ok(SqliteValue::Null);
1987 }
1988 let input = json_arg_value(self.name(), args, 0)?;
1989 let blob = encode_jsonb_root(&input)?;
1990 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
1991 }
1992
1993 fn num_args(&self) -> i32 {
1994 1
1995 }
1996
1997 fn name(&self) -> &'static str {
1998 "jsonb"
1999 }
2000}
2001
2002pub struct JsonValidFunc;
2003
2004impl ScalarFunction for JsonValidFunc {
2005 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2006 if !(1..=2).contains(&args.len()) {
2007 return Err(invalid_arity(self.name(), "1 or 2 arguments", args.len()));
2008 }
2009 let flags = optional_flags_arg(self.name(), args, 1)?;
2010 let value = match &args[0] {
2011 SqliteValue::Null => return Ok(SqliteValue::Null),
2012 SqliteValue::Text(text) => json_valid(text, flags),
2013 SqliteValue::Blob(bytes) => json_valid_blob(bytes, flags),
2014 _ => 0,
2015 };
2016 Ok(SqliteValue::Integer(value))
2017 }
2018
2019 fn num_args(&self) -> i32 {
2020 -1
2021 }
2022
2023 fn name(&self) -> &'static str {
2024 "json_valid"
2025 }
2026}
2027
2028pub struct JsonTypeFunc;
2029
2030impl ScalarFunction for JsonTypeFunc {
2031 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2032 if !(1..=2).contains(&args.len()) {
2033 return Err(invalid_arity(self.name(), "1 or 2 arguments", args.len()));
2034 }
2035 if matches!(args[0], SqliteValue::Null) {
2036 return Ok(SqliteValue::Null);
2037 }
2038 let input = json_arg_value(self.name(), args, 0)?;
2039 let path = if args.len() == 2 {
2040 if matches!(args[1], SqliteValue::Null) {
2041 return Ok(SqliteValue::Null);
2042 }
2043 Some(text_arg(self.name(), args, 1)?)
2044 } else {
2045 None
2046 };
2047 Ok(match json_type_value(&input, path)? {
2048 Some(kind) => SqliteValue::Text(Arc::from(kind)),
2049 None => SqliteValue::Null,
2050 })
2051 }
2052
2053 fn num_args(&self) -> i32 {
2054 -1
2055 }
2056
2057 fn name(&self) -> &'static str {
2058 "json_type"
2059 }
2060}
2061
2062pub struct JsonExtractFunc;
2063
2064impl ScalarFunction for JsonExtractFunc {
2065 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2066 if args.is_empty() {
2067 return Err(invalid_arity(
2068 self.name(),
2069 "at least 1 argument (json, path...)",
2070 args.len(),
2071 ));
2072 }
2073 if args.len() == 1 {
2074 return Ok(SqliteValue::Null);
2075 }
2076 if matches!(args[0], SqliteValue::Null) {
2077 return Ok(SqliteValue::Null);
2078 }
2079 if args[1..].iter().any(|a| matches!(a, SqliteValue::Null)) {
2081 return Ok(SqliteValue::Null);
2082 }
2083 let input = json_arg_value(self.name(), args, 0)?;
2084 let paths = collect_path_args(self.name(), args, 1)?;
2085 json_extract_value(&input, &paths)
2086 }
2087
2088 fn num_args(&self) -> i32 {
2089 -1
2090 }
2091
2092 fn name(&self) -> &'static str {
2093 "json_extract"
2094 }
2095}
2096
2097pub struct JsonbExtractFunc;
2098
2099impl ScalarFunction for JsonbExtractFunc {
2100 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2101 if args.is_empty() {
2102 return Err(invalid_arity(
2103 self.name(),
2104 "at least 1 argument (json, path...)",
2105 args.len(),
2106 ));
2107 }
2108 if args.len() == 1 {
2109 return Ok(SqliteValue::Null);
2110 }
2111 if matches!(args[0], SqliteValue::Null) {
2112 return Ok(SqliteValue::Null);
2113 }
2114 if args[1..].iter().any(|a| matches!(a, SqliteValue::Null)) {
2115 return Ok(SqliteValue::Null);
2116 }
2117 let input = json_arg_value(self.name(), args, 0)?;
2118 let paths = collect_path_args(self.name(), args, 1)?;
2119 let blob = jsonb_extract_value(&input, &paths)?;
2120 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2121 }
2122
2123 fn num_args(&self) -> i32 {
2124 -1
2125 }
2126
2127 fn name(&self) -> &'static str {
2128 "jsonb_extract"
2129 }
2130}
2131
2132pub struct JsonArrowFunc;
2133
2134impl ScalarFunction for JsonArrowFunc {
2135 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2136 invoke_json_arrow(self.name(), args, false)
2137 }
2138
2139 fn num_args(&self) -> i32 {
2140 2
2141 }
2142
2143 fn name(&self) -> &'static str {
2144 "json_arrow"
2145 }
2146}
2147
2148pub struct JsonDoubleArrowFunc;
2149
2150impl ScalarFunction for JsonDoubleArrowFunc {
2151 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2152 invoke_json_arrow(self.name(), args, true)
2153 }
2154
2155 fn num_args(&self) -> i32 {
2156 2
2157 }
2158
2159 fn name(&self) -> &'static str {
2160 "json_double_arrow"
2161 }
2162}
2163
2164pub struct JsonArrayFunc;
2165
2166impl ScalarFunction for JsonArrayFunc {
2167 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2168 let s = json_array(args)?;
2169 Ok(SqliteValue::Text(Arc::from(s)))
2170 }
2171
2172 fn num_args(&self) -> i32 {
2173 -1
2174 }
2175
2176 fn name(&self) -> &'static str {
2177 "json_array"
2178 }
2179}
2180
2181pub struct JsonbArrayFunc;
2182
2183impl ScalarFunction for JsonbArrayFunc {
2184 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2185 let blob = jsonb_array(args)?;
2186 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2187 }
2188
2189 fn num_args(&self) -> i32 {
2190 -1
2191 }
2192
2193 fn name(&self) -> &'static str {
2194 "jsonb_array"
2195 }
2196}
2197
2198pub struct JsonObjectFunc;
2199
2200impl ScalarFunction for JsonObjectFunc {
2201 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2202 let s = json_object(args)?;
2203 Ok(SqliteValue::Text(Arc::from(s)))
2204 }
2205
2206 fn num_args(&self) -> i32 {
2207 -1
2208 }
2209
2210 fn name(&self) -> &'static str {
2211 "json_object"
2212 }
2213}
2214
2215pub struct JsonbObjectFunc;
2216
2217impl ScalarFunction for JsonbObjectFunc {
2218 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2219 let blob = jsonb_object(args)?;
2220 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2221 }
2222
2223 fn num_args(&self) -> i32 {
2224 -1
2225 }
2226
2227 fn name(&self) -> &'static str {
2228 "jsonb_object"
2229 }
2230}
2231
2232pub struct JsonQuoteFunc;
2233
2234impl ScalarFunction for JsonQuoteFunc {
2235 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2236 if args.len() != 1 {
2237 return Err(invalid_arity(self.name(), "exactly 1 argument", args.len()));
2238 }
2239 let s = json_quote(&args[0])?;
2240 Ok(SqliteValue::Text(Arc::from(s)))
2241 }
2242
2243 fn num_args(&self) -> i32 {
2244 1
2245 }
2246
2247 fn name(&self) -> &'static str {
2248 "json_quote"
2249 }
2250}
2251
2252pub struct JsonSetFunc;
2253
2254impl ScalarFunction for JsonSetFunc {
2255 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2256 if args.len() < 3 || args.len() % 2 == 0 {
2257 return Err(invalid_arity(
2258 self.name(),
2259 "an odd argument count >= 3 (json, path, value, ...)",
2260 args.len(),
2261 ));
2262 }
2263 if matches!(args[0], SqliteValue::Null) {
2264 return Ok(SqliteValue::Null);
2265 }
2266 if args[1..]
2268 .iter()
2269 .step_by(2)
2270 .any(|a| matches!(a, SqliteValue::Null))
2271 {
2272 return Ok(SqliteValue::Null);
2273 }
2274 let input = json_arg_value(self.name(), args, 0)?;
2275 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2276 let pairs = pairs_owned
2277 .iter()
2278 .map(|(path, value)| (path.as_str(), value.clone()))
2279 .collect::<Vec<_>>();
2280 let edited = edit_json_paths_value(&input, &pairs, EditMode::Set)?;
2281 let encoded = encode_json_text("json edit encode failed", &edited)?;
2282 Ok(SqliteValue::Text(Arc::from(encoded)))
2283 }
2284
2285 fn num_args(&self) -> i32 {
2286 -1
2287 }
2288
2289 fn name(&self) -> &'static str {
2290 "json_set"
2291 }
2292}
2293
2294pub struct JsonbSetFunc;
2295
2296impl ScalarFunction for JsonbSetFunc {
2297 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2298 if args.len() < 3 || args.len() % 2 == 0 {
2299 return Err(invalid_arity(
2300 self.name(),
2301 "an odd argument count >= 3 (json, path, value, ...)",
2302 args.len(),
2303 ));
2304 }
2305 if matches!(args[0], SqliteValue::Null) {
2306 return Ok(SqliteValue::Null);
2307 }
2308 if args[1..]
2309 .iter()
2310 .step_by(2)
2311 .any(|a| matches!(a, SqliteValue::Null))
2312 {
2313 return Ok(SqliteValue::Null);
2314 }
2315 let input = json_arg_value(self.name(), args, 0)?;
2316 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2317 let pairs = pairs_owned
2318 .iter()
2319 .map(|(path, value)| (path.as_str(), value.clone()))
2320 .collect::<Vec<_>>();
2321 let edited = edit_json_paths_value(&input, &pairs, EditMode::Set)?;
2322 let blob = encode_jsonb_root(&edited)?;
2323 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2324 }
2325
2326 fn num_args(&self) -> i32 {
2327 -1
2328 }
2329
2330 fn name(&self) -> &'static str {
2331 "jsonb_set"
2332 }
2333}
2334
2335pub struct JsonInsertFunc;
2336
2337impl ScalarFunction for JsonInsertFunc {
2338 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2339 if args.len() < 3 || args.len() % 2 == 0 {
2340 return Err(invalid_arity(
2341 self.name(),
2342 "an odd argument count >= 3 (json, path, value, ...)",
2343 args.len(),
2344 ));
2345 }
2346 if matches!(args[0], SqliteValue::Null) {
2347 return Ok(SqliteValue::Null);
2348 }
2349 if args[1..]
2351 .iter()
2352 .step_by(2)
2353 .any(|a| matches!(a, SqliteValue::Null))
2354 {
2355 return Ok(SqliteValue::Null);
2356 }
2357 let input = json_arg_value(self.name(), args, 0)?;
2358 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2359 let pairs = pairs_owned
2360 .iter()
2361 .map(|(path, value)| (path.as_str(), value.clone()))
2362 .collect::<Vec<_>>();
2363 let edited = edit_json_paths_value(&input, &pairs, EditMode::Insert)?;
2364 let encoded = encode_json_text("json edit encode failed", &edited)?;
2365 Ok(SqliteValue::Text(Arc::from(encoded)))
2366 }
2367
2368 fn num_args(&self) -> i32 {
2369 -1
2370 }
2371
2372 fn name(&self) -> &'static str {
2373 "json_insert"
2374 }
2375}
2376
2377pub struct JsonbInsertFunc;
2378
2379impl ScalarFunction for JsonbInsertFunc {
2380 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2381 if args.len() < 3 || args.len() % 2 == 0 {
2382 return Err(invalid_arity(
2383 self.name(),
2384 "an odd argument count >= 3 (json, path, value, ...)",
2385 args.len(),
2386 ));
2387 }
2388 if matches!(args[0], SqliteValue::Null) {
2389 return Ok(SqliteValue::Null);
2390 }
2391 if args[1..]
2392 .iter()
2393 .step_by(2)
2394 .any(|a| matches!(a, SqliteValue::Null))
2395 {
2396 return Ok(SqliteValue::Null);
2397 }
2398 let input = json_arg_value(self.name(), args, 0)?;
2399 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2400 let pairs = pairs_owned
2401 .iter()
2402 .map(|(path, value)| (path.as_str(), value.clone()))
2403 .collect::<Vec<_>>();
2404 let edited = edit_json_paths_value(&input, &pairs, EditMode::Insert)?;
2405 let blob = encode_jsonb_root(&edited)?;
2406 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2407 }
2408
2409 fn num_args(&self) -> i32 {
2410 -1
2411 }
2412
2413 fn name(&self) -> &'static str {
2414 "jsonb_insert"
2415 }
2416}
2417
2418pub struct JsonReplaceFunc;
2419
2420impl ScalarFunction for JsonReplaceFunc {
2421 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2422 if args.len() < 3 || args.len() % 2 == 0 {
2423 return Err(invalid_arity(
2424 self.name(),
2425 "an odd argument count >= 3 (json, path, value, ...)",
2426 args.len(),
2427 ));
2428 }
2429 if matches!(args[0], SqliteValue::Null) {
2430 return Ok(SqliteValue::Null);
2431 }
2432 if args[1..]
2434 .iter()
2435 .step_by(2)
2436 .any(|a| matches!(a, SqliteValue::Null))
2437 {
2438 return Ok(SqliteValue::Null);
2439 }
2440 let input = json_arg_value(self.name(), args, 0)?;
2441 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2442 let pairs = pairs_owned
2443 .iter()
2444 .map(|(path, value)| (path.as_str(), value.clone()))
2445 .collect::<Vec<_>>();
2446 let edited = edit_json_paths_value(&input, &pairs, EditMode::Replace)?;
2447 let encoded = encode_json_text("json edit encode failed", &edited)?;
2448 Ok(SqliteValue::Text(Arc::from(encoded)))
2449 }
2450
2451 fn num_args(&self) -> i32 {
2452 -1
2453 }
2454
2455 fn name(&self) -> &'static str {
2456 "json_replace"
2457 }
2458}
2459
2460pub struct JsonbReplaceFunc;
2461
2462impl ScalarFunction for JsonbReplaceFunc {
2463 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2464 if args.len() < 3 || args.len() % 2 == 0 {
2465 return Err(invalid_arity(
2466 self.name(),
2467 "an odd argument count >= 3 (json, path, value, ...)",
2468 args.len(),
2469 ));
2470 }
2471 if matches!(args[0], SqliteValue::Null) {
2472 return Ok(SqliteValue::Null);
2473 }
2474 if args[1..]
2475 .iter()
2476 .step_by(2)
2477 .any(|a| matches!(a, SqliteValue::Null))
2478 {
2479 return Ok(SqliteValue::Null);
2480 }
2481 let input = json_arg_value(self.name(), args, 0)?;
2482 let pairs_owned = collect_path_value_pairs(self.name(), args, 1)?;
2483 let pairs = pairs_owned
2484 .iter()
2485 .map(|(path, value)| (path.as_str(), value.clone()))
2486 .collect::<Vec<_>>();
2487 let edited = edit_json_paths_value(&input, &pairs, EditMode::Replace)?;
2488 let blob = encode_jsonb_root(&edited)?;
2489 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2490 }
2491
2492 fn num_args(&self) -> i32 {
2493 -1
2494 }
2495
2496 fn name(&self) -> &'static str {
2497 "jsonb_replace"
2498 }
2499}
2500
2501pub struct JsonRemoveFunc;
2502
2503impl ScalarFunction for JsonRemoveFunc {
2504 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2505 if args.is_empty() {
2506 return Err(invalid_arity(
2507 self.name(),
2508 "at least 1 argument (json [, path...])",
2509 args.len(),
2510 ));
2511 }
2512 if matches!(args[0], SqliteValue::Null) {
2513 return Ok(SqliteValue::Null);
2514 }
2515 let input = json_arg_value(self.name(), args, 0)?;
2516 if args.len() == 1 {
2517 let encoded = encode_json_text("json serialize failed", &input)?;
2519 return Ok(SqliteValue::Text(Arc::from(encoded)));
2520 }
2521 if args[1..].iter().any(|a| matches!(a, SqliteValue::Null)) {
2523 return Ok(SqliteValue::Null);
2524 }
2525 let paths = collect_path_args(self.name(), args, 1)?;
2526 let edited = json_remove_value(&input, &paths)?;
2527 let encoded = encode_json_text("json_remove encode failed", &edited)?;
2528 Ok(SqliteValue::Text(Arc::from(encoded)))
2529 }
2530
2531 fn num_args(&self) -> i32 {
2532 -1
2533 }
2534
2535 fn name(&self) -> &'static str {
2536 "json_remove"
2537 }
2538}
2539
2540pub struct JsonbRemoveFunc;
2541
2542impl ScalarFunction for JsonbRemoveFunc {
2543 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2544 if args.is_empty() {
2545 return Err(invalid_arity(
2546 self.name(),
2547 "at least 1 argument (json [, path...])",
2548 args.len(),
2549 ));
2550 }
2551 if matches!(args[0], SqliteValue::Null) {
2552 return Ok(SqliteValue::Null);
2553 }
2554 let input = json_arg_value(self.name(), args, 0)?;
2555 if args.len() == 1 {
2556 let blob = encode_jsonb_root(&input)?;
2557 return Ok(SqliteValue::Blob(Arc::from(blob.as_slice())));
2558 }
2559 if args[1..].iter().any(|a| matches!(a, SqliteValue::Null)) {
2560 return Ok(SqliteValue::Null);
2561 }
2562 let paths = collect_path_args(self.name(), args, 1)?;
2563 let edited = json_remove_value(&input, &paths)?;
2564 let blob = encode_jsonb_root(&edited)?;
2565 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2566 }
2567
2568 fn num_args(&self) -> i32 {
2569 -1
2570 }
2571
2572 fn name(&self) -> &'static str {
2573 "jsonb_remove"
2574 }
2575}
2576
2577pub struct JsonPatchFunc;
2578
2579impl ScalarFunction for JsonPatchFunc {
2580 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2581 if args.len() != 2 {
2582 return Err(invalid_arity(
2583 self.name(),
2584 "exactly 2 arguments",
2585 args.len(),
2586 ));
2587 }
2588 if matches!(args[0], SqliteValue::Null) || matches!(args[1], SqliteValue::Null) {
2589 return Ok(SqliteValue::Null);
2590 }
2591 let input = json_arg_value(self.name(), args, 0)?;
2592 let patch = json_arg_value(self.name(), args, 1)?;
2593 let merged = json_patch_value(&input, &patch);
2594 let encoded = encode_json_text("json_patch encode failed", &merged)?;
2595 Ok(SqliteValue::Text(Arc::from(encoded)))
2596 }
2597
2598 fn num_args(&self) -> i32 {
2599 2
2600 }
2601
2602 fn name(&self) -> &'static str {
2603 "json_patch"
2604 }
2605}
2606
2607pub struct JsonbPatchFunc;
2608
2609impl ScalarFunction for JsonbPatchFunc {
2610 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2611 if args.len() != 2 {
2612 return Err(invalid_arity(
2613 self.name(),
2614 "exactly 2 arguments",
2615 args.len(),
2616 ));
2617 }
2618 if matches!(args[0], SqliteValue::Null) || matches!(args[1], SqliteValue::Null) {
2619 return Ok(SqliteValue::Null);
2620 }
2621 let input = json_arg_value(self.name(), args, 0)?;
2622 let patch = json_arg_value(self.name(), args, 1)?;
2623 let merged = json_patch_value(&input, &patch);
2624 let blob = encode_jsonb_root(&merged)?;
2625 Ok(SqliteValue::Blob(Arc::from(blob.as_slice())))
2626 }
2627
2628 fn num_args(&self) -> i32 {
2629 2
2630 }
2631
2632 fn name(&self) -> &'static str {
2633 "jsonb_patch"
2634 }
2635}
2636
2637pub struct JsonArrayLengthFunc;
2638
2639impl ScalarFunction for JsonArrayLengthFunc {
2640 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2641 if !(1..=2).contains(&args.len()) {
2642 return Err(invalid_arity(self.name(), "1 or 2 arguments", args.len()));
2643 }
2644 if matches!(args[0], SqliteValue::Null) {
2645 return Ok(SqliteValue::Null);
2646 }
2647 let input = json_arg_value(self.name(), args, 0)?;
2648 let path = if args.len() == 2 {
2649 if matches!(args[1], SqliteValue::Null) {
2650 return Ok(SqliteValue::Null);
2651 }
2652 Some(text_arg(self.name(), args, 1)?)
2653 } else {
2654 None
2655 };
2656 Ok(match json_array_length_value(&input, path)? {
2657 Some(len) => SqliteValue::Integer(usize_to_i64(self.name(), len)?),
2658 None => SqliteValue::Null,
2659 })
2660 }
2661
2662 fn num_args(&self) -> i32 {
2663 -1
2664 }
2665
2666 fn name(&self) -> &'static str {
2667 "json_array_length"
2668 }
2669}
2670
2671pub struct JsonErrorPositionFunc;
2672
2673impl ScalarFunction for JsonErrorPositionFunc {
2674 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2675 if args.len() != 1 {
2676 return Err(invalid_arity(self.name(), "exactly 1 argument", args.len()));
2677 }
2678 if matches!(args[0], SqliteValue::Null) {
2679 return Ok(SqliteValue::Null);
2680 }
2681 let position = match &args[0] {
2682 SqliteValue::Text(text) => json_error_position(text),
2683 SqliteValue::Blob(bytes) => json_error_position_blob(bytes),
2684 other => {
2685 return Err(FrankenError::function_error(format!(
2686 "{} argument 1 must be TEXT or BLOB, got {}",
2687 self.name(),
2688 other.typeof_str()
2689 )));
2690 }
2691 };
2692 Ok(SqliteValue::Integer(usize_to_i64(self.name(), position)?))
2693 }
2694
2695 fn num_args(&self) -> i32 {
2696 1
2697 }
2698
2699 fn name(&self) -> &'static str {
2700 "json_error_position"
2701 }
2702}
2703
2704pub struct JsonPrettyFunc;
2705
2706impl ScalarFunction for JsonPrettyFunc {
2707 fn invoke(&self, args: &[SqliteValue]) -> Result<SqliteValue> {
2708 if !(1..=2).contains(&args.len()) {
2709 return Err(invalid_arity(self.name(), "1 or 2 arguments", args.len()));
2710 }
2711 if matches!(args[0], SqliteValue::Null) {
2712 return Ok(SqliteValue::Null);
2713 }
2714 let input = json_arg_value(self.name(), args, 0)?;
2715 let indent = if args.len() == 2 {
2716 if matches!(args[1], SqliteValue::Null) {
2717 None
2718 } else {
2719 Some(text_arg(self.name(), args, 1)?)
2720 }
2721 } else {
2722 None
2723 };
2724 let s = json_pretty_value(&input, indent)?;
2725 Ok(SqliteValue::Text(Arc::from(s)))
2726 }
2727
2728 fn num_args(&self) -> i32 {
2729 -1
2730 }
2731
2732 fn name(&self) -> &'static str {
2733 "json_pretty"
2734 }
2735}
2736
2737pub fn register_json_scalars(registry: &mut FunctionRegistry) {
2739 registry.register_scalar(JsonFunc);
2740 registry.register_scalar(JsonbFunc);
2741 registry.register_scalar(JsonValidFunc);
2742 registry.register_scalar(JsonTypeFunc);
2743 registry.register_scalar(JsonExtractFunc);
2744 registry.register_scalar(JsonbExtractFunc);
2745 registry.register_scalar(JsonArrowFunc);
2746 registry.register_scalar(JsonDoubleArrowFunc);
2747 registry.register_scalar(JsonArrayFunc);
2748 registry.register_scalar(JsonbArrayFunc);
2749 registry.register_scalar(JsonObjectFunc);
2750 registry.register_scalar(JsonbObjectFunc);
2751 registry.register_scalar(JsonQuoteFunc);
2752 registry.register_scalar(JsonSetFunc);
2753 registry.register_scalar(JsonbSetFunc);
2754 registry.register_scalar(JsonInsertFunc);
2755 registry.register_scalar(JsonbInsertFunc);
2756 registry.register_scalar(JsonReplaceFunc);
2757 registry.register_scalar(JsonbReplaceFunc);
2758 registry.register_scalar(JsonRemoveFunc);
2759 registry.register_scalar(JsonbRemoveFunc);
2760 registry.register_scalar(JsonPatchFunc);
2761 registry.register_scalar(JsonbPatchFunc);
2762 registry.register_scalar(JsonArrayLengthFunc);
2763 registry.register_scalar(JsonErrorPositionFunc);
2764 registry.register_scalar(JsonPrettyFunc);
2765}
2766
2767#[cfg(test)]
2768mod tests {
2769 use super::*;
2770 use fsqlite_func::FunctionRegistry;
2771
2772 #[test]
2773 fn test_register_json_scalars_registers_core_functions() {
2774 let mut registry = FunctionRegistry::new();
2775 register_json_scalars(&mut registry);
2776
2777 for name in [
2778 "json",
2779 "jsonb",
2780 "json_valid",
2781 "json_type",
2782 "json_extract",
2783 "jsonb_extract",
2784 "json_arrow",
2785 "json_double_arrow",
2786 "json_set",
2787 "jsonb_set",
2788 "json_remove",
2789 "jsonb_remove",
2790 "json_array",
2791 "jsonb_array",
2792 "json_object",
2793 "jsonb_object",
2794 "json_quote",
2795 "json_patch",
2796 "jsonb_patch",
2797 ] {
2798 assert!(
2799 registry.contains_scalar(name),
2800 "missing registration for {name}"
2801 );
2802 }
2803 }
2804
2805 #[test]
2806 fn test_registered_json_extract_scalar_executes() {
2807 let mut registry = FunctionRegistry::new();
2808 register_json_scalars(&mut registry);
2809 let func = registry
2810 .find_scalar("json_extract", 2)
2811 .expect("json_extract should be registered");
2812 let out = func
2813 .invoke(&[
2814 SqliteValue::Text(Arc::from(r#"{"a":1,"b":[2,3]}"#)),
2815 SqliteValue::Text(Arc::from("$.b[1]")),
2816 ])
2817 .unwrap();
2818 assert_eq!(out, SqliteValue::Integer(3));
2819 }
2820
2821 #[test]
2822 fn test_registered_json_arrow_scalar_normalizes_label_shorthand() {
2823 let mut registry = FunctionRegistry::new();
2824 register_json_scalars(&mut registry);
2825 let func = registry
2826 .find_scalar("json_arrow", 2)
2827 .expect("json_arrow should be registered");
2828 let out = func
2829 .invoke(&[
2830 SqliteValue::Text(Arc::from(r#"{"a.b":1,"a":{"b":2}}"#)),
2831 SqliteValue::Text(Arc::from("a.b")),
2832 ])
2833 .expect("json_arrow should normalize bare labels");
2834 assert_eq!(out, SqliteValue::Text(Arc::from("1")));
2835 }
2836
2837 #[test]
2838 fn test_registered_json_double_arrow_scalar_normalizes_integer_shorthand() {
2839 let mut registry = FunctionRegistry::new();
2840 register_json_scalars(&mut registry);
2841 let func = registry
2842 .find_scalar("json_double_arrow", 2)
2843 .expect("json_double_arrow should be registered");
2844 let out = func
2845 .invoke(&[
2846 SqliteValue::Text(Arc::from("[10,20,30]")),
2847 SqliteValue::Integer(1),
2848 ])
2849 .expect("json_double_arrow should normalize integer indexes");
2850 assert_eq!(out, SqliteValue::Integer(20));
2851 }
2852
2853 #[test]
2854 fn test_registered_json_set_scalar_executes() {
2855 let mut registry = FunctionRegistry::new();
2856 register_json_scalars(&mut registry);
2857 let func = registry
2858 .find_scalar("json_set", 3)
2859 .expect("json_set should be registered");
2860 let out = func
2861 .invoke(&[
2862 SqliteValue::Text(Arc::from(r#"{"a":1}"#)),
2863 SqliteValue::Text(Arc::from("$.b")),
2864 SqliteValue::Integer(2),
2865 ])
2866 .unwrap();
2867 assert_eq!(out, SqliteValue::Text(Arc::from(r#"{"a":1,"b":2}"#)));
2868 }
2869
2870 #[test]
2871 fn test_registered_jsonb_scalar_executes() {
2872 let mut registry = FunctionRegistry::new();
2873 register_json_scalars(&mut registry);
2874 let func = registry
2875 .find_scalar("jsonb", 1)
2876 .expect("jsonb should be registered");
2877 let out = func
2878 .invoke(&[SqliteValue::Text(Arc::from(r#"{"a":[1,2]}"#))])
2879 .expect("jsonb should encode to JSONB");
2880 let SqliteValue::Blob(blob) = out else {
2881 panic!("jsonb should return BLOB");
2882 };
2883 assert_eq!(json_from_jsonb(&blob).unwrap(), r#"{"a":[1,2]}"#);
2884 }
2885
2886 #[test]
2887 fn test_registered_json_extract_accepts_jsonb_blob_input() {
2888 let mut registry = FunctionRegistry::new();
2889 register_json_scalars(&mut registry);
2890 let func = registry
2891 .find_scalar("json_extract", 2)
2892 .expect("json_extract should be registered");
2893 let input = jsonb(r#"{"a":{"b":7}}"#).unwrap();
2894 let out = func
2895 .invoke(&[
2896 SqliteValue::Blob(Arc::from(input)),
2897 SqliteValue::Text(Arc::from("$.a.b")),
2898 ])
2899 .expect("json_extract should accept JSONB blob input");
2900 assert_eq!(out, SqliteValue::Integer(7));
2901 }
2902
2903 #[test]
2904 fn test_registered_jsonb_set_accepts_jsonb_blob_input() {
2905 let mut registry = FunctionRegistry::new();
2906 register_json_scalars(&mut registry);
2907 let func = registry
2908 .find_scalar("jsonb_set", 3)
2909 .expect("jsonb_set should be registered");
2910 let input = jsonb(r#"{"a":1}"#).unwrap();
2911 let out = func
2912 .invoke(&[
2913 SqliteValue::Blob(Arc::from(input)),
2914 SqliteValue::Text(Arc::from("$.b")),
2915 SqliteValue::Integer(9),
2916 ])
2917 .expect("jsonb_set should accept JSONB blob input");
2918 let SqliteValue::Blob(blob) = out else {
2919 panic!("jsonb_set should return BLOB");
2920 };
2921 assert_eq!(json_from_jsonb(&blob).unwrap(), r#"{"a":1,"b":9}"#);
2922 }
2923
2924 #[test]
2925 fn test_registered_json_pretty_accepts_jsonb_blob_input() {
2926 let mut registry = FunctionRegistry::new();
2927 register_json_scalars(&mut registry);
2928 let func = registry
2929 .find_scalar("json_pretty", 1)
2930 .expect("json_pretty should be registered");
2931 let input = jsonb(r#"{"a":[1,2]}"#).unwrap();
2932 let out = func
2933 .invoke(&[SqliteValue::Blob(Arc::from(input))])
2934 .expect("json_pretty should accept JSONB blob input");
2935 let SqliteValue::Text(pretty) = out else {
2936 panic!("json_pretty should return TEXT");
2937 };
2938 assert!(pretty.contains('\n'));
2939 assert!(pretty.contains("\"a\""));
2940 }
2941
2942 #[test]
2943 fn test_registered_json_error_position_accepts_jsonb_blob_input() {
2944 let mut registry = FunctionRegistry::new();
2945 register_json_scalars(&mut registry);
2946 let func = registry
2947 .find_scalar("json_error_position", 1)
2948 .expect("json_error_position should be registered");
2949 let input = jsonb(r#"{"a":1}"#).unwrap();
2950 let out = func
2951 .invoke(&[SqliteValue::Blob(Arc::from(input))])
2952 .expect("json_error_position should accept JSONB blob input");
2953 assert_eq!(out, SqliteValue::Integer(0));
2954 }
2955
2956 #[test]
2957 fn test_json_valid_text() {
2958 assert_eq!(json(r#"{"a":1}"#).unwrap(), r#"{"a":1}"#);
2959 }
2960
2961 #[test]
2962 fn test_json_invalid_error() {
2963 let err = json("not json").unwrap_err();
2964 assert!(matches!(err, FrankenError::FunctionError(_)));
2965 }
2966
2967 #[test]
2968 fn test_json_valid_flags_default() {
2969 assert_eq!(json_valid(r#"{"a":1}"#, None), 1);
2970 assert_eq!(json_valid("not json", None), 0);
2971 }
2972
2973 #[test]
2974 fn test_json_valid_flags_json5() {
2975 let json5_text = concat!("{", "a:1", "}");
2976 assert_eq!(json_valid(json5_text, Some(JSON_VALID_JSON5_FLAG)), 1);
2977 assert_eq!(json_valid(json5_text, Some(JSON_VALID_RFC_8259_FLAG)), 0);
2978 }
2979
2980 #[test]
2981 fn test_json_valid_flags_strict() {
2982 assert_eq!(json_valid("invalid", Some(JSON_VALID_RFC_8259_FLAG)), 0);
2983 }
2984
2985 #[test]
2986 fn test_json_valid_flags_jsonb() {
2987 let payload = jsonb(r#"{"a":[1,2,3]}"#).unwrap();
2988 assert_eq!(
2989 json_valid_blob(&payload, Some(JSON_VALID_JSONB_SUPERFICIAL_FLAG)),
2990 1
2991 );
2992 assert_eq!(
2993 json_valid_blob(&payload, Some(JSON_VALID_JSONB_STRICT_FLAG)),
2994 1
2995 );
2996 let mut trailing = payload.clone();
2999 trailing.push(0xFF);
3000 assert_eq!(
3001 json_valid_blob(&trailing, Some(JSON_VALID_JSONB_SUPERFICIAL_FLAG)),
3002 0
3003 );
3004 assert_eq!(
3005 json_valid_blob(&trailing, Some(JSON_VALID_JSONB_STRICT_FLAG)),
3006 0
3007 );
3008
3009 let mut corrupted = payload;
3014 assert!(corrupted.len() > 3);
3015 corrupted[2] = 0xFF;
3016 assert_eq!(
3017 json_valid_blob(&corrupted, Some(JSON_VALID_JSONB_SUPERFICIAL_FLAG)),
3018 1
3019 );
3020 assert_eq!(
3021 json_valid_blob(&corrupted, Some(JSON_VALID_JSONB_STRICT_FLAG)),
3022 0
3023 );
3024 }
3025
3026 #[test]
3027 fn test_json_type_object() {
3028 assert_eq!(json_type(r#"{"a":1}"#, None).unwrap(), Some("object"));
3029 }
3030
3031 #[test]
3032 fn test_json_type_path() {
3033 assert_eq!(
3034 json_type(r#"{"a":1}"#, Some("$.a")).unwrap(),
3035 Some("integer")
3036 );
3037 }
3038
3039 #[test]
3040 fn test_json_type_missing_path() {
3041 assert_eq!(json_type(r#"{"a":1}"#, Some("$.b")).unwrap(), None);
3042 }
3043
3044 #[test]
3045 fn test_json_extract_single() {
3046 let result = json_extract(r#"{"a":1}"#, &["$.a"]).unwrap();
3047 assert_eq!(result, SqliteValue::Integer(1));
3048 }
3049
3050 #[test]
3051 fn test_json_extract_multiple() {
3052 let result = json_extract(r#"{"a":1,"b":2}"#, &["$.a", "$.b"]).unwrap();
3053 assert_eq!(result, SqliteValue::Text(Arc::from("[1,2]")));
3054 }
3055
3056 #[test]
3057 fn test_json_extract_string_unwrap() {
3058 let result = json_extract(r#"{"a":"hello"}"#, &["$.a"]).unwrap();
3059 assert_eq!(result, SqliteValue::Text(Arc::from("hello")));
3060 }
3061
3062 #[test]
3063 fn test_arrow_preserves_json() {
3064 let result = json_arrow(r#"{"a":"hello"}"#, "$.a").unwrap();
3065 assert_eq!(result, SqliteValue::Text(Arc::from(r#""hello""#)));
3066 }
3067
3068 #[test]
3069 fn test_double_arrow_unwraps() {
3070 let result = json_double_arrow(r#"{"a":"hello"}"#, "$.a").unwrap();
3071 assert_eq!(result, SqliteValue::Text(Arc::from("hello")));
3072 }
3073
3074 #[test]
3075 fn test_json_extract_array_index() {
3076 let result = json_extract("[10,20,30]", &["$[1]"]).unwrap();
3077 assert_eq!(result, SqliteValue::Integer(20));
3078 }
3079
3080 #[test]
3081 fn test_json_extract_quoted_key_segment() {
3082 let result = json_extract(r#"{"a.b":1}"#, &["$.\"a.b\""]).unwrap();
3083 assert_eq!(result, SqliteValue::Integer(1));
3084 }
3085
3086 #[test]
3087 fn test_json_extract_from_end() {
3088 let result = json_extract("[10,20,30]", &["$[#-1]"]).unwrap();
3089 assert_eq!(result, SqliteValue::Integer(30));
3090 }
3091
3092 #[test]
3093 fn test_jsonb_extract_returns_blob() {
3094 let blob = jsonb_extract(r#"{"a":"hello"}"#, &["$.a"]).unwrap();
3095 let text = json_from_jsonb(&blob).unwrap();
3096 assert_eq!(text, r#""hello""#);
3097 }
3098
3099 #[test]
3100 fn test_json_quote_text() {
3101 assert_eq!(
3102 json_quote(&SqliteValue::Text(Arc::from("hello"))).unwrap(),
3103 r#""hello""#
3104 );
3105 }
3106
3107 #[test]
3108 fn test_json_quote_null() {
3109 assert_eq!(json_quote(&SqliteValue::Null).unwrap(), "null");
3110 }
3111
3112 #[test]
3113 fn test_json_array_basic() {
3114 let out = json_array(&[
3115 SqliteValue::Integer(1),
3116 SqliteValue::Text(Arc::from("two")),
3117 SqliteValue::Null,
3118 ])
3119 .unwrap();
3120 assert_eq!(out, r#"[1,"two",null]"#);
3121 }
3122
3123 #[test]
3124 fn test_json_object_basic() {
3125 let out = json_object(&[
3126 SqliteValue::Text(Arc::from("a")),
3127 SqliteValue::Integer(1),
3128 SqliteValue::Text(Arc::from("b")),
3129 SqliteValue::Text(Arc::from("two")),
3130 ])
3131 .unwrap();
3132 assert_eq!(out, r#"{"a":1,"b":"two"}"#);
3133 }
3134
3135 #[test]
3136 fn test_jsonb_roundtrip() {
3137 let blob = jsonb(r#"{"a":1,"b":[2,3]}"#).unwrap();
3138 let text = json_from_jsonb(&blob).unwrap();
3139 assert_eq!(text, r#"{"a":1,"b":[2,3]}"#);
3140 }
3141
3142 #[test]
3143 fn test_jsonb_array_variant() {
3144 let blob = jsonb_array(&[
3145 SqliteValue::Integer(1),
3146 SqliteValue::Text(Arc::from("two")),
3147 SqliteValue::Null,
3148 ])
3149 .unwrap();
3150 assert_eq!(json_from_jsonb(&blob).unwrap(), r#"[1,"two",null]"#);
3151 }
3152
3153 #[test]
3154 fn test_jsonb_object_variant() {
3155 let blob = jsonb_object(&[
3156 SqliteValue::Text(Arc::from("a")),
3157 SqliteValue::Integer(1),
3158 SqliteValue::Text(Arc::from("b")),
3159 SqliteValue::Text(Arc::from("two")),
3160 ])
3161 .unwrap();
3162 assert_eq!(json_from_jsonb(&blob).unwrap(), r#"{"a":1,"b":"two"}"#);
3163 }
3164
3165 #[test]
3166 fn test_json_array_length() {
3167 assert_eq!(json_array_length("[1,2,3]", None).unwrap(), Some(3));
3168 assert_eq!(json_array_length("[]", None).unwrap(), Some(0));
3169 assert_eq!(json_array_length(r#"{"a":1}"#, None).unwrap(), None);
3170 }
3171
3172 #[test]
3173 fn test_json_array_length_path() {
3174 assert_eq!(
3175 json_array_length(r#"{"a":[1,2,3]}"#, Some("$.a")).unwrap(),
3176 Some(3)
3177 );
3178 }
3179
3180 #[test]
3181 fn test_json_array_length_not_array() {
3182 assert_eq!(json_array_length(r#"{"a":1}"#, Some("$.a")).unwrap(), None);
3183 assert_eq!(json_array_length(r#""text""#, None).unwrap(), None);
3184 }
3185
3186 #[test]
3187 fn test_json_error_position_valid() {
3188 assert_eq!(json_error_position(r#"{"a":1}"#), 0);
3189 }
3190
3191 #[test]
3192 fn test_json_error_position_invalid() {
3193 assert!(json_error_position(r#"{"a":}"#) > 0);
3194 }
3195
3196 #[test]
3197 fn test_json_pretty_default() {
3198 let output = json_pretty(r#"{"a":1}"#, None).unwrap();
3199 assert!(output.contains('\n'));
3200 assert!(output.contains(" \"a\""));
3201 }
3202
3203 #[test]
3204 fn test_json_pretty_custom_indent() {
3205 let output = json_pretty(r#"{"a":1}"#, Some("\t")).unwrap();
3206 assert!(output.contains("\n\t\"a\""));
3207 }
3208
3209 #[test]
3210 fn test_json_set_create() {
3211 let out = json_set(r#"{"a":1}"#, &[("$.b", SqliteValue::Integer(2))]).unwrap();
3212 assert_eq!(out, r#"{"a":1,"b":2}"#);
3213 }
3214
3215 #[test]
3216 fn test_json_set_nested_path_create() {
3217 let out = json_set("{}", &[("$.a.b", SqliteValue::Integer(1))]).unwrap();
3218 assert_eq!(out, r#"{"a":{"b":1}}"#);
3219 }
3220
3221 #[test]
3222 fn test_json_set_nested_array_path_create() {
3223 let out = json_set("{}", &[("$.a[0]", SqliteValue::Integer(1))]).unwrap();
3224 assert_eq!(out, r#"{"a":[1]}"#);
3225 }
3226
3227 #[test]
3228 fn test_json_set_nested_append_path_create() {
3229 let out = json_set("{}", &[("$.a[#]", SqliteValue::Integer(1))]).unwrap();
3230 assert_eq!(out, r#"{"a":[1]}"#);
3231 }
3232
3233 #[test]
3234 fn test_json_set_nested_array_object_create() {
3235 let out = json_set("{}", &[("$.a[0].b", SqliteValue::Integer(1))]).unwrap();
3236 assert_eq!(out, r#"{"a":[{"b":1}]}"#);
3237 }
3238
3239 #[test]
3240 fn test_json_set_nested_array_index_out_of_range_does_not_scaffold() {
3241 let out = json_set("{}", &[("$.a[1]", SqliteValue::Integer(1))]).unwrap();
3242 assert_eq!(out, "{}");
3243 }
3244
3245 #[test]
3246 fn test_json_set_nested_from_end_does_not_scaffold() {
3247 let out = json_set("{}", &[("$.a[#-1]", SqliteValue::Integer(1))]).unwrap();
3248 assert_eq!(out, "{}");
3249 }
3250
3251 #[test]
3252 fn test_json_set_scalar_root_with_array_path_is_noop() {
3253 let out = json_set("null", &[("$.a[0]", SqliteValue::Integer(1))]).unwrap();
3254 assert_eq!(out, "null");
3255 }
3256
3257 #[test]
3258 fn test_json_set_existing_null_value_with_array_path_is_noop() {
3259 let out = json_set(r#"{"a":null}"#, &[("$.a[1]", SqliteValue::Integer(1))]).unwrap();
3260 assert_eq!(out, r#"{"a":null}"#);
3261 }
3262
3263 #[test]
3264 fn test_json_set_overwrite() {
3265 let out = json_set(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(2))]).unwrap();
3266 assert_eq!(out, r#"{"a":2}"#);
3267 }
3268
3269 #[test]
3270 fn test_json_insert_no_overwrite() {
3271 let out = json_insert(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(2))]).unwrap();
3272 assert_eq!(out, r#"{"a":1}"#);
3273 }
3274
3275 #[test]
3276 fn test_json_insert_create() {
3277 let out = json_insert(r#"{"a":1}"#, &[("$.b", SqliteValue::Integer(2))]).unwrap();
3278 assert_eq!(out, r#"{"a":1,"b":2}"#);
3279 }
3280
3281 #[test]
3282 fn test_json_insert_nested_path_create() {
3283 let out = json_insert("{}", &[("$.a.b", SqliteValue::Integer(1))]).unwrap();
3284 assert_eq!(out, r#"{"a":{"b":1}}"#);
3285 }
3286
3287 #[test]
3288 fn test_json_insert_nested_array_path_create() {
3289 let out = json_insert("{}", &[("$.a[0]", SqliteValue::Integer(1))]).unwrap();
3290 assert_eq!(out, r#"{"a":[1]}"#);
3291 }
3292
3293 #[test]
3294 fn test_json_replace_overwrite() {
3295 let out = json_replace(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(2))]).unwrap();
3296 assert_eq!(out, r#"{"a":2}"#);
3297 }
3298
3299 #[test]
3300 fn test_json_replace_no_create() {
3301 let out = json_replace(r#"{"a":1}"#, &[("$.b", SqliteValue::Integer(2))]).unwrap();
3302 assert_eq!(out, r#"{"a":1}"#);
3303 }
3304
3305 #[test]
3306 fn test_json_remove_key() {
3307 let out = json_remove(r#"{"a":1,"b":2}"#, &["$.a"]).unwrap();
3308 assert_eq!(out, r#"{"b":2}"#);
3309 }
3310
3311 #[test]
3312 fn test_json_remove_array_compact() {
3313 let out = json_remove("[1,2,3]", &["$[1]"]).unwrap();
3314 assert_eq!(out, "[1,3]");
3315 }
3316
3317 #[test]
3318 fn test_json_patch_merge() {
3319 let out = json_patch(r#"{"a":1,"b":2}"#, r#"{"b":3,"c":4}"#).unwrap();
3320 assert_eq!(out, r#"{"a":1,"b":3,"c":4}"#);
3321 }
3322
3323 #[test]
3324 fn test_json_patch_delete() {
3325 let out = json_patch(r#"{"a":1,"b":2}"#, r#"{"b":null}"#).unwrap();
3326 assert_eq!(out, r#"{"a":1}"#);
3327 }
3328
3329 #[test]
3330 fn test_jsonb_set_variant() {
3331 let blob = jsonb_set(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(9))]).unwrap();
3332 let text = json_from_jsonb(&blob).unwrap();
3333 assert_eq!(text, r#"{"a":9}"#);
3334 }
3335
3336 #[test]
3337 fn test_jsonb_insert_variant() {
3338 let blob = jsonb_insert(r#"{"a":1}"#, &[("$.b", SqliteValue::Integer(2))]).unwrap();
3339 let text = json_from_jsonb(&blob).unwrap();
3340 assert_eq!(text, r#"{"a":1,"b":2}"#);
3341 }
3342
3343 #[test]
3344 fn test_jsonb_replace_variant() {
3345 let blob = jsonb_replace(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(5))]).unwrap();
3346 let text = json_from_jsonb(&blob).unwrap();
3347 assert_eq!(text, r#"{"a":5}"#);
3348 }
3349
3350 #[test]
3351 fn test_jsonb_remove_variant() {
3352 let blob = jsonb_remove(r#"{"a":1,"b":2}"#, &["$.a"]).unwrap();
3353 let text = json_from_jsonb(&blob).unwrap();
3354 assert_eq!(text, r#"{"b":2}"#);
3355 }
3356
3357 #[test]
3358 fn test_jsonb_patch_variant() {
3359 let blob = jsonb_patch(r#"{"a":1,"b":2}"#, r#"{"b":7}"#).unwrap();
3360 let text = json_from_jsonb(&blob).unwrap();
3361 assert_eq!(text, r#"{"a":1,"b":7}"#);
3362 }
3363
3364 #[test]
3365 fn test_json_group_array_includes_nulls() {
3366 let out = json_group_array(&[
3367 SqliteValue::Integer(1),
3368 SqliteValue::Null,
3369 SqliteValue::Integer(3),
3370 ])
3371 .unwrap();
3372 assert_eq!(out, "[1,null,3]");
3373 }
3374
3375 #[test]
3376 fn test_json_group_array_basic() {
3377 let out = json_group_array(&[
3378 SqliteValue::Integer(1),
3379 SqliteValue::Integer(2),
3380 SqliteValue::Integer(3),
3381 ])
3382 .unwrap();
3383 assert_eq!(out, "[1,2,3]");
3384 }
3385
3386 #[test]
3387 fn test_json_group_object_basic() {
3388 let out = json_group_object(&[
3389 (SqliteValue::Text(Arc::from("a")), SqliteValue::Integer(1)),
3390 (SqliteValue::Text(Arc::from("b")), SqliteValue::Integer(2)),
3391 ])
3392 .unwrap();
3393 assert_eq!(out, r#"{"a":1,"b":2}"#);
3394 }
3395
3396 #[test]
3397 fn test_json_group_object_duplicate_keys_last_wins() {
3398 let out = json_group_object(&[
3399 (SqliteValue::Text(Arc::from("k")), SqliteValue::Integer(1)),
3400 (SqliteValue::Text(Arc::from("k")), SqliteValue::Integer(2)),
3401 ])
3402 .unwrap();
3403 assert_eq!(out, r#"{"k":2}"#);
3404 }
3405
3406 #[test]
3407 fn test_jsonb_group_array_and_object_variants() {
3408 let array_blob = jsonb_group_array(&[SqliteValue::Integer(1), SqliteValue::Null]).unwrap();
3409 assert_eq!(json_from_jsonb(&array_blob).unwrap(), "[1,null]");
3410
3411 let object_blob =
3412 jsonb_group_object(&[(SqliteValue::Text(Arc::from("a")), SqliteValue::Integer(7))])
3413 .unwrap();
3414 assert_eq!(json_from_jsonb(&object_blob).unwrap(), r#"{"a":7}"#);
3415 }
3416
3417 #[test]
3418 fn test_json_each_array() {
3419 let rows = json_each("[10,20]", None).unwrap();
3420 assert_eq!(rows.len(), 2);
3421 assert_eq!(rows[0].key, SqliteValue::Integer(0));
3422 assert_eq!(rows[1].key, SqliteValue::Integer(1));
3423 assert_eq!(rows[0].value, SqliteValue::Integer(10));
3424 assert_eq!(rows[1].value, SqliteValue::Integer(20));
3425 }
3426
3427 #[test]
3428 fn test_json_each_object() {
3429 let rows = json_each(r#"{"a":1,"b":2}"#, None).unwrap();
3430 assert_eq!(rows.len(), 2);
3431 assert_eq!(rows[0].key, SqliteValue::Text(Arc::from("a")));
3432 assert_eq!(rows[1].key, SqliteValue::Text(Arc::from("b")));
3433 assert_eq!(rows[0].value, SqliteValue::Integer(1));
3434 assert_eq!(rows[1].value, SqliteValue::Integer(2));
3435 }
3436
3437 #[test]
3438 fn test_json_each_path() {
3439 let rows = json_each(r#"{"a":{"b":1,"c":2}}"#, Some("$.a")).unwrap();
3440 assert_eq!(rows.len(), 2);
3441 assert_eq!(rows[0].path, "$.a");
3442 assert_eq!(rows[1].path, "$.a");
3443 }
3444
3445 #[test]
3446 fn test_json_each_nested_value_is_json_text() {
3447 let rows = json_each(r#"{"a":[1,2]}"#, None).unwrap();
3448 assert_eq!(rows[0].value, SqliteValue::Text(Arc::from("[1,2]")));
3449 assert_eq!(rows[0].atom, SqliteValue::Null); }
3451
3452 #[test]
3453 fn test_json_tree_recursive() {
3454 let rows = json_tree(r#"{"a":{"b":1}}"#, None).unwrap();
3455 assert!(rows.iter().any(|row| row.fullkey == "$.a"));
3456 assert!(rows.iter().any(|row| row.fullkey == "$.a.b"));
3457 }
3458
3459 #[test]
3460 fn test_json_tree_columns() {
3461 let rows = json_tree(r#"{"a":{"b":1}}"#, None).unwrap();
3462 let row = rows
3463 .iter()
3464 .find(|candidate| candidate.fullkey == "$.a.b")
3465 .expect("nested row should exist");
3466 assert_eq!(row.key, SqliteValue::Text(Arc::from("b")));
3467 assert_eq!(row.value, SqliteValue::Integer(1));
3468 assert_eq!(row.type_name, "integer");
3469 assert_eq!(row.atom, SqliteValue::Integer(1));
3470 assert_eq!(row.path, "$.a");
3471 }
3472
3473 #[test]
3474 fn test_json_tree_vtab_cursor_scan() {
3475 let cx = Cx::new();
3476 let vtab = JsonTreeVtab::connect(&cx, &[]).unwrap();
3477 let mut cursor = vtab.open().unwrap();
3478 cursor
3479 .filter(
3480 &cx,
3481 0,
3482 None,
3483 &[
3484 SqliteValue::Text(Arc::from(r#"{"a":{"b":1}}"#)),
3485 SqliteValue::Text(Arc::from("$.a")),
3486 ],
3487 )
3488 .unwrap();
3489
3490 let mut fullkeys = Vec::new();
3491 while !cursor.eof() {
3492 let mut ctx = ColumnContext::new();
3493 cursor.column(&mut ctx, 6).unwrap();
3494 let fullkey = ctx.take_value().unwrap();
3495 if let SqliteValue::Text(text) = fullkey {
3496 fullkeys.push(text);
3497 }
3498 cursor.next(&cx).unwrap();
3499 }
3500
3501 assert_eq!(fullkeys, vec![Arc::from("$.a"), Arc::from("$.a.b")]);
3502 }
3503
3504 #[test]
3505 fn test_json_each_vtab_cursor_accepts_jsonb_blob_input() {
3506 let cx = Cx::new();
3507 let vtab = JsonEachVtab::connect(&cx, &[]).unwrap();
3508 let mut cursor = vtab.open().unwrap();
3509 let input = jsonb(r#"{"a":[10,20]}"#).unwrap();
3510 cursor
3511 .filter(
3512 &cx,
3513 0,
3514 None,
3515 &[
3516 SqliteValue::Blob(Arc::from(input)),
3517 SqliteValue::Text(Arc::from("$.a")),
3518 ],
3519 )
3520 .expect("json_each cursor should accept JSONB blob input");
3521
3522 let mut values = Vec::new();
3523 while !cursor.eof() {
3524 let mut ctx = ColumnContext::new();
3525 cursor.column(&mut ctx, 1).unwrap();
3526 values.push(ctx.take_value().unwrap());
3527 cursor.next(&cx).unwrap();
3528 }
3529
3530 assert_eq!(
3531 values,
3532 vec![SqliteValue::Integer(10), SqliteValue::Integer(20)]
3533 );
3534 }
3535
3536 #[test]
3537 fn test_json_tree_vtab_cursor_accepts_jsonb_blob_input() {
3538 let cx = Cx::new();
3539 let vtab = JsonTreeVtab::connect(&cx, &[]).unwrap();
3540 let mut cursor = vtab.open().unwrap();
3541 let input = jsonb(r#"{"a":{"b":1}}"#).unwrap();
3542 cursor
3543 .filter(
3544 &cx,
3545 0,
3546 None,
3547 &[
3548 SqliteValue::Blob(Arc::from(input)),
3549 SqliteValue::Text(Arc::from("$.a")),
3550 ],
3551 )
3552 .expect("json_tree cursor should accept JSONB blob input");
3553
3554 let mut fullkeys = Vec::new();
3555 while !cursor.eof() {
3556 let mut ctx = ColumnContext::new();
3557 cursor.column(&mut ctx, 6).unwrap();
3558 let fullkey = ctx.take_value().unwrap();
3559 if let SqliteValue::Text(text) = fullkey {
3560 fullkeys.push(text);
3561 }
3562 cursor.next(&cx).unwrap();
3563 }
3564
3565 assert_eq!(fullkeys, vec![Arc::from("$.a"), Arc::from("$.a.b")]);
3566 }
3567
3568 #[test]
3569 fn test_jsonb_chain_validity() {
3570 let first = jsonb_set(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(9))]).unwrap();
3571 let first_text = json_from_jsonb(&first).unwrap();
3572 let second = jsonb_patch(&first_text, r#"{"b":2}"#).unwrap();
3573 assert_eq!(
3574 json_valid_blob(&second, Some(JSON_VALID_JSONB_STRICT_FLAG)),
3575 1
3576 );
3577 }
3578
3579 #[test]
3584 fn test_json_minify_whitespace() {
3585 assert_eq!(json(" { \"a\" : 1 } ").unwrap(), r#"{"a":1}"#);
3586 }
3587
3588 #[test]
3589 fn test_json_scalar_string() {
3590 assert_eq!(json(r#""hello""#).unwrap(), r#""hello""#);
3591 }
3592
3593 #[test]
3594 fn test_json_scalar_number() {
3595 assert_eq!(json("42").unwrap(), "42");
3596 }
3597
3598 #[test]
3599 fn test_json_scalar_null() {
3600 assert_eq!(json("null").unwrap(), "null");
3601 }
3602
3603 #[test]
3604 fn test_json_scalar_bool() {
3605 assert_eq!(json("true").unwrap(), "true");
3606 assert_eq!(json("false").unwrap(), "false");
3607 }
3608
3609 #[test]
3610 fn test_json_nested_structure() {
3611 let input = r#"{"a":{"b":[1,2,{"c":3}]}}"#;
3612 assert_eq!(json(input).unwrap(), input);
3613 }
3614
3615 #[test]
3616 fn test_json_unicode() {
3617 let input = r#"{"key":"\u00fc\u00e9"}"#;
3618 let result = json(input).unwrap();
3619 assert!(result.contains("key"));
3621 }
3622
3623 #[test]
3628 fn test_json_valid_zero_flags() {
3629 assert_eq!(json_valid(r#"{"a":1}"#, Some(0)), 0);
3630 }
3631
3632 #[test]
3633 fn test_json_valid_empty_string() {
3634 assert_eq!(json_valid("", None), 0);
3635 }
3636
3637 #[test]
3642 fn test_json_type_null() {
3643 assert_eq!(json_type("null", None).unwrap(), Some("null"));
3644 }
3645
3646 #[test]
3647 fn test_json_type_true() {
3648 assert_eq!(json_type("true", None).unwrap(), Some("true"));
3649 }
3650
3651 #[test]
3652 fn test_json_type_false() {
3653 assert_eq!(json_type("false", None).unwrap(), Some("false"));
3654 }
3655
3656 #[test]
3657 fn test_json_type_real() {
3658 assert_eq!(json_type("3.14", None).unwrap(), Some("real"));
3659 }
3660
3661 #[test]
3662 fn test_json_type_text() {
3663 assert_eq!(json_type(r#""hello""#, None).unwrap(), Some("text"));
3664 }
3665
3666 #[test]
3667 fn test_json_type_array() {
3668 assert_eq!(json_type("[1,2]", None).unwrap(), Some("array"));
3669 }
3670
3671 #[test]
3676 fn test_json_extract_missing_path_null() {
3677 let result = json_extract(r#"{"a":1}"#, &["$.b"]).unwrap();
3678 assert_eq!(result, SqliteValue::Null);
3679 }
3680
3681 #[test]
3682 fn test_json_extract_no_paths_error() {
3683 let empty: &[&str] = &[];
3684 assert!(json_extract(r#"{"a":1}"#, empty).is_err());
3685
3686 let func = JsonExtractFunc;
3687 let args = vec![SqliteValue::Text(Arc::from(r#"{"a":1}"#))];
3688 assert_eq!(func.invoke(&args).unwrap(), SqliteValue::Null);
3689 }
3690
3691 #[test]
3692 fn test_json_extract_null_value() {
3693 let result = json_extract(r#"{"a":null}"#, &["$.a"]).unwrap();
3694 assert_eq!(result, SqliteValue::Null);
3695 }
3696
3697 #[test]
3698 fn test_json_extract_boolean() {
3699 let result = json_extract(r#"{"a":true}"#, &["$.a"]).unwrap();
3700 assert_eq!(result, SqliteValue::Integer(1));
3701 let result = json_extract(r#"{"a":false}"#, &["$.a"]).unwrap();
3702 assert_eq!(result, SqliteValue::Integer(0));
3703 }
3704
3705 #[test]
3706 fn test_json_extract_nested_array() {
3707 let result = json_extract(r#"{"a":[[1,2],[3,4]]}"#, &["$.a[1][0]"]).unwrap();
3708 assert_eq!(result, SqliteValue::Integer(3));
3709 }
3710
3711 #[test]
3712 fn test_json_extract_multiple_with_missing() {
3713 let result = json_extract(r#"{"a":1}"#, &["$.a", "$.b"]).unwrap();
3714 assert_eq!(result, SqliteValue::Text(Arc::from("[1,null]")));
3715 }
3716
3717 #[test]
3722 fn test_json_arrow_missing_path_null() {
3723 let result = json_arrow(r#"{"a":1}"#, "$.b").unwrap();
3724 assert_eq!(result, SqliteValue::Null);
3725 }
3726
3727 #[test]
3728 fn test_json_arrow_number() {
3729 let result = json_arrow(r#"{"a":42}"#, "$.a").unwrap();
3730 assert_eq!(result, SqliteValue::Text(Arc::from("42")));
3731 }
3732
3733 #[test]
3734 fn test_json_arrow_null() {
3735 let result = json_arrow(r#"{"a":null}"#, "$.a").unwrap();
3736 assert_eq!(result, SqliteValue::Text(Arc::from("null")));
3737 }
3738
3739 #[test]
3744 fn test_json_array_length_nested_not_array() {
3745 assert_eq!(
3746 json_array_length(r#"{"a":"text"}"#, Some("$.a")).unwrap(),
3747 None
3748 );
3749 }
3750
3751 #[test]
3752 fn test_json_array_length_missing_path() {
3753 assert_eq!(json_array_length(r#"{"a":1}"#, Some("$.b")).unwrap(), None);
3754 }
3755
3756 #[test]
3761 fn test_json_error_position_empty() {
3762 assert!(json_error_position("") > 0);
3763 }
3764
3765 #[test]
3766 fn test_json_error_position_just_brace() {
3767 assert!(json_error_position("{") > 0);
3768 }
3769
3770 #[test]
3775 fn test_json_pretty_empty_array() {
3776 assert_eq!(json_pretty("[]", None).unwrap(), "[]");
3777 }
3778
3779 #[test]
3780 fn test_json_pretty_empty_object() {
3781 assert_eq!(json_pretty("{}", None).unwrap(), "{}");
3782 }
3783
3784 #[test]
3785 fn test_json_pretty_scalar() {
3786 assert_eq!(json_pretty("42", None).unwrap(), "42");
3787 }
3788
3789 #[test]
3790 fn test_json_pretty_nested() {
3791 let result = json_pretty(r#"{"a":[1,2]}"#, None).unwrap();
3792 assert!(result.contains('\n'));
3793 assert!(result.contains("\"a\""));
3794 }
3795
3796 #[test]
3801 fn test_json_pretty_object() {
3802 let output = json_pretty(r#"{"a":1,"b":[2,3]}"#, None).unwrap();
3803 assert!(output.contains('\n'));
3804 assert!(output.contains(" \"a\""));
3805 assert!(output.contains(" \"b\""));
3806 }
3807
3808 #[test]
3809 fn test_json_pretty_array() {
3810 let output = json_pretty("[1,2,3]", None).unwrap();
3811 assert!(output.contains('\n'));
3812 assert!(output.contains(" 1"));
3813 assert!(output.contains(" 2"));
3814 assert!(output.contains(" 3"));
3815 }
3816
3817 #[test]
3818 fn test_json_pretty_idempotent() {
3819 let input = r#"{"a":1,"b":[2,3]}"#;
3820 let first = json_pretty(input, None).unwrap();
3821 let second = json_pretty(&first, None).unwrap();
3822 assert_eq!(first, second, "json_pretty should be idempotent");
3823 }
3824
3825 #[test]
3826 fn test_jsonb_functions_available() {
3827 let blob = jsonb_array(&[SqliteValue::Integer(1), SqliteValue::Integer(2)]).unwrap();
3828 assert!(
3829 !blob.is_empty(),
3830 "jsonb_array should produce non-empty output"
3831 );
3832
3833 let blob2 = jsonb_set(r#"{"a":1}"#, &[("$.a", SqliteValue::Integer(9))]).unwrap();
3834 assert!(
3835 !blob2.is_empty(),
3836 "jsonb_set should produce non-empty output"
3837 );
3838
3839 let blob3 = jsonb_object(&[
3840 SqliteValue::Text(Arc::from("key")),
3841 SqliteValue::Integer(42),
3842 ])
3843 .unwrap();
3844 assert!(
3845 !blob3.is_empty(),
3846 "jsonb_object should produce non-empty output"
3847 );
3848 }
3849
3850 #[test]
3855 fn test_json_quote_integer() {
3856 assert_eq!(json_quote(&SqliteValue::Integer(42)).unwrap(), "42");
3857 assert_eq!(json_quote(&SqliteValue::Integer(-1)).unwrap(), "-1");
3858 }
3859
3860 #[test]
3861 fn test_json_quote_float() {
3862 #[allow(clippy::approx_constant)]
3863 let result = json_quote(&SqliteValue::Float(3.14)).unwrap();
3864 assert!(result.starts_with("3.14"));
3865 }
3866
3867 #[test]
3868 fn test_json_quote_float_infinity() {
3869 assert_eq!(
3870 json_quote(&SqliteValue::Float(f64::INFINITY)).unwrap(),
3871 "null"
3872 );
3873 assert_eq!(
3874 json_quote(&SqliteValue::Float(f64::NEG_INFINITY)).unwrap(),
3875 "null"
3876 );
3877 assert_eq!(json_quote(&SqliteValue::Float(f64::NAN)).unwrap(), "null");
3878 }
3879
3880 #[test]
3881 fn test_json_quote_blob() {
3882 let result = json_quote(&SqliteValue::Blob(Arc::from(vec![0xDE, 0xAD])));
3883 assert!(result.is_err());
3884 assert!(
3885 result
3886 .unwrap_err()
3887 .to_string()
3888 .contains("JSON cannot hold BLOB values")
3889 );
3890 }
3891
3892 #[test]
3893 fn test_json_quote_text_special_chars() {
3894 let result = json_quote(&SqliteValue::Text(Arc::from("a\"b\\c"))).unwrap();
3895 assert!(result.contains("\\\""));
3896 assert!(result.contains("\\\\"));
3897 }
3898
3899 #[test]
3904 fn test_json_object_odd_args_error() {
3905 let err = json_object(&[
3906 SqliteValue::Text(Arc::from("a")),
3907 SqliteValue::Integer(1),
3908 SqliteValue::Text(Arc::from("b")),
3909 ]);
3910 assert!(err.is_err());
3911 }
3912
3913 #[test]
3914 fn test_json_object_non_text_key_error() {
3915 let err = json_object(&[SqliteValue::Integer(1), SqliteValue::Integer(2)]);
3916 assert!(err.is_err());
3917 }
3918
3919 #[test]
3920 fn test_json_object_empty() {
3921 assert_eq!(json_object(&[]).unwrap(), "{}");
3922 }
3923
3924 #[test]
3925 fn test_json_object_duplicate_keys() {
3926 let out = json_object(&[
3927 SqliteValue::Text(Arc::from("k")),
3928 SqliteValue::Integer(1),
3929 SqliteValue::Text(Arc::from("k")),
3930 SqliteValue::Integer(2),
3931 ])
3932 .unwrap();
3933 assert_eq!(out, r#"{"k":2}"#);
3934 }
3935
3936 #[test]
3941 fn test_json_set_array_element() {
3942 let out = json_set("[1,2,3]", &[("$[1]", SqliteValue::Integer(99))]).unwrap();
3943 assert_eq!(out, "[1,99,3]");
3944 }
3945
3946 #[test]
3947 fn test_json_set_array_append_at_len() {
3948 let out = json_set("[1,2]", &[("$[2]", SqliteValue::Integer(3))]).unwrap();
3949 assert_eq!(out, "[1,2,3]");
3950 }
3951
3952 #[test]
3953 fn test_json_insert_array_append_at_len() {
3954 let out = json_insert("[1,2]", &[("$[2]", SqliteValue::Integer(3))]).unwrap();
3955 assert_eq!(out, "[1,2,3]");
3956 }
3957
3958 #[test]
3959 fn test_json_set_append_pseudo_index() {
3960 let out = json_set("[1,2]", &[("$[#]", SqliteValue::Integer(3))]).unwrap();
3961 assert_eq!(out, "[1,2,3]");
3962 }
3963
3964 #[test]
3965 fn test_json_replace_append_pseudo_index_noop() {
3966 let out = json_replace("[1,2]", &[("$[#]", SqliteValue::Integer(3))]).unwrap();
3967 assert_eq!(out, "[1,2]");
3968 }
3969
3970 #[test]
3971 fn test_json_replace_array_element() {
3972 let out = json_replace("[1,2,3]", &[("$[0]", SqliteValue::Integer(0))]).unwrap();
3973 assert_eq!(out, "[0,2,3]");
3974 }
3975
3976 #[test]
3977 fn test_json_set_multiple_paths() {
3978 let out = json_set(
3979 r#"{"a":1,"b":2}"#,
3980 &[
3981 ("$.a", SqliteValue::Integer(10)),
3982 ("$.c", SqliteValue::Integer(30)),
3983 ],
3984 )
3985 .unwrap();
3986 let parsed: serde_json::Value = serde_json::from_str(&out).unwrap();
3987 assert_eq!(parsed["a"], 10);
3988 assert_eq!(parsed["c"], 30);
3989 }
3990
3991 #[test]
3996 fn test_json_remove_missing_key_no_change() {
3997 let out = json_remove(r#"{"a":1}"#, &["$.b"]).unwrap();
3998 assert_eq!(out, r#"{"a":1}"#);
3999 }
4000
4001 #[test]
4002 fn test_json_remove_multiple_paths() {
4003 let out = json_remove(r#"{"a":1,"b":2,"c":3}"#, &["$.a", "$.c"]).unwrap();
4004 assert_eq!(out, r#"{"b":2}"#);
4005 }
4006
4007 #[test]
4008 fn test_json_remove_from_end_index() {
4009 let out = json_remove("[1,2,3]", &["$[#-1]"]).unwrap();
4010 assert_eq!(out, "[1,2]");
4011 }
4012
4013 #[test]
4018 fn test_json_patch_non_object_replaces() {
4019 let out = json_patch(r#"{"a":1}"#, "42").unwrap();
4020 assert_eq!(out, "42");
4021 }
4022
4023 #[test]
4024 fn test_json_patch_nested_merge() {
4025 let out = json_patch(r#"{"a":{"b":1,"c":2}}"#, r#"{"a":{"b":10,"d":4}}"#).unwrap();
4026 let parsed: serde_json::Value = serde_json::from_str(&out).unwrap();
4027 assert_eq!(parsed["a"]["b"], 10);
4028 assert_eq!(parsed["a"]["c"], 2);
4029 assert_eq!(parsed["a"]["d"], 4);
4030 }
4031
4032 #[test]
4037 fn test_json_each_scalar() {
4038 let rows = json_each("42", None).unwrap();
4039 assert_eq!(rows.len(), 1);
4040 assert_eq!(rows[0].key, SqliteValue::Null);
4041 assert_eq!(rows[0].value, SqliteValue::Integer(42));
4042 assert_eq!(rows[0].type_name, "integer");
4043 }
4044
4045 #[test]
4046 fn test_json_each_empty_array() {
4047 let rows = json_each("[]", None).unwrap();
4048 assert!(rows.is_empty());
4049 }
4050
4051 #[test]
4052 fn test_json_each_empty_object() {
4053 let rows = json_each("{}", None).unwrap();
4054 assert!(rows.is_empty());
4055 }
4056
4057 #[test]
4058 fn test_json_each_missing_path() {
4059 let rows = json_each(r#"{"a":1}"#, Some("$.b")).unwrap();
4060 assert!(rows.is_empty());
4061 }
4062
4063 #[test]
4068 fn test_json_tree_scalar() {
4069 let rows = json_tree("42", None).unwrap();
4070 assert_eq!(rows.len(), 1);
4071 assert_eq!(rows[0].type_name, "integer");
4072 }
4073
4074 #[test]
4075 fn test_json_tree_empty_array() {
4076 let rows = json_tree("[]", None).unwrap();
4077 assert_eq!(rows.len(), 1);
4078 assert_eq!(rows[0].type_name, "array");
4079 }
4080
4081 #[test]
4082 fn test_json_tree_parent_ids() {
4083 let rows = json_tree(r#"{"a":1}"#, None).unwrap();
4084 assert_eq!(rows.len(), 2);
4085 assert_eq!(rows[0].parent, SqliteValue::Null); assert_eq!(rows[1].parent, SqliteValue::Integer(rows[0].id)); }
4088
4089 #[test]
4090 fn test_json_tree_missing_path() {
4091 let rows = json_tree(r#"{"a":1}"#, Some("$.b")).unwrap();
4092 assert!(rows.is_empty());
4093 }
4094
4095 #[test]
4100 fn test_jsonb_null() {
4101 let blob = jsonb("null").unwrap();
4102 assert_eq!(json_from_jsonb(&blob).unwrap(), "null");
4103 }
4104
4105 #[test]
4106 fn test_jsonb_booleans() {
4107 assert_eq!(json_from_jsonb(&jsonb("true").unwrap()).unwrap(), "true");
4108 assert_eq!(json_from_jsonb(&jsonb("false").unwrap()).unwrap(), "false");
4109 }
4110
4111 #[test]
4112 fn test_jsonb_integer() {
4113 let blob = jsonb("42").unwrap();
4114 assert_eq!(json_from_jsonb(&blob).unwrap(), "42");
4115 }
4116
4117 #[test]
4118 fn test_jsonb_float() {
4119 let blob = jsonb("3.14").unwrap();
4120 let text = json_from_jsonb(&blob).unwrap();
4121 assert!(text.starts_with("3.14"));
4122 }
4123
4124 #[test]
4125 fn test_jsonb_nested_array() {
4126 let blob = jsonb("[[1],[2,3]]").unwrap();
4127 assert_eq!(json_from_jsonb(&blob).unwrap(), "[[1],[2,3]]");
4128 }
4129
4130 #[test]
4131 fn test_jsonb_empty_string() {
4132 let blob = jsonb(r#""""#).unwrap();
4133 assert_eq!(json_from_jsonb(&blob).unwrap(), r#""""#);
4134 }
4135
4136 #[test]
4137 fn test_jsonb_extract_multiple_paths() {
4138 let blob = jsonb_extract(r#"{"a":1,"b":2}"#, &["$.a", "$.b"]).unwrap();
4139 assert_eq!(json_from_jsonb(&blob).unwrap(), "[1,2]");
4140 }
4141
4142 #[test]
4143 fn test_jsonb_extract_no_paths_error() {
4144 let empty: &[&str] = &[];
4145 assert!(jsonb_extract(r#"{"a":1}"#, empty).is_err());
4146 }
4147
4148 #[test]
4149 fn test_jsonb_decode_trailing_bytes() {
4150 let mut blob = jsonb("42").unwrap();
4151 blob.push(0xFF); assert!(json_from_jsonb(&blob).is_err());
4153 assert_eq!(
4154 json_valid_blob(&blob, Some(JSON_VALID_JSONB_SUPERFICIAL_FLAG)),
4155 0
4156 );
4157 }
4158
4159 #[test]
4160 fn test_jsonb_decode_empty() {
4161 assert!(json_from_jsonb(&[]).is_err());
4162 }
4163
4164 #[test]
4169 fn test_path_invalid_no_dollar() {
4170 assert!(json_extract(r#"{"a":1}"#, &["a"]).is_err());
4171 }
4172
4173 #[test]
4174 fn test_path_empty_key_error() {
4175 assert!(json_extract(r#"{"a":1}"#, &["$."]).is_err());
4176 }
4177
4178 #[test]
4179 fn test_path_unclosed_bracket() {
4180 assert!(json_extract(r"[1,2]", &["$[0"]).is_err());
4181 }
4182
4183 #[test]
4184 fn test_path_from_end_zero_error() {
4185 assert!(json_extract("[1,2,3]", &["$[#-0]"]).is_err());
4186 }
4187
4188 #[test]
4189 fn test_path_from_end_beyond_length() {
4190 let result = json_extract("[1,2,3]", &["$[#-10]"]).unwrap();
4191 assert_eq!(result, SqliteValue::Null);
4192 }
4193
4194 #[test]
4199 fn test_json_group_object_non_text_key_error() {
4200 let err = json_group_object(&[(SqliteValue::Integer(1), SqliteValue::Integer(2))]);
4201 assert!(err.is_err());
4202 }
4203
4204 #[test]
4205 fn test_json_group_object_empty() {
4206 assert_eq!(json_group_object(&[]).unwrap(), "{}");
4207 }
4208
4209 #[test]
4214 fn test_json_array_empty() {
4215 assert_eq!(json_array(&[]).unwrap(), "[]");
4216 }
4217
4218 #[test]
4219 fn test_json_array_with_blob() {
4220 let err = json_array(&[SqliteValue::Blob(Arc::from(vec![0xCA, 0xFE]))]).unwrap_err();
4221 assert!(err.to_string().contains("JSON cannot hold BLOB values"));
4222 }
4223}