Rust and sqlite, which one to use?

Hi, I want to test rust with sqlite.
What wraper is stable?, What crate should I use?
Note: I have rustc 1.67.1 (d5a82bbd2 2023-02-07)

Thanks.

1 Like

I'd probably go with rusqlite.

2 Likes

does not require external dependencies or crates?

Well, it obviously depends on libsqlite3 (though you can request that it be built from source), and it has some third-party crate dependencies. If you don't want to depend on a bunch of crates you could always use libsqlite3-sys directly, but it'll be kind of a pain.

I use Debian 10.
believe that installing solve libsqlite3-0 ??

You don't have to install any packages if you depend on rusqlite like this:

[dependencies]
rusqlite = {version = "0.28.0", features = ["bundled"]}

This causes rusqlite to compile its own private libsqlite3 and link it with your Rust code, instead of using /usr/lib/x86_64-linux-gnu/libsqlite3.so or whatever.

If you want to link to the system libsqlite3, you can leave out the features = ["bundled"] part and apt install libsqlite3-0, as you say.

1 Like

2 steps ??

  1. So I declare dependencies like this in Cargo.toml:
    rusqlite = { version = "0.28.0", features = ["bundled"] }

  2. cargo run

Step one can be performed like so.

cargo add rusqlite --features bundled 
2 Likes

Take long time download.?
downloaded so far 200 mb aprox ...

END WITH:
cargo add rusqlite --features bundled
Updating crates.io index
Adding rusqlite v0.28.0 to dependencies.
Features:
+ bundled
+ modern_sqlite
- array
- backup
- blob
- buildtime_bindgen
- bundled-full
- bundled-sqlcipher
- bundled-sqlcipher-vendored-openssl
- bundled-windows
- chrono
- collation
- column_decltype
- csv
- csvtab
- extra_check
- functions
- hooks
- i128_blob
- in_gecko
- lazy_static
- limits
- load_extension
- modern-full
- release_memory
- serde_json
- series
- session
- sqlcipher
- time
- trace
- unlock_notify
- url
- uuid
- vtab
- wasm32-wasi-vfs
- window
- winsqlite3
- with-asan

AND AFTER RUN:
cargo run
Downloaded fallible-streaming-iterator v0.1.9
Downloaded cfg-if v1.0.0
Downloaded version_check v0.9.4
...

rusqlite has also been recommended in this other thread:

1 Like

where cargo download all dependencies? in my system? or rust folder ?

For reference, here's the complete dependency tree of rusqlite with only the modern_sqlite and bundled features enabled (you can see this for your own project with cargo tree):

└── rusqlite v0.28.0
    ├── bitflags v1.3.2
    ├── fallible-iterator v0.2.0
    ├── fallible-streaming-iterator v0.1.9
    ├── hashlink v0.8.1
    │   └── hashbrown v0.12.3
    │       └── ahash v0.7.6
    │           ├── getrandom v0.2.8
    │           │   ├── cfg-if v1.0.0
    │           │   └── libc v0.2.140
    │           └── once_cell v1.17.1
    │           [build-dependencies]
    │           └── version_check v0.9.4
    ├── libsqlite3-sys v0.25.2
    │   [build-dependencies]
    │   ├── cc v1.0.79
    │   ├── pkg-config v0.3.26
    │   └── vcpkg v0.2.15
    └── smallvec v1.10.0

Anything that says [build-dependencies] is not actually used by your compiled application.

2 Likes

Hi, i continue learn and testing in Rust, but i'm clumsy. This code work fine, and the OUTPUT is:
Found person Person { id: 21, name: "Steven", data: "Data1" }
HOW TO SHOW A BEAUTIFUL OUTPUT ??

I continue to clarify about, (Option(Some and None), Result(Ok, Err) etc etc).

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

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    age: u8,
    data: String,
}

fn main() -> Result<()> {
    let conn = Connection::open_in_memory()?;

    conn.execute(
        "CREATE TABLE person (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL,
                  age           INTEGER,
                  data            TEXT
                  )",
        [],
    )?;
    let me = Person {
        id: 0,
        name: "Steven".to_string(),
        age:1,
        data: "data1".to_string(),
    };
    conn.execute(
        "INSERT INTO person (name, age, data) VALUES (?1, ?2, ?3)",
        params![me.name, me.age, me.data],
    )?;

    conn.execute(
        "INSERT INTO person (name, age, data) VALUES (?1, ?2, ?3)",
        params!["john".to_string(), 2, "data2".to_string()],
    )?;
    
    let age:u8 = 1;
    
    let mut stmt = conn.prepare("SELECT id, name, age, data FROM person WHERE age=:age;")?;
    let person_iter = stmt.query_map(&[(":age", age.to_string().as_str())], |row| {
        Ok(Person {
            id: row.get(0)?,
            name: row.get(1)?,
            age: row.get(2)?,
            data: row.get(3)?,
        })
    })?;

    for person in person_iter {
        println!("Found person {:?}", person);
    }

    Ok(())

Define beautiful. Normally you'd implement the Display trait for Person, format its field however you like and use the normal formatter:

println!("Found person {}", person);

See the fmt module's documentation for an overview over how Rust does string formatting.

1 Like

The letter "Person" is a Struct. why is it show ?
Thanks.

This is a derive macro implementing the Debug trait. The trait is invoked by your call here:

The {:?} is the formatter that invokes Debug. {} is the formatter that invokes the aforementioned Display trait.

#[derive(Debug)] creates a default implementation for Person which looks like what you see in your console. You could implement it yourself and format your person however you like.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.