Introducción al trabajo con bases de datos en Rust
El lenguaje Rust está ganando rápidamente popularidad en la programación de sistemas, pero sus capacidades van mucho más allá de las tareas de bajo nivel. Gracias a su estricto sistema de tipos, seguridad de memoria y alto rendimiento, Rust se convierte en una excelente opción para crear aplicaciones de servidor robustas que trabajan con bases de datos. En este artículo, analizaremos en detalle cómo conectarse y realizar operaciones con dos SGBD populares: la relacional PostgreSQL y la orientada a documentos MongoDB.
Revisaremos las bibliotecas principales (crates), como diesel para PostgreSQL y el driver oficial mongodb, y también mostraremos ejemplos de operaciones CRUD en Rust puro. El artículo será útil tanto para principiantes como para desarrolladores experimentados que deseen ampliar su stack tecnológico.
1. Trabajo con PostgreSQL: el crate Diesel
Diesel es un ORM y constructor de consultas seguro y extensible para Rust. Proporciona verificación de tipos en tiempo de compilación, lo que elimina muchos errores de tiempo de ejecución relacionados con consultas SQL. Para comenzar, es necesario agregar las dependencias en el archivo Cargo.toml.
Instalación y configuración
Agregue los siguientes crates:
[dependencies]diesel = { version = "2.1", features = ["postgres"] }dotenvy = "0.15"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"tokio = { version = "1.0", features = ["full"] }También instale la utilidad de línea de comandos Diesel CLI:
cargo install diesel_cli --no-default-features --features postgresCree un archivo .env en la raíz del proyecto con la URL de su base de datos:
DATABASE_URL=postgres://username:password@localhost/my_databaseEjecute el comando para configurar las migraciones:
diesel setupdiesel migration generate create_usersDefinición del esquema y modelo
En el archivo de migración up.sql, escriba el SQL para crear la tabla:
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, email VARCHAR NOT NULL UNIQUE, age INTEGER NOT NULL);Luego ejecute diesel migration run. Después de esto, genere el esquema de Rust (archivo src/schema.rs) usando:
diesel print-schema > src/schema.rsAhora definamos el modelo y la estructura para la inserción de datos:
// src/models.rsuse diesel::prelude::*;use serde::{Deserialize, Serialize};use crate::schema::users;
#[derive(Queryable, Selectable, Serialize, Deserialize)]#[diesel(table_name = users)]pub struct User { pub id: i32, pub name: String, pub email: String, pub age: i32,}
#[derive(Insertable, Deserialize)]#[diesel(table_name = users)]pub struct NewUser { pub name: String, pub email: String, pub age: i32,}Operaciones CRUD con PostgreSQL
Revisemos las operaciones principales. Conexión a la BD y creación de un nuevo usuario:
use diesel::prelude::*;use dotenvy::dotenv;use std::env;
use crate::models::{NewUser, User};use crate::schema::users::dsl::*;
pub fn establish_connection() -> PgConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL") .expect("DATABASE_URL must be set"); PgConnection::establish(&database_url) .expect(&format!("Error connecting to {}", database_url))}
pub fn create_user(conn: &mut PgConnection, name: &str, email: &str, age: i32) -> User { let new_user = NewUser { name: name.to_string(), email: email.to_string(), age, };
diesel::insert_into(users) .values(&new_user) .returning(User::as_returning()) .get_result(conn)```