#![cfg(feature = "std")]
use graphitesql::{Connection, Value};
fn text(c: &Connection, sql: &str) -> String {
match c.query(sql).unwrap().rows.remove(0).remove(0) {
Value::Text(s) => s,
other => panic!("expected text, got {other:?}"),
}
}
fn int(c: &Connection, sql: &str) -> i64 {
match c.query(sql).unwrap().rows.remove(0).remove(0) {
Value::Integer(i) => i,
other => panic!("expected integer, got {other:?}"),
}
}
#[test]
fn unquoted_object_keys() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, "SELECT json('{a:1}')"), r#"{"a":1}"#);
assert_eq!(
text(&c, "SELECT json('{a:1, $b:2, _c:3}')"),
r#"{"a":1,"$b":2,"_c":3}"#
);
assert_eq!(text(&c, "SELECT json('{a:{b:5}}')"), r#"{"a":{"b":5}}"#);
assert_eq!(int(&c, "SELECT json_extract('{a:{b:5}}','$.a.b')"), 5);
}
#[test]
fn single_quoted_strings() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, "SELECT json('{''k'':''v''}')"), r#"{"k":"v"}"#);
assert_eq!(
text(&c, r#"SELECT json('{x:''a\'' b''}')"#),
r#"{"x":"a' b"}"#
);
assert_eq!(text(&c, r#"SELECT json('"a\'' b"')"#), r#""a' b""#);
}
#[test]
fn trailing_commas() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, r#"SELECT json('{"a":1,}')"#), r#"{"a":1}"#);
assert_eq!(text(&c, "SELECT json('[1,2,]')"), "[1,2]");
assert_eq!(
text(&c, "SELECT json('{a:1, b:[2,3,], c:{d:4,}}')"),
r#"{"a":1,"b":[2,3],"c":{"d":4}}"#
);
assert!(c.query("SELECT json('[,]')").is_err());
assert!(c.query("SELECT json('[1,,]')").is_err());
assert!(c.query("SELECT json('{,}')").is_err());
}
#[test]
fn comments() {
let c = Connection::open_memory().unwrap();
assert_eq!(
text(&c, "SELECT json('[1, /* block */ 2, // line\n3]')"),
"[1,2,3]"
);
assert_eq!(text(&c, "SELECT json('// hi\n5')"), "5");
assert_eq!(text(&c, "SELECT json('[/* a */]')"), "[]");
assert_eq!(text(&c, "SELECT json('{ /* */ }')"), "{}");
assert_eq!(int(&c, "SELECT json_error_position('/* x */ 5')"), 0);
assert_eq!(int(&c, "SELECT json_error_position('/* unterminated')"), 1);
}
#[test]
fn numbers() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, "SELECT json('+5')"), "5");
assert_eq!(text(&c, "SELECT json('.5')"), "0.5");
assert_eq!(text(&c, "SELECT json('5.')"), "5.0");
assert_eq!(text(&c, "SELECT json('+.5')"), "0.5");
assert_eq!(text(&c, "SELECT json('-.5')"), "-0.5");
assert_eq!(text(&c, "SELECT json('0xFF')"), "255");
assert_eq!(text(&c, "SELECT json('0x10')"), "16");
assert_eq!(text(&c, "SELECT json('-0x10')"), "-16");
assert_eq!(text(&c, "SELECT json('+0x10')"), "16");
assert_eq!(text(&c, "SELECT json_type('0x10')"), "integer");
assert_eq!(
text(&c, "SELECT json('0x7FFFFFFFFFFFFFFF')"),
"9223372036854775807"
);
assert_eq!(
int(&c, "SELECT json_extract('[0xFFFFFFFFFFFFFFFF]','$[0]')"),
-1
);
}
#[test]
fn infinity_and_nan() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, "SELECT json('Infinity')"), "9e999");
assert_eq!(text(&c, "SELECT json('-Infinity')"), "-9e999");
assert_eq!(text(&c, "SELECT json('+Infinity')"), "9e999");
assert_eq!(text(&c, "SELECT json_type('Infinity')"), "real");
assert_eq!(text(&c, "SELECT json('NaN')"), "null");
assert_eq!(text(&c, "SELECT json_type('NaN')"), "null");
assert_eq!(
text(&c, "SELECT json('[Infinity, NaN, -Infinity]')"),
"[9e999,null,-9e999]"
);
assert_eq!(
text(&c, "SELECT json('{a:Infinity, b:NaN}')"),
r#"{"a":9e999,"b":null}"#
);
}
#[test]
fn string_escapes() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, "SELECT json('\"a\\\nb\"')"), r#""ab""#);
assert_eq!(
int(&c, r#"SELECT unicode(json_extract('{"x":"\x41"}','$.x'))"#),
65 );
assert_eq!(
text(&c, r#"SELECT hex(json_extract('{"x":"\0"}','$.x'))"#),
"00"
);
assert_eq!(
int(&c, r#"SELECT length(json_extract('{"x":"\0"}','$.x'))"#),
0 );
}
#[test]
fn json_valid_is_strict_rfc8259() {
let c = Connection::open_memory().unwrap();
assert_eq!(int(&c, "SELECT json_valid('{a:1}')"), 0); assert_eq!(int(&c, r#"SELECT json_valid('{"a":1,}')"#), 0); assert_eq!(int(&c, "SELECT json_valid('[1,2,]')"), 0); assert_eq!(int(&c, "SELECT json_valid('\"x\"')"), 1); assert_eq!(int(&c, r#"SELECT json_valid('{"a":1}')"#), 1);
assert_eq!(int(&c, "SELECT json_valid('[1,2]')"), 1);
assert_eq!(int(&c, "SELECT json_valid('5')"), 1);
assert_eq!(int(&c, "SELECT json_valid('1.5e3')"), 1);
assert_eq!(int(&c, "SELECT json_valid('{bad}')"), 0);
assert_eq!(int(&c, "SELECT json_valid('nul')"), 0);
}
#[test]
fn strict_json_unchanged() {
let c = Connection::open_memory().unwrap();
assert_eq!(text(&c, r#"SELECT json(' {"a":1} ')"#), r#"{"a":1}"#);
assert_eq!(text(&c, "SELECT json(' [ 1, 2 ,3 ] ')"), "[1,2,3]");
assert_eq!(
text(&c, r#"SELECT json('{"z":1,"a":2}')"#),
r#"{"z":1,"a":2}"#
);
assert_eq!(text(&c, r#"SELECT json('"hello"')"#), r#""hello""#);
}