带有"InvalidColumnType(0,Null)"的SUM恐慌的Rusqlite查询

ede*_*ngh 1 sqlite rust

我有这个工作代码:

extern crate rusqlite;

use rusqlite::Connection;

fn main() {
    let conn = Connection::open("db.sqlite").unwrap();

    conn.execute("CREATE TABLE toto (size INTEGER NOT NULL DEFAULT 0);", &[]).unwrap();
    conn.execute("INSERT INTO toto(size) VALUES (42);", &[]).unwrap();

    let filter = 0;
    let i: i64 = conn.query_row("SELECT SUM(size) FROM toto", &[], |r| r.get(0)).unwrap();
    println!("Coucou");
    println!("Coucou: {}", i);
}
Run Code Online (Sandbox Code Playgroud)

但如果我改变

"SELECT SUM(size) FROM toto", &[]
Run Code Online (Sandbox Code Playgroud)

"SELECT SUM(size) FROM toto WHERE size=?1", &[&filter]
Run Code Online (Sandbox Code Playgroud)

它重新运行,恐慌:

rm db.sqlite
RUST_BACKTRACE=1 cargo run
Run Code Online (Sandbox Code Playgroud)
        Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
         Running `target/debug/testsqlite`
    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidColumnType(0, Null)', /checkout/src/libcore/result.rs:860
Run Code Online (Sandbox Code Playgroud)

如果我在sqliteman中执行此查询,它可以工作,那么为什么rusqlite会出现恐慌?

She*_*ter 8

如果我直接在sqlite命令行实用程序中运行查询,则没有值,结果是NULL:

sqlite> SELECT SUM(size) FROM toto WHERE size=42;

sqlite> SELECT coalesce(SUM(size), 'NULL!') FROM toto WHERE size=42;
NULL!
sqlite>
Run Code Online (Sandbox Code Playgroud)

由于没有与where子句匹配的行,因此总和为NULL:

如果没有非NULL输入行,则sum()返回NULL但total()返回0.0

您的NULL结果无法转换为i64,因此您收到错误消息:

InvalidColumnType(0, Null)

如果你打印出那个错误,它会说同样的事情:

let i: i64 = conn.query_row("SELECT SUM(size) FROM toto WHERE size = ?1", &[&filter], |r| {
    match r.get_checked(0) {
        Ok(v) => v,
        Err(e) => panic!("query_row error: {}", e),
    }
}).expect("select failed");
Run Code Online (Sandbox Code Playgroud)

query_row错误:索引处的列类型无效:0

修复它生锈的一面

如果您NULL使用a更新代码以考虑a Option,它将正确执行:

let i: Option<i64> = conn.query_row(
    "SELECT SUM(size) FROM toto WHERE size = ?1",
    &[&filter],
    |r| r.get(0)
).expect("select failed");
Run Code Online (Sandbox Code Playgroud)

然后你可以使用i.unwrap_or(0).

用SQL修复它 TOTAL

let i: f64 = conn.query_row(
    "SELECT TOTAL(size) FROM toto WHERE size = ?1",
    &[&filter],
    |r| r.get(0)
).expect("select failed");
Run Code Online (Sandbox Code Playgroud)

请注意,我们切换到了f64.

用SQL修复它 COALESCE

let i: i64 = conn.query_row(
    "SELECT COALESCE(SUM(size), 0) FROM toto WHERE size = ?1",
    &[&filter],
    |r| r.get(0)
).expect("select failed");
Run Code Online (Sandbox Code Playgroud)