SQLx pour Rust : guide complet avec exemples

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

Qu'est-ce que SQLx et pourquoi l'utiliser ?

SQLx est une bibliothèque Rust asynchrone et pure pour interagir avec les bases de données, qui adopte une approche "SQL sans ORM". Contrairement à des solutions ORM comme Diesel ou SeaORM, SQLx ne masque pas les requêtes SQL derrière des abstractions, mais vous permet d'écrire du code SQL pur, tout en garantissant une sécurité de typage totale à la compilation.

Les principaux avantages de SQLx :

  • Sécurité de typage à la compilation — SQLx vérifie la conformité de vos requêtes SQL avec le schéma de la base de données directement lors de la compilation du projet.
  • Asynchrone par défaut — la bibliothèque prend entièrement en charge async/await, ce qui est idéal pour les applications web à forte charge.
  • Support de plusieurs SGBD — PostgreSQL, MySQL, SQLite et MSSQL.
  • Aucune magie — vous écrivez du SQL standard, la bibliothèque se contente de vous aider à passer les paramètres et à récupérer les résultats en toute sécurité.
  • Migrations — système de gestion de migrations de schéma de base de données intégré.

SQLx est parfait pour les projets où le contrôle total des requêtes, les performances et la sécurité de typage sont essentiels, sans avoir à apprendre des DSL (langages dédiés) complexes d'ORM.

Installation

SQLx s'installe via le gestionnaire de paquets Cargo. Ajoutez la dépendance dans le fichier Cargo.toml :

[dependencies]
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"

En fonction de la base de données utilisée, choisissez le feature-flag correspondant :

  • postgres — pour PostgreSQL
  • mysql — pour MySQL
  • sqlite — pour SQLite
  • mssql — pour Microsoft SQL Server

Pour le runtime, vous pouvez choisir runtime-tokio-rustls (recommandé) ou runtime-async-std-rustls.

Démarrage rapide

Créons une application simple qui se connecte à PostgreSQL et exécute une requête :

use sqlx::postgres::PgPoolOptions;
use anyhow::Result;

#[tokio::main]
async fn main() -> Result<()> {
    // Création d'un pool de connexions
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect("postgres://utilisateur:motdepasse@localhost/mabd")
        .await?;

    // Exécution d'une requête simple
    let ligne: (i64,) = sqlx::query_as("SELECT $1::bigint")
        .bind(42_i64)
        .fetch_one(&pool)
        .await?;

    println!("Résultat : {}", ligne.0);

    Ok(())
}

Ce code crée un pool de 5 connexions à la base de données, exécute une requête avec un paramètre et affiche le résultat.

Méthodes et fonctions principales de SQLx

1. sqlx::query

Fonction : Crée une nouvelle requête SQL avec possibilité de lier des paramètres. C'est la brique de base pour toutes les opérations.

Paramètres :

  • sql: &str — chaîne de la requête SQL avec des placeholders ($1, $2 pour PostgreSQL ; ? pour MySQL/SQLite)

Exemple :

use sqlx::query;

let requete = sqlx::query("SELECT * FROM utilisateurs WHERE id = $1 AND actif = $2")
    .bind(1)
    .bind(true);

2. .bind()

Fonction : Lie une valeur à un paramètre de la requête. L'ordre des appels correspond à l'ordre des placeholders dans le SQL.

Paramètres :

  • valeur: impl Encode + Type<DB> — toute valeur pouvant être encodée pour la base de données (i32, String, bool, Option, etc.)

Exemple :

let id_utilisateur: i32 = 42;
let nom_utilisateur: &str = "Alice";

sqlx::query("INSERT INTO utilisateurs (id, nom) VALUES ($1, $2)")
    .bind(id_utilisateur)
    .bind(nom_utilisateur)
    .execute(&pool)
    .await?;

3. .fetch_one()

Fonction : Exécute la requête et récupère exactement une ligne de résultat. Si la requête ne retourne aucune ligne ou plus d'une ligne, une erreur est renvoyée.

Paramètres :

  • executor: impl Executor<Database = DB> — une référence au pool de connexions ou à une connexion

Exemple :

let utilisateur: (i32, String) = sqlx::query_as(
    "SELECT id, nom FROM utilisateurs WHERE email = $1"
)
.bind("alice@exemple.com")
.fetch_one(&pool)
.await?;

Recommendations