2026'da Rust ve SQLx: Derleme Zamanı Kontrollü Sorgular ve Mülakat Soruları
Rust'ta SQLx kullanımı hakkında kapsamlı rehber - derleme zamanı sorgu doğrulaması, ORM karşılaştırmaları ve teknik mülakat soruları.

SQLx kütüphanesi, Rust geliştiricilerinin veritabanlarıyla etkileşim kurma biçimini kökten değiştirdi. Geleneksel ORM'lerin aksine SQLx benzersiz bir yaklaşım sunuyor: derleme zamanı kontrolü ile ham SQL sorguları. Bu kombinasyon, performans veya oluşturulan SQL üzerindeki kontrolden ödün vermeden tip güvenliği sağlıyor.
SQLx 0.8+ sürümü tokio veya async-std üzerinden tam asenkron destekle PostgreSQL, MySQL, MariaDB ve SQLite'ı destekler. Derleme zamanı sorgu kontrolü, SQL sözdizimi hatalarını ve tip uyumsuzluklarını uygulama çalıştırılmadan önce yakalar.
Neden Geleneksel ORM'ler Yerine SQLx
Rust ekosistemi çeşitli veritabanı erişim seçenekleri sunuyor: tam özellikli ORM olarak Diesel, ActiveRecord yaklaşımı için SeaORM ve tip kontrolü ile ham SQL için SQLx. Her araç farklı bir amaca hizmet ediyor.
Diesel, tip güvenli sorgu oluşturuculardan SQL üretiyor. Bu yaklaşım standart CRUD işlemleri için iyi çalışıyor ancak veritabanına özgü işlevler gerektiren karmaşık sorgularda zorlaşıyor. SQLx farklı bir felsefe benimsiyor - geliştiriciler gerçek SQL sorguları yazıyor ve derleyici bunları veritabanı şemasına karşı doğruluyor.
use sqlx::postgres::PgPoolOptions;
use sqlx::FromRow;
#[derive(Debug, FromRow)]
struct User {
id: i32,
email: String,
created_at: chrono::DateTime<chrono::Utc>,
}
async fn fetch_users(pool: &sqlx::PgPool) -> Result<Vec<User>, sqlx::Error> {
sqlx::query_as::<_, User>(
"SELECT id, email, created_at FROM users WHERE active = $1"
)
.bind(true)
.fetch_all(pool)
.await
}query_as makrosu, users tablosunda id, email ve created_at sütunlarının var olduğunu ve tiplerinin struct alanlarıyla eşleştiğini doğrular. Veritabanı şeması değişirse, derleme net hata mesajlarıyla başarısız olur.
Derleme Zamanı Kontrolünü Yapılandırma
Derleme zamanı sorgu kontrolü, derleme işlemi sırasında veritabanı bağlantısı gerektirir. SQLx bunu DATABASE_URL ortam değişkeni veya .env dosyaları aracılığıyla yönetir.
# .env
DATABASE_URL=postgres://user:password@localhost/myapp_devVeritabanı bağlantısının mevcut olmadığı CI ortamları için SQLx çevrimdışı mod sağlar. cargo sqlx prepare komutu, depoya commit edilen sorgu metadata'sı oluşturur.
cargo install sqlx-cli
cargo sqlx prepareBu komut, derlenmiş sorgu bilgilerini içeren .sqlx dizinini oluşturur. DATABASE_URL ayarlanmadığında SQLx bu önbelleğe alınmış metadata'yı kullanır.
// Veritabanı mevcut olsa bile çevrimdışı kontrolü zorla
#[sqlx::test]
async fn test_user_query(pool: PgPool) {
let users = sqlx::query_as!(
User,
r#"SELECT id, email, created_at FROM users LIMIT 10"#
)
.fetch_all(&pool)
.await
.unwrap();
assert!(users.len() <= 10);
}Gelişmiş Sorgu Kalıpları
Üretim uygulamaları basit CRUD işlemlerinden fazlasını gerektirir. SQLx dinamik sorgular, işlemler ve toplu işlemler dahil karmaşık senaryoları destekler.
Opsiyonel Filtrelerle Dinamik Sorgular
use sqlx::QueryBuilder;
async fn search_users(
pool: &PgPool,
email_filter: Option<&str>,
min_age: Option<i32>,
limit: i64,
) -> Result<Vec<User>, sqlx::Error> {
let mut builder = QueryBuilder::new(
"SELECT id, email, created_at FROM users WHERE 1=1"
);
if let Some(email) = email_filter {
builder.push(" AND email ILIKE ");
builder.push_bind(format!("%{}%", email));
}
if let Some(age) = min_age {
builder.push(" AND age >= ");
builder.push_bind(age);
}
builder.push(" LIMIT ");
builder.push_bind(limit);
builder
.build_query_as::<User>()
.fetch_all(pool)
.await
}Geri Alma Yönetimi ile İşlemler
async fn transfer_funds(
pool: &PgPool,
from_account: i32,
to_account: i32,
amount: rust_decimal::Decimal,
) -> Result<(), sqlx::Error> {
let mut tx = pool.begin().await?;
// Kaynak hesaptan düş
let result = sqlx::query!(
r#"UPDATE accounts SET balance = balance - $1
WHERE id = $2 AND balance >= $1"#,
amount,
from_account
)
.execute(&mut *tx)
.await?;
if result.rows_affected() == 0 {
return Err(sqlx::Error::RowNotFound);
}
// Hedef hesaba ekle
sqlx::query!(
"UPDATE accounts SET balance = balance + $1 WHERE id = $2",
amount,
to_account
)
.execute(&mut *tx)
.await?;
tx.commit().await?;
Ok(())
}Toplu Ekleme
async fn bulk_insert_users(
pool: &PgPool,
users: &[(String, String)],
) -> Result<(), sqlx::Error> {
let mut builder = QueryBuilder::new(
"INSERT INTO users (email, name) "
);
builder.push_values(users, |mut b, (email, name)| {
b.push_bind(email).push_bind(name);
});
builder.build().execute(pool).await?;
Ok(())
}Migrasyonlar ve Şema Yönetimi
SQLx CLI, derleme zamanı kontrolüyle sorunsuz entegre olan yerleşik migrasyon yönetimi sağlar.
# Yeni migrasyon oluştur
sqlx migrate add create_users_table
# Bekleyen migrasyonları çalıştır
sqlx migrate run
# Son migrasyonu geri al
sqlx migrate revertMigrasyon dosyaları sıralama için zaman damgası numaralandırması kullanır:
-- migrations/20260915120000_create_users_table.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);Karmaşık uygulamalar için migrasyonlar hem up hem de down dosyaları içerebilir:
-- migrations/20260915120000_create_users_table.up.sql
CREATE TABLE users (...);
-- migrations/20260915120000_create_users_table.down.sql
DROP TABLE users;Bağlantı Havuzu ve Üretim Yapılandırması
Üretim dağıtımları uygun bağlantı havuzu yapılandırması, zaman aşımı yönetimi ve izleme gerektirir.
use sqlx::postgres::{PgPoolOptions, PgConnectOptions};
use std::time::Duration;
async fn create_production_pool() -> Result<PgPool, sqlx::Error> {
let options = PgConnectOptions::new()
.host("db.example.com")
.database("production")
.username("app_user")
.password("secure_password")
.ssl_mode(sqlx::postgres::PgSslMode::Require);
PgPoolOptions::new()
.max_connections(20)
.min_connections(5)
.acquire_timeout(Duration::from_secs(5))
.idle_timeout(Duration::from_secs(600))
.max_lifetime(Duration::from_secs(1800))
.connect_with(options)
.await
}Bağlantı havuzu boyutu çeşitli faktörlere bağlıdır: CPU çekirdek sayısı, veritabanı iş yükü özellikleri ve kaynak limitleri. Tipik başlangıç noktası CPU çekirdeği başına 2-3 bağlantıdır ve metriklere göre ayarlanır.
Hata Yönetimi ve Dayanıklılık
Üretim veritabanı uygulamaları çeşitli hata senaryolarını zarif bir şekilde yönetmelidir.
use sqlx::Error as SqlxError;
#[derive(Debug, thiserror::Error)]
enum DatabaseError {
#[error("Record not found")]
NotFound,
#[error("Duplicate entry: {0}")]
Duplicate(String),
#[error("Connection failed: {0}")]
Connection(String),
#[error("Query error: {0}")]
Query(String),
}
impl From<SqlxError> for DatabaseError {
fn from(err: SqlxError) -> Self {
match err {
SqlxError::RowNotFound => DatabaseError::NotFound,
SqlxError::Database(db_err) => {
if let Some(code) = db_err.code() {
if code == "23505" {
return DatabaseError::Duplicate(
db_err.message().to_string()
);
}
}
DatabaseError::Query(db_err.message().to_string())
}
SqlxError::PoolTimedOut => DatabaseError::Connection(
"Connection pool timeout".to_string()
),
_ => DatabaseError::Query(err.to_string()),
}
}
}Rust mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
SQLx Mülakat Soruları
Teknik mülakatlar genellikle veritabanı etkileşimi anlayışını, tip güvenliğini ve SQLx'e özgü özellikleri araştırır.
Soru: SQLx, çalışma zamanını değiştiren prosedürel makrolar olmadan derleme zamanı sorgu doğrulamasını nasıl başarır?
SQLx, derleme sırasında veritabanına bağlanan prosedürel makrolar kullanır. query! makrosu SQL dizesini ayrıştırır, doğrulama için veritabanına gönderir ve sonuç tiplerini eşleyen Rust kodu üretir. Bu kod üretimi tamamen derleme zamanında gerçekleşir - çalışma zamanı yalnızca hazırlanmış ifadeleri yürütür.
Soru: Üretim uygulamaları için SQLx ve Diesel arasındaki ödünleşimler nelerdir?
Diesel daha ergonomik sorgu oluşturma ve tip sistemi aracılığıyla daha iyi sorgu kompozisyonu desteği sağlar. SQLx doğrudan SQL erişimi ve veritabanına özgü özellikler için daha iyi destek sunar. Diesel standart CRUD işlemleri için daha az şablon kod gerektirirken, SQLx karmaşık sorgular ve performans optimizasyonu için daha fazla kontrol sağlar.
Soru: SQLx'te nullable değerler uygun tip güvenliğiyle nasıl ele alınır?
#[derive(FromRow)]
struct UserProfile {
id: i32,
email: String,
bio: Option<String>, // Veritabanında nullable
}
// Sorgu otomatik olarak null'ları yönetir
let profile = sqlx::query_as!(
UserProfile,
"SELECT id, email, bio FROM user_profiles WHERE id = $1",
user_id
)
.fetch_one(pool)
.await?;Soru: SQLx'te fetch_one, fetch_optional ve fetch_all arasındaki farkı açıklayın.
fetch_one tam olarak bir satır bekler ve sorgu sıfır veya birden fazla satır döndürürse hata verir. fetch_optional, satırın var olmayabileceği durumları yöneterek Option<T> döndürür. fetch_all, çoklu sonuç sorguları için Vec<T> döndürür. Doğru fetch metodunu seçmek çalışma zamanı hatalarını önler ve tip sisteminde niyeti ifade eder.
Soru: SQLx ile sayfalama nasıl uygulanır?
async fn paginated_users(
pool: &PgPool,
page: i64,
per_page: i64,
) -> Result<(Vec<User>, i64), sqlx::Error> {
let offset = (page - 1) * per_page;
let users = sqlx::query_as!(
User,
r#"SELECT id, email, created_at
FROM users
ORDER BY created_at DESC
LIMIT $1 OFFSET $2"#,
per_page,
offset
)
.fetch_all(pool)
.await?;
let total: (i64,) = sqlx::query_as(
"SELECT COUNT(*) FROM users"
)
.fetch_one(pool)
.await?;
Ok((users, total.0))
}Performans Karşılaştırması ve Benchmark'lar
SQLx performansı ham veritabanı sürücüleriyle rekabet eder çünkü çalışma zamanında soyutlama yükü eklemez. Tip sistemi ve derleme zamanı kod üretimi, birçok ORM'de bulunan yansıma maliyetlerini ortadan kaldırır.
Yoğun okuma uygulamaları için bağlantı havuzları ve uygun hazırlanmış ifade kullanımı, kütüphane seçiminden daha fazla etki yapar. SQLx'in çevrimdışı modu, çalışma zamanı sorgu ayrıştırmasını tamamen atlamayı sağlar.
// Hazırlanmış ifade - bir kez ayrıştırılır, birçok kez yürütülür
let stmt = sqlx::query!("SELECT id, email FROM users WHERE active = $1");
for _ in 0..1000 {
let users = stmt.clone().bind(true).fetch_all(pool).await?;
}Sonuç
SQLx, Rust'ta veritabanı erişimine pragmatik bir yaklaşımı temsil eder. Derleme zamanı sorgu kontrolü, SQL kontrolünü kaybetmeden hataları erken yakalar. Asenkron destek, Rust async ekosistemiyle doğal olarak entegre olur ve CLI araç seti migrasyon yönetimini basitleştirir.
SQL ile rahat çalışan ve Rust'ın tip güvenliğini isteyen ekipler için SQLx her iki dünyanın en iyisini sağlar. Tip sistemi derleme sırasında doğruluğu garanti ederken, ham SQL veritabanı yeteneklerine tam erişimi korur.
Bu rehberde sunulan kalıpları anlamak, geliştiricileri hem pratik kullanım hem de veritabanı mimarisi ve Rust'a özgü seçimler hakkındaki teknik mülakat tartışmalarına hazırlar.
Rust kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
12 Eylül 2026 tarihinde güncellendi
Etiketler
Paylaş
İlgili makaleler

Rust Öğrenme 2026: Bootcamp Karşılaştırması ve Kendi Kendine Çalışma Kaynakları
Rust bootcamp'leri, çevrimiçi kurslar ve ücretsiz eğitim materyallerinin kapsamlı karşılaştırması. 2026'da Rust kariyeri planlayan geliştiriciler için rehber.

Rust'ta Hata Yönetimi 2026: Result, Option, thiserror ve anyhow
Result, Option, ? operatörü ve thiserror ile anyhow kütüphanelerini kullanarak Rust'ta hata yönetimi için kapsamlı rehber. Üretim uygulamalarında kullanılan en iyi pratikler ve kalıplar.

Rust Akıllı İşaretçiler: Box, Rc, Arc ve RefCell (2026)
Rust akıllı işaretçileri Box, Rc, Arc ve RefCell; derlenebilir 2026 örnekleri, bir karar tablosu ve yaygın mülakat sorularıyla açıklanıyor.