#![recursion_limit = "512"]
use fsqlite_core::connection::Connection;
use fsqlite_types::value::SqliteValue;
fn tag_f(v: &SqliteValue) -> String {
match v {
SqliteValue::Null => "NULL".to_owned(),
SqliteValue::Integer(n) => n.to_string(),
SqliteValue::Float(f) => format!("{f}"),
SqliteValue::Text(s) => format!("'{s}'"),
SqliteValue::Blob(b) => format!("X'{}'", b.iter().map(|x| format!("{x:02X}")).collect::<String>()),
}
}
fn tag_r(v: &rusqlite::types::Value) -> String {
match v {
rusqlite::types::Value::Null => "NULL".to_owned(),
rusqlite::types::Value::Integer(n) => n.to_string(),
rusqlite::types::Value::Real(f) => format!("{f}"),
rusqlite::types::Value::Text(s) => format!("'{s}'"),
rusqlite::types::Value::Blob(b) => format!("X'{}'", b.iter().map(|x| format!("{x:02X}")).collect::<String>()),
}
}
async fn assert_agree(fconn: &Connection, rconn: &rusqlite::Connection, sql: &str) {
let mut fr: Vec<Vec<String>> = fconn.query(sql).await.unwrap_or_else(|e| panic!("{sql}: {e:?}")).iter().map(|r| r.values().iter().map(tag_f).collect()).collect();
fr.sort();
let mut st = rconn.prepare(sql).unwrap();
let n = st.column_count();
let mut rr: Vec<Vec<String>> = st.query_map([], |row| Ok((0..n).map(|i| tag_r(&row.get_unwrap::<_, rusqlite::types::Value>(i))).collect())).unwrap().collect::<Result<Vec<_>, _>>().unwrap();
rr.sort();
assert_eq!(fr, rr, "string-function code-point mismatch on `{sql}`");
}
async fn seed(fconn: &Connection, rconn: &rusqlite::Connection) {
for s in [
"CREATE TABLE t (id INTEGER PRIMARY KEY, s TEXT)",
"INSERT INTO t VALUES (1,'café'),(2,'€uro'),(3,'a🦀b𐍈c'),(4,'naïve'),(5,'')",
] {
fconn.execute(s).await.unwrap();
rconn.execute_batch(s).unwrap();
}
}
#[test]
fn bld9w6_length_counts_code_points() {
asupersync::test_utils::run_test(|| async {
let f = Connection::open(":memory:").await.unwrap();
let r = rusqlite::Connection::open_in_memory().unwrap();
seed(&f, &r).await;
assert_agree(&f, &r, "SELECT id, length(s) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT length(CAST('café' AS BLOB))").await;
});
}
#[test]
fn bld9w6_substr_indexes_code_points() {
asupersync::test_utils::run_test(|| async {
let f = Connection::open(":memory:").await.unwrap();
let r = rusqlite::Connection::open_in_memory().unwrap();
seed(&f, &r).await;
assert_agree(&f, &r, "SELECT id, substr(s,2) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, substr(s,2,2) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, substr(s,-2) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, substr(s,-2,1) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, substr(s,0,3) FROM t ORDER BY id").await;
});
}
#[test]
fn bld9w6_instr_and_replace_code_points() {
asupersync::test_utils::run_test(|| async {
let f = Connection::open(":memory:").await.unwrap();
let r = rusqlite::Connection::open_in_memory().unwrap();
seed(&f, &r).await;
assert_agree(&f, &r, "SELECT id, instr(s,'🦀') FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, instr(s,'é') FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT instr('a🦀b𐍈c','b')").await;
assert_agree(&f, &r, "SELECT id, replace(s,'é','E') FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT replace('a🦀b🦀c','🦀','__')").await;
});
}
#[test]
fn bld9w6_typeof_and_upper_lower_ascii_scope() {
asupersync::test_utils::run_test(|| async {
let f = Connection::open(":memory:").await.unwrap();
let r = rusqlite::Connection::open_in_memory().unwrap();
seed(&f, &r).await;
assert_agree(&f, &r, "SELECT id, typeof(s) FROM t ORDER BY id").await;
assert_agree(&f, &r, "SELECT id, upper(s), lower(s) FROM t ORDER BY id").await;
});
}