Почему Rusqlite отклоняет тип Option при выполнении запроса? - PullRequest
1 голос
/ 24 января 2020

Я пытаюсь вставить данные CSV в базу данных SQLite. stripe_id является необязательным, поэтому его тип Option<&str>. Все остальные поля &str. Когда я использую conn.execute для вставки значений, все они вставляются правильно, за исключением stripe_id, который выдает ошибку, говорящую, что ожидает &str, а не Option.

Я искал документы и Option<T> реализует ToSQL, и когда я попытался заменить мой код примером Rusqlite, который включает значение Option, он выдает ту же ошибку для кода примера.

Соответствующая структура и запрос фрагмент кода:

struct Merchant<'a> {
    name: &'a str,
    billing_portal: &'a str,
    billing_period: &'a str,
    stripe_id: Option<&'a str>,
}
conn.execute(
    "INSERT INTO merchants (name, billing_portal, billing_period, stripe_id)
     values (?, ?, ?, ?)",
     &[&merch.name, &merch.billing_portal, &merch.billing_period, &merch.stripe_id]
).expect("Error inserting merchant into database");

Ошибка:

error[E0308]: mismatched types
  --> src/main.rs:38:75
   |
38 |              &[&merch.name, &merch.billing_portal, &merch.billing_period, &merch.stripe_id]
   |                                                                           ^^^^^^^^^^^^^^^^ expected `&str`, found enum `std::option::Option`
   |
   = note: expected reference `&&str`
              found reference `&std::option::Option<&str>`

И полный код:

extern crate csv;
extern crate rusqlite;

use rusqlite::{Connection, Result};

#[derive(Debug)]
struct Merchant<'a> {
    name: &'a str,
    billing_portal: &'a str,
    billing_period: &'a str,
    stripe_id: Option<&'a str>,
}

fn main() -> Result<()> {
    let conn = Connection::open("data.sqlite")?;

    let mut reader = csv::ReaderBuilder::new()
                                        .has_headers(false)
                                        .from_path("merchants.csv")
                                        .expect("Failed to read csv");
    for record in reader.records() {
        let record = record.unwrap();
        let merch = Merchant {
            name: &record[0],
            billing_portal: &record[3],
            billing_period: &record[4],
            stripe_id: (match &record[5] {
                x if x == "" => None,
                x            => Some(x)
            }),
        };
        println!("{:?}", &merch);

        conn.execute(
            "INSERT INTO merchants (name, billing_portal, billing_period, stripe_id)
             values (?, ?, ?, ?)",
             &[&merch.name, &merch.billing_portal, &merch.billing_period, &merch.stripe_id]
        ).expect("Error inserting merchant into database");

    }

    Ok(())
}

1 Ответ

1 голос
/ 24 января 2020

Использование макроса rusqlite::params решает проблему:

use rusqlite::{params, Connection, Result};

fn main() -> Result<()> {
    // ...

    for record in reader.records() {
        // ...

        conn.execute(
            "INSERT INTO merchants (name, billing_portal, billing_period, stripe_id)
             values (?, ?, ?, ?)",
            params![
                &merch.name,
                &merch.billing_portal,
                &merch.billing_period,
                &merch.stripe_id,
            ],
        )
        .expect("Error inserting merchant into database");
    }

    Ok(())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...