Reputation: 13
I'm trying to insert CSV data into a SQLite database. stripe_id
is optional, and so its type is Option<&str>
. All the other fields are &str
. When I use conn.execute
to insert the values, they all insert correctly except for stripe_id
, which throws an error saying it expects &str
and not Option
.
I've searched the docs and Option<T>
implements ToSQL
, and when I've tried replacing my code with the Rusqlite example that includes an Option
value, it throws the same error for the example code.
The relevant struct and query code snippet:
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");
The error:
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>`
And the complete code:
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(())
}
Upvotes: 1
Views: 982
Reputation: 13972
Using the rusqlite::params
macro solves the problem:
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(())
}
Upvotes: 3