Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use rusqlite's Row::get method for a type which I don't know at compile time?

Tags:

sql

rust

I am using Rust's rusqlite crate to insert and recall data from a sqlite database.

I am using the get() method for its Row that returns a Result<T>. I have this current code snippet:

while let Some(row) = rows.next()? {
    let value = match row.get(0).expect("Could not get value from database cell.") {
      // Do something here to specify types and return them or add them to a separate collection
   };
}

How could I specify the type? Currently the only way I can properly unwrap the get function is by assigning it to a variable with a specific type already, like let value: i64 = row.get(0).unwrap(), but I don't know how to differentiate if the get(0) was actually a string or a boolean or any other acceptable SQL type.

I've searched through other examples of match with Result, but their match enums are based off values, not types.

like image 854
Narnian12 Avatar asked Oct 14 '25 08:10

Narnian12


2 Answers

How could I specify the type? Currently the only way I can properly unwrap the get function is by assigning it to a variable with a specific type already, like let value: i64 = row.get(0).unwrap()

If I understand what you want correctly, you're looking for get_raw and get_raw_checked which return a ValueRef enum this way you can check at runtime what type the retrieved value was:

while let Some(row) = rows.next()? {
   let value = match row.get_raw(0) {
         ValueRef::Null => ...
         ValueRef::Integer(i) => ...
         ValueRef::Real(f) => ...
         ValueRef::Text(t) => ...
         ValueRef::Blob(b) => ...
   }
}

get indicates an expectation and returns an Err if the expectation is betrayed, because usually you know what the type of the value stored in the column should be, and if someone went under you and replaced the column or value's type, then everything is broken. It also conveniently handles various conversions so you don't have to handle them by hand.

Incidentally if you don't want to handle the possible error from get you can just use its sibling get_unwrap.

like image 50
Masklinn Avatar answered Oct 17 '25 19:10

Masklinn


The T on your Result<T> is coming from the table scheme, so T's type will be already determined by the database, not by Rust.

Usually a good practice is to create a struct that maps your SQL table like in the example on the documentation.

SQLite side

CREATE TABLE person (
    id              INTEGER PRIMARY KEY,
    name            TEXT NOT NULL,
    time_created    TEXT NOT NULL,
    data            BLOB
)

Rust side

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    time_created: Timespec,
    data: Option<Vec<u8>>,
}
like image 41
Hollay-Horváth Zsombor Avatar answered Oct 17 '25 19:10

Hollay-Horváth Zsombor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!