Travailler avec les bases de données en Rust : PostgreSQL et MongoDB en pratique

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi Rust et les bases de données sont une combinaison puissante

Rust est un langage de programmation système qui combine les performances du C/C++ avec la sécurité de la mémoire. Cependant, pendant longtemps, l'écosystème de travail avec les bases de données en Rust était considéré comme "brut". Aujourd'hui, la situation a radicalement changé : les bibliothèques sqlx (pour PostgreSQL) et le pilote officiel mongodb fournissent des API matures, asynchrones et sécurisées.

Dans cet article, nous allons voir en pratique comment se connecter à PostgreSQL et MongoDB depuis Rust, effectuer des opérations CRUD et gérer les erreurs. Tous les exemples utiliseront le runtime asynchrone tokio.



1. Configuration du projet et installation des dépendances

Créez un nouveau projet Cargo :

cargo new rust_db_examplecd rust_db_example

Ajoutez les dépendances suivantes dans Cargo.toml :

[dependencies]tokio = { version = "1", features = ["full"] }sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }mongodb = "2.8"serde = { version = "1", features = ["derive"] }anyhow = "1"
  • sqlx — pilote asynchrone pour PostgreSQL avec vérification des requêtes à la compilation.
  • mongodb — pilote officiel de MongoDB Inc.
  • serde — pour la sérialisation/désérialisation des structures.
  • anyhow — pour une gestion pratique des erreurs.


2. Travailler avec PostgreSQL via sqlx

2.1 Connexion à la base de données

Pour la connexion, utilisez une chaîne de connexion de la forme postgres://user:password@localhost/dbname. Exemple :

use sqlx::postgres::PgPool;use anyhow::Result;

#[tokio::main]async fn main() -> Result<()> { let pool = PgPool::connect("postgres://postgres:password@localhost/testdb").await?; println!("Connexion à PostgreSQL établie !"); Ok(())}


2.2 Création de la table et insertion de données

Définissons la structure User et effectuons la migration :

use serde::{Deserialize, Serialize};use sqlx::FromRow;

#[derive(Debug, Serialize, Deserialize, FromRow)]struct User { id: i32, name: String, email: String,}

async fn create_table(pool: &PgPool) -> Result<()> { sqlx::query( "CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE )" ) .execute(pool) .await?; println!("Table users créée"); Ok(())}

async fn insert_user(pool: &PgPool, name: &str, email: &str) -> Result<User> { let user = sqlx::query_as::<_, User>( "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email" ) .bind(name) .bind(email) .fetch_one(pool) .await?; Ok(user)}

Notez $1, $2 — ce sont des requêtes paramétrées qui protègent contre les injections SQL.



2.3 Lecture et mise à jour des données

async fn get_user_by_email(pool: &PgPool, email: &str) -> Result<Option<User>> {    let user = sqlx::query_as::<_, User>("SELECT * FROM users WHERE email = $1")        .bind(email)        .fetch_optional(pool)        .await?;    Ok(user)}

async fn update_user_name(pool: &PgPool, id: i32, new_name: &str) -> Result<()> { sqlx::query("UPDATE users SET name = $1 WHERE id = $2") .bind(new_name) .bind(id) .execute(pool) .await?; println!("Utilisateur {} mis à jour", id); Ok(())}

L'utilisation de fetch_optional permet de gérer le cas où l'enregistrement n'est pas trouvé, sans panique.



3. Travailler avec MongoDB via le pilote officiel

3.1 Connexion et sélection de la base de données

Blogs

Book Recommendations