[Rust] mit Diesel und PostgreSql 15

Sooo, nun habe ich einen weiteren Step in meiner „Rust“ Erfahrung gemacht, ich möchte meine Reise wieder mit euch teilen:

Wie kann ich mit Rust und Diesel auf eine PostgreSQL Datenbank zugreifen? Das erkläre ich euch nachstehend:

Wie wir Diesel installieren, habe ich im Beitrag https://www.predl.cc/rust-diesel-fuer…ows-installieren/ erklärt, bitte da starten, falls Diesel noch nicht am PC ist. Die Rust Installation habe ich kurz am Anfang des Beitrages angerissen, jedoch denke ich von dem Punkt kommt jeder weiter…

Zuerst einmal erstellen wir unser erstes Projekt. Wir öffnen ein cmd Fenster und schreiben

cargo new diesel_example

Dann cd ins Verzeichnis:

cd diesel_example

So nun ist das Projekt erstellt, wir finden nun im Verzeichnis folgende Dateien (nur die Wichtigsten!):

diesel_example/
|-- Cargo.toml # Unsere Konfigurationsdatei fürs Projekt
|-- src/
|   |-- main.rs  # Das Projekt main.rs, hier startet alles

So nun können wir erstmal die Cargo.toml öffnen:

[package]
name = "diesel_example"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

Das ändern wir auf:

[package]
name = "diesel_example"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
diesel = { version = "*", features = ["postgres"] }
dotenv = "*"
diesel_codegen = "*"  # Füge diesel_codegen hinzu

Damit haben wir bereits Diesel als Abhängigkeit hinzugefügt, codegen erlaubt uns, die Schema.rs automatisch aus der Datenbank zu erstellen, sehr nützlich.
dann erstellen wir eine .env Datei und schreiben hinein:

DATABASE_URL=postgres://postgres:{password}@localhost/diesel_example

{password} bitte mit Ihrem Passwort ersetzen.
Dann müssen wir noch die main.rs aus dem src Verzeichnis ändern:

extern crate diesel;
extern crate dotenv;

use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

table! {
    users (user_id) {
        user_id -> Int8,
        user_name -> Varchar,
        user_password -> Varchar,
    }
}

//use schema::users;cls

// Diesel-Verbindung initialisieren
fn establish_connection() -> PgConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL not found in .env");
    PgConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url))
}

fn main() {
    let mut connection = establish_connection();

    // Hier verwenden wir Diesel-Abfragen, um alle Benutzer aus der Tabelle "users" abzurufen
    let all_users = users::table.load::<(i64, String, String)>(&mut connection) // mutable Verweis
        .expect("Error loading users");

    for user in all_users {
        let (user_id, user_name, user_password) = user;
        println!("User ID: {}, User Name: {}, User Password: {}", user_id, user_name, user_password);
    }

}

Damit sind wir fast fertig, nur noch in pgAdmin eine datenbank anlegen, wir benennen diese einfach „diesel_example“…

CREATE TABLE IF NOT EXISTS public.users
(
    user_id bigint NOT NULL DEFAULT nextval('users_user_id_seq'::regclass),
    user_name character varying(35) COLLATE pg_catalog."default" NOT NULL,
    user_password character varying(35) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT users_pkey PRIMARY KEY (user_id)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS public.users
    OWNER to postgres;

Wir können gleich ein paar Datensätze in die PostgreSQL Datenbank speichern:

insert into users (user_name, user_password) values('alex','password');
insert into users (user_name, user_password) values('admin','password');
insert into users (user_name, user_password) values('john','password');

Dann sehen wir auch eine Ausgabe vom Rust Projekt.

diesel setup

Damit wird die migration erstellt (also eine Datenbank Versions Kontrolle)

diesel migration run

Das erstellt die schema.rs im /src Verzeichnis! Das ist die Struktur der Tabellen, die brauchen wir später

cargo run

Damit startet man dann das Projekt, zuerst wird laaaange kompiliert und dann ausgeführt, später dauert der Vorgang nicht mehr so lange, da verwendet Cargo die bereits kompilierten Komponenten und das geht viel schneller.
Die Ausgabe:

   Compiling proc-macro2 v1.0.67
      Compiling unicode-ident v1.0.12
      Compiling unicode-xid v0.0.4
      Compiling synom v0.11.3
      Compiling regex v0.2.11
      Compiling quote v0.3.15
      Compiling quote v1.0.33
      Compiling syn v2.0.33
      Compiling lazy_static v1.4.0
      Compiling serde v1.0.188
      Compiling memchr v2.6.3
      Compiling ucd-util v0.1.10
      Compiling vcpkg v0.2.15
      Compiling pq-sys v0.4.8
      Compiling regex-syntax v0.5.6
      Compiling serde_derive v1.0.188
      Compiling aho-corasick v0.6.10
      Compiling thread_local v0.3.6
      Compiling syn v0.11.11
      Compiling byteorder v1.4.3
      Compiling itoa v1.0.9
      Compiling utf8-ranges v1.0.5
      Compiling serde_json v1.0.107
      Compiling derive-error-chain v0.10.1
      Compiling diesel_table_macro_syntax v0.1.0
      Compiling error-chain v0.10.0
      Compiling ryu v1.0.15
      Compiling dotenv v0.10.1
      Compiling diesel_derives v2.1.1
      Compiling diesel v0.16.0
      Compiling bitflags v2.4.0
      Compiling diesel_codegen v0.16.1
      Compiling dotenv v0.15.0
      Compiling diesel v2.1.1
      Compiling diesel_example v0.1.0 (C:\rust_projects\diesel_example)
    Finished dev [unoptimized + debuginfo] target(s) in 2m 02s
     Running `target\debug\diesel_example.exe`
User ID: 1, User Name: alex, User Password: password
User ID: 2, User Name: admin, User Password: password
User ID: 3, User Name: john, User Password: password

Dauert etwa 3-4 Minuten, nachdem aber das Projekt erstellt wurde, geht es wesentlich schneller:

    Finished dev [unoptimized + debuginfo] target(s) in 0.16s
     Running `target\debug\diesel_example.exe`
User ID: 1, User Name: alex, User Password: password
User ID: 2, User Name: admin, User Password: password
User ID: 3, User Name: john, User Password: password

Dann nur mehr Sekunden…

cargo build

Das Projekt wird nur kompiliert, keine Ausführung.

cargo clean

Falls sich die Importe stark ändern, es sich ein Fehler eingeschlichen hat usw. kann man wieder von vorne anfangen.

Getestet unter Windows 10 (wird unter Windows 11 sicher auch gehen!), müsste aber auch so in Linux funktionieren…

Wie immer, alle Angaben ohne Gewähr, Anwendung auf eigene Gefahr und Verantwortung, ich übernehme keinerlei Haftung für Ausfälle, Datenverlust oder andere finanzielle Schäden.

Happy coding!