در اینجا راهنمای استفاده از پایگاه داده SQL در Rust به شما کمک می کند.
همانطور که برنامه های Rust بیشتری می سازید، ممکن است برای ذخیره و بازیابی داده ها نیاز به تعامل با پایگاه های داده داشته باشید.
تایپ قوی، ایمنی حافظه و عملکرد Rust، همراه با پشتیبانی آن از عملیات ناهمزمان، ORM ها و مهاجرت ها، پردازش داده های کارآمد و مقیاس پذیر را امکان پذیر می کند و Rust را به گزینه ای عالی برای ساخت برنامه های پایگاه داده تبدیل می کند.
مقدمه ای بر استفاده از پایگاه های داده SQL در Rust
جعبه های پایگاه داده و کتابخانه های زیادی در اکوسیستم Rust وجود دارد که از پارادایم های مختلف پایگاه داده پشتیبانی می کند.
برای پایگاههای داده SQL، میتوانید بین درایورهای پایگاه داده مانند Libpq، Mysql-connector و Sqlite3 یکی را انتخاب کنید که رابطی را برای برنامههای Rust فراهم میکند تا مستقیماً بدون هیچ لایه انتزاعی روی SQL و ORMها (نقشهنگارهای شیء-رابطهای) با پایگاههای داده تعامل داشته باشند. Sqlx و Rust-postgres که روشی مناسب برای کار با پایگاه داده بر روی انواع داده های Rust مانند ساختارها و توابع ارائه می دهند.
Diesel ORM یکی از محبوب ترین بسته های پایگاه داده در اکوسیستم Rust است. به عنوان یک ORM، دیزل ویژگی هایی از ساخت و اجرای پرس و جو تا تعریف مدل و انتقال طرح های پایگاه داده را فراهم می کند، که تعامل با پایگاه های داده و نوشتن کدهای کارآمد، تمیز و آسان را برای شما آسان تر می کند.
دیزل همچنین از چندین موتور پایگاه داده از جمله PostgreSQL، MySQL و SQLite پشتیبانی میکند و مجموعهای قوی از ویژگیها را برای مدیریت عملیات پیچیده پایگاه داده مانند تراکنشها، پیوستنها و توابع انبوه فراهم میکند.
دیزل با ابزارهای قدرتمند، ویژگیها و مستندات عالی، به گزینهای برای بسیاری از توسعهدهندگان Rust تبدیل شده است که به دنبال ساخت برنامههای مبتنی بر دادههای قوی و مقیاسپذیر هستند.
شروع کار با دیزل
شما باید جعبه های دیزل و dotenv را به وابستگی های پروژه خود در بخش وابستگی های فایل cargo.toml خود اضافه کنید.
[dependencies]
diesel = { version = "1.4.4", features = ["sqlite"] }
dotenv = "0.15.0"
پس از افزودن جعبه ها به عنوان وابستگی، باید ابزار diesel_cli CLI را برای تعامل با دیزل نصب کنید.
برای نصب ابزار diesel_cli این دستور را اجرا کنید:
cargo install diesel_cli
بعد از نصب ابزار می توانید با دستور diesel ابزار CLI را فراخوانی کنید.
بعد، یک فایل متغیرهای محیطی ایجاد کنید و URL پایگاه داده خود را مشخص کنید.
این دستور را برای ایجاد و درج URL پایگاه داده برای پایگاه داده SQLite در حافظه اجرا کنید.
echo DATABASE_URL=database.db > .env
برای کار با دیزل، باید sqlite3 یا پایگاه داده دلخواه خود را بر روی کامپیوتر خود نصب کنید.
در نهایت، دستور setup را برای Diesel اجرا کنید تا یک پایگاه داده برای پروژه خود راه اندازی کند:
diesel setup
دستور setup یک دایرکتوری migrations ایجاد می کند، پایگاه داده مشخص شده در DATABASE_URL را ایجاد می کند و مهاجرت های موجود را اجرا می کند.
راه اندازی مهاجرت با دیزل
پس از راه اندازی پایگاه داده خود با Diesel، از دستور migration generate برای تولید فایل های مهاجرت استفاده خواهید کرد. نام فایل را به عنوان آرگومان اضافه خواهید کرد:
diesel migration generate create_humans
این دستور دو فایل SQL را در دایرکتوری migrations ایجاد می کند: up.sql و down.sql.
شما SQL را برای تعاریف جدول پایگاه داده خود در فایل up.sql می نویسید:
-- Your SQL goes here
CREATE TABLE "human"
(
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"first_name" TEXT NOT NULL,
"last_name" TEXT NOT NULL,
"age" INTEGER NOT NULL
);
برای رها کردن جداول پایگاه داده در فایل down.sql کد SQL می نویسید:
-- down.sql
-- This file should undo anything in `up.sql`
DROP TABLE "human"
پس از نوشتن فایلهای SQL، دستور migration run را برای اعمال مهاجرتهای معلق اجرا کنید.
diesel migration run
علاوه بر این، می توانید از دستور migration redo برای برگرداندن مهاجرت ها استفاده کنید:
diesel migration redo
همچنین می توانید از دستور print-schema برای چاپ طرح استفاده کنید. دستور محتویات فایل schema.rs را چاپ می کند.
diesel print-schema
خروجی دستور print_schema کد Rust است که با طرح SQL شما مطابقت دارد:
اتصال به پایگاه داده SQL با دیزل
ابتدا این واردات و دستورات را به فایل خود اضافه کنید:
mod schema;
#[macro_use]
extern crate diesel;
use dotenv::dotenv;
use diesel::prelude::*;
use std::env;
use Diesel::{Connection, ExpressionMethods, QueryDsl, RunQueryDsl, SqliteConnection};
use crate::schema::human;
شما از واردات و دستورالعمل ها برای اتصال به پایگاه داده خود و انجام عملیات استفاده خواهید کرد.
در اینجا نحوه اتصال به پایگاه داده SQLite با یک تابع و بازگرداندن نمونه اتصال آورده شده است:
use std::env;
use diesel::{Connection, SqliteConnection};
fn establish_connection() -> SqliteConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
SqliteConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}
تابع install_connection ساختار نمونه اتصال (SqliteConnection) را برمی گرداند. install_connection متغیرهای محیطی را با تابع ok بارگیری می کند، با تابع var به URL پایگاه داده دسترسی پیدا می کند و از طریق URL با تابع install با پایگاه داده ارتباط برقرار می کند.
پس از اتصال موفقیت آمیز، می توانید کوئری ها را اجرا کرده و در پایگاه داده خود وارد کنید.
درج مقادیر به یک پایگاه داده با دیزل
شما از ساختاری استفاده خواهید کرد که با طرحواره SQL شما مطابقت دارد تا مقادیر را در پایگاه داده خود درج کنید.
در اینجا ساختاری وجود دارد که با طرح جدول انسانی مطابقت دارد:
#[derive(Queryable)]
pub struct Human {
pub id: i32,
pub first_name: String,
pub last_name: String,
pub age: i32,
}
تابع درج نمونه ای از نوع Human را برای سایر عملیات برمی گرداند.
شما به یک ساختار برای تابع درج نیاز دارید. ساختار دو ویژگی ماکرو را پیاده سازی می کند، یکی برای عملکرد درج و دیگری که جدول را برای عملیات مشخص می کند.
در اینجا ساختار عملیات درج است:
#[derive(Insertable)]
#[table_name = "human"]
struct NewHuman<'a> {
first_name: &'a str,
last_name: &'a str,
age: i32,
}
تابع درج شما یک نمونه اتصال و داده هایی را که می خواهید در پایگاه داده وارد کنید، می گیرد. داده ها را وارد کنید و یک پیام را بر اساس وضعیت عملیات چاپ کنید.
fn insert_into<'a>(conn: &SqliteConnection, first_name: &'a str, last_name: &'a str, age: i32) -> Human {
use crate::schema::human;
let new_human = NewHuman {
first_name,
last_name,
age,
};
diesel::insert_into(human::table).values(&new_human).execute(conn).expect("Error inserting new human");
human::table.order(human::id.desc()).first(conn).unwrap()
}
تابع insert_into پارامترها را می گیرد و مقادیر را با تابع insert_into Diesel که در جدول می گیرد و تابع مقادیر که در یک نمونه ساختاری می گیرد، در پایگاه داده وارد می کند. این تابع قبل از اجرای عملیات، شناسه را به ترتیب نزولی با تابع desc اختصاص می دهد.
در اینجا تابع اصلی است که تابع insert_into را فراخوانی می کند:
fn main() {
let conn = establish_connection();
let new_human = insert_into(&conn, "John", "Doe", 25);
println!("New human inserted with ID: {}", new_human.id);
}
متغیر conn یک نمونه اتصال است و متغیر new_human فراخوانی تابع است. تابع اصلی پس از یک عملیات موفقیت آمیز، شناسه را چاپ می کند.
پرس و جو از پایگاه های داده با دیزل
همچنین، ساختار تابع query شما ویژگی Queryable را با یک ماکرو مشتق اجرا میکند.
در اینجا ساختار عملیات query آمده است:
// Define a struct that represents a row in your table
#[derive(Queryable)]
struct Human {
id: i32,
first_name: String,
last_name: String,
age: i32,
}
تابع query در یک نمونه اتصال می گیرد و یک ساختار انسانی را به صورت زیر برمی گرداند:
fn query_db(conn: &SqliteConnection) -> Human {
human.filter(age.eq(25)).first(conn).expect("Error querying database")
}
تابع query_db جدول انسان را برای ردیفی که سن آن برابر با 25 است فیلتر می کند و اولین رخداد را به عنوان نمونه ساختار برمی گرداند.
fn main() {
let conn = establish_connection();
let person = query_db(&conn);
println!("ID: {}", person.id);
println!("First Name: {}", person.first_name);
println!("Last Name: {}", person.last_name);
println!("Age: {}", person.age);
}
در تابع main، متغیر person تابع query_db را فراخوانی می کند و فیلدهای ردیف را با مقدار سنی برابر با 25 چاپ می کند.
با Rust می توانید وب سرور بسازید
Rust همچنان به محبوبیت در توسعه وب به عنوان یک زبان سمت سرور با کتابخانه هایی مانند Actix-web و Rocket ادامه می دهد که راه اندازی سرورها و ساخت API و وب سایت ها را با انتزاع کردن عملکردهای پیچیده آسان تر می کند.
اکثر وب سرورها برای ذخیره و بازیابی داده ها باید با پایگاه های داده تعامل داشته باشند. میتوانید برنامههای دیزلی خود را با Actix-web یا Rocket ادغام کنید تا برنامههای وب پیچیده بسازید.