sql_support/
debug_tools.rs1use rusqlite::{functions::Context, types::Value, Connection};
10
11#[cfg(feature = "debug-tools")]
14pub fn print_query(conn: &Connection, query: &str) -> rusqlite::Result<()> {
15 use text_table::{Row, Table};
16
17 let mut stmt = conn.prepare(query)?;
18 let mut rows = stmt.query([])?;
19 let mut table = Table::new();
20 let mut titles = Row::empty();
21 for col in rows.as_ref().expect("must have statement").columns() {
22 titles = titles.add_cell(col.name());
23 }
24 table.add_row(titles);
25 while let Some(sql_row) = rows.next()? {
26 let mut table_row = Row::empty();
27 for i in 0..sql_row.as_ref().column_count() {
28 let val = match sql_row.get::<_, Value>(i)? {
29 Value::Null => "null".to_string(),
30 Value::Integer(i) => i.to_string(),
31 Value::Real(f) => f.to_string(),
32 Value::Text(s) => s,
33 Value::Blob(b) => format!("<blob with {} bytes>", b.len()),
34 };
35 table_row = table_row.add_cell(&val);
36 }
37 table.add_row(table_row);
38 }
39 use std::io::Write;
41 std::io::stdout()
42 .write_all(format!("query: {query}\n").as_bytes())
43 .unwrap();
44 table.printstd();
45 Ok(())
46}
47
48#[cfg(feature = "debug-tools")]
49#[inline(never)]
50fn dbg(ctx: &Context<'_>) -> rusqlite::Result<Value> {
51 let mut s = Value::Null;
52 for i in 0..ctx.len() {
53 let raw = ctx.get_raw(i);
54 let str_repr = match raw {
55 rusqlite::types::ValueRef::Text(_) => raw.as_str().unwrap().to_owned(),
56 _ => format!("{:?}", raw),
57 };
58 eprint!("{} ", str_repr);
59 s = raw.into();
60 }
61 eprintln!();
62 Ok(s)
63}
64
65#[cfg(not(feature = "debug-tools"))]
66fn dbg(ctx: &Context<'_>) -> rusqlite::Result<Value> {
70 Ok(if ctx.is_empty() {
71 Value::Null
72 } else {
73 ctx.get_raw(ctx.len() - 1).into()
74 })
75}
76
77pub fn define_debug_functions(c: &Connection) -> rusqlite::Result<()> {
99 use rusqlite::functions::FunctionFlags;
100 c.create_scalar_function("dbg", -1, FunctionFlags::SQLITE_UTF8, dbg)?;
101 Ok(())
102}
103
104#[cfg(test)]
105mod test {
106 use super::*;
107 use crate::conn_ext::ConnExt;
108
109 #[test]
110 fn test_dbg() {
111 let conn = Connection::open_with_flags(":memory:", rusqlite::OpenFlags::default()).unwrap();
112 define_debug_functions(&conn).unwrap();
113 assert_eq!(
114 conn.conn_ext_query_one::<i64>("SELECT dbg('foo', 0);")
115 .unwrap(),
116 0
117 );
118 assert_eq!(
119 conn.conn_ext_query_one::<String>("SELECT dbg('foo');")
120 .unwrap(),
121 "foo"
122 );
123 assert_eq!(
124 conn.conn_ext_query_one::<Option<String>>("SELECT dbg();")
125 .unwrap(),
126 None
127 );
128 }
129}