# 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ı. - Published: 2026-09-12 - Updated: 2026-09-12 - Author: Anthony Fillion-Maillet - Tags: rust, sqlx, database, postgresql, tutorial - Reading time: 12 min --- 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. ```rust use sqlx::postgres::PgPoolOptions; use sqlx::FromRow; #[derive(Debug, FromRow)] struct User { id: i32, email: String, created_at: chrono::DateTime, } async fn fetch_users(pool: &sqlx::PgPool) -> Result, 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. ```bash # .env DATABASE_URL=postgres://user:password@localhost/myapp_dev ``` Veritabanı 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. ```bash cargo install sqlx-cli cargo sqlx prepare ``` Bu komut, derlenmiş sorgu bilgilerini içeren `.sqlx` dizinini oluşturur. `DATABASE_URL` ayarlanmadığında SQLx bu önbelleğe alınmış metadata'yı kullanır. ```rust // 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 ```rust use sqlx::QueryBuilder; async fn search_users( pool: &PgPool, email_filter: Option<&str>, min_age: Option, limit: i64, ) -> Result, 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::() .fetch_all(pool) .await } ``` ### Geri Alma Yönetimi ile İşlemler ```rust 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 ```rust 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. ```bash # Yeni migrasyon oluştur sqlx migrate add create_users_table # Bekleyen migrasyonları çalıştır sqlx migrate run # Son migrasyonu geri al sqlx migrate revert ``` Migrasyon dosyaları sıralama için zaman damgası numaralandırması kullanır: ```sql -- 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: ```sql -- 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. ```rust use sqlx::postgres::{PgPoolOptions, PgConnectOptions}; use std::time::Duration; async fn create_production_pool() -> Result { 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. ```rust 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 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()), } } } ``` ## 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?** ```rust #[derive(FromRow)] struct UserProfile { id: i32, email: String, bio: Option, // 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` döndürür. `fetch_all`, çoklu sonuç sorguları için `Vec` 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?** ```rust async fn paginated_users( pool: &PgPool, page: i64, per_page: i64, ) -> Result<(Vec, 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. ```rust // 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. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/rust/rust-sqlx-compile-time-queries-tutorial