parsql 0.5.0

Deneyimsel bir sql yardımcı küfesidir. UYARI: bu bir ORM aracı değildir. Amaç sql yazımı ve kullanımında basit cümlecikler için kolaylık sağlamaktır.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# parsql

[![Version](https://img.shields.io/crates/v/parsql.svg)](https://crates.io/crates/parsql)
[![Documentation](https://docs.rs/parsql/badge.svg)](https://docs.rs/parsql)
[![License](https://img.shields.io/crates/l/parsql.svg)](https://github.com/yazdostum-nettr/parsql/blob/master/LICENSE)

Deneyimsel bir sql yardımcı küfesidir. Bu bir ORM aracı değildir. Amaç sql yazımı ve kullanımında basit cümlecikler için kolaylık sağlamaktır.

## Özellikler

- Otomatik SQL sorgu oluşturma
- Güvenli parametre yönetimi
- Birden fazla veritabanı sistemi için destek (PostgreSQL, SQLite, Tokio PostgreSQL, Deadpool PostgreSQL)
- Tip güvenliği olan veritabanı işlemleri
- SQL Injection saldırılarına karşı otomatik koruma
- **Yeni (0.3.3):** Sayfalama (pagination) için tam destek: `limit` ve `offset` öznitelikleri ile verimli sayfalama yapabilirsiniz
- `Queryable` türetme özniteliği, tablo adı, where ifadesi, select ifadesi, group by, having, order by, limit ve offset ifadeleri için destek sağlar.
- `Insertable` türetme özniteliği, tabloya özgü INSERT ifadeleri oluşturur.
- `Updateable` türetme özniteliği, tabloya özgü UPDATE ifadeleri oluşturur.
- `Deletable` türetme özniteliği, tabloya özgü DELETE ifadeleri oluşturur.
- `SqlParams` türetme özniteliği, yapının SQL parametreleri için kullanılmasını sağlar.
- `UpdateParams` türetme özniteliği, yapının UPDATE ifadeleri için kullanılmasını sağlar.
- `FromRow` türetme özniteliği, veritabanı satırlarının yapıya dönüştürülmesini sağlar.
- **Yeni (0.3.3):** SQL trace kayıtları için `PARSQL_TRACE` çevre değişkeni desteği eklendi.

## Ne İşe Yarar?

Parsql, SQL sorgularınızı doğrudan Rust struct'ları üzerinden yönetmenize olanak tanıyan bir kütüphanedir. Temel amacı, veritabanı işlemlerini daha güvenli ve daha az kod ile gerçekleştirmenizi sağlamaktır. Bu kütüphane ile:

- Struct tanımları üzerinden otomatik SQL sorguları oluşturabilirsiniz
- Veritabanı parametrelerini güvenli bir şekilde yönetebilirsiniz
- Generic CRUD işlemlerini (ekleme, okuma, güncelleme, silme) kolayca yapabilirsiniz
- Dinamik SQL oluşturabilir ve karmaşık sorgular çalıştırabilirsiniz
- Asenkron veritabanı işlemlerini kolayca gerçekleştirebilirsiniz
- SQL injection saldırılarına karşı otomatik koruma sağlayabilirsiniz
- Doğrudan `Pool` ve `Transaction` nesneleri üzerinde extension method'lar kullanabilirsiniz

Parsql standart bir ORM değildir. Daha çok, SQL yazımını ve kullanımını basitleştirmeye odaklanır.

## Desteklenen Veritabanları

Parsql aşağıdaki veritabanı sistemlerini desteklemektedir:

- **SQLite** (senkron): `parsql-sqlite` paketi
- **PostgreSQL** (senkron): `parsql-postgres` paketi
- **Tokio PostgreSQL** (asenkron): `parsql-tokio-postgres` paketi
- **Deadpool PostgreSQL** (asenkron bağlantı havuzu): `parsql-deadpool-postgres` paketi

## Kurulum

Cargo.toml içinde aşağıdaki şekilde tanımlama yapın:

```toml
[dependencies]
parsql = { version = "0.5.0", features = ["sqlite"] }
```

veya PostgreSQL için:

```toml
[dependencies]
parsql = { version = "0.5.0", features = ["postgres"] }
```

veya Tokio PostgreSQL için:

```toml
[dependencies]
parsql = { version = "0.5.0", features = ["tokio-postgres"] }
```

veya Deadpool PostgreSQL için:

```toml
[dependencies]
parsql = { version = "0.5.0", features = ["deadpool-postgres"] }
```

## Temel Özellikler

### Prelude Modülü (v0.5.0+)

Parsql artık tüm yaygın kullanılan trait'ler, makrolar ve tipleri içeren bir `prelude` modülü sunmaktadır:

```rust
use parsql::prelude::*;
```

Bu import ile şunlara erişebilirsiniz:
- Tüm derive makroları (`Queryable`, `Insertable`, `Updateable`, `Deletable`, `FromRow`, `SqlParams`, `UpdateParams`)
- Tüm trait'ler (`CrudOps`, `FromRow`, `SqlParams`, `SqlQuery`, `SqlCommand`, `UpdateParams`)
- Veritabanına özel tipler (`Row`, `ToSql`, `Connection`, `Error`, vb.)
- Extension trait'leri (`SqliteConnectionExt`, `PostgresConnectionExt`, vb.)

### Procedural Makrolar
Parsql, veritabanı işlemlerini kolaylaştırmak için çeşitli procedural makrolar sunar:

- `#[derive(Queryable)]` - Okuma (select) işlemleri için
- `#[derive(Insertable)]` - Ekleme işlemleri için
- `#[derive(Updateable)]` - Güncelleme işlemleri için
- `#[derive(Deletable)]` - Silme işlemleri için
- `#[derive(FromRow)]` - Veritabanı sonuçlarını nesnelere dönüştürmek için
- `#[derive(SqlParams)]` - SQL parametrelerini yapılandırmak için
- `#[derive(UpdateParams)]` - Güncelleme parametrelerini yapılandırmak için

### Extension Metodu Kullanımı

Parsql, 0.3.3 sürümünden itibaren, CRUD işlemlerini doğrudan veritabanı nesneleri üzerinden yapmanızı sağlayan extension metotları sunmaktadır. Bu yaklaşım sayesinde kodunuz daha akıcı ve okunabilir hale gelir.

#### Pool Nesnesi Üzerinde Extension Metodları

Bağlantı havuzu (Pool) nesneleri üzerinde doğrudan CRUD işlemleri yapabilirsiniz:

```rust
// Geleneksel kullanım
let rows_affected = insert(&pool, user).await?;

// Extension metodu ile kullanım (prelude ile otomatik gelir)
let rows_affected = pool.insert(user).await?;
```

#### Transaction Nesnesi Üzerinde Extension Metodları

Transaction nesneleri üzerinde doğrudan CRUD işlemleri yapabilirsiniz:

```rust
// Geleneksel kullanım
let (tx, rows_affected) = tx_insert(tx, user).await?;

// Extension metodu ile kullanım (prelude ile otomatik gelir)
let rows_affected = tx.insert(user).await?;
```

#### Desteklenen Extension Metodları

Hem Pool hem de Transaction nesneleri için şu extension metodları kullanılabilir:

- `insert(entity)` - Kayıt ekler
- `update(entity)` - Kayıt günceller
- `delete(entity)` - Kayıt siler
- `fetch(params)` - Tek bir kayıt getirir
- `fetch_all(params)` - Birden fazla kayıt getirir
- `select(entity, to_model)` - Özel dönüştürücü fonksiyon ile tek kayıt getirir
- `select_all(entity, to_model)` - Özel dönüştürücü fonksiyon ile çoklu kayıt getirir

### Transaction Desteği

Parsql şu anda aşağıdaki paketlerde transaction desteği sunmaktadır:

- `parsql-postgres` - Senkron PostgreSQL işlemleri için transaction desteği
- `parsql-tokio-postgres` - Asenkron Tokio-PostgreSQL işlemleri için transaction desteği
- `parsql-deadpool-postgres` - Asenkron Deadpool PostgreSQL bağlantı havuzu için transaction desteği

Örnek bir transaction kullanımı:

```rust
// Transaction başlatma
let client = pool.get().await?;
let tx = client.transaction().await?;

// Extension method kullanarak transaction içinde işlem yapma
let result = tx.insert(user).await?;
let rows_affected = tx.update(user_update).await?;

// İşlem başarılı olursa commit
tx.commit().await?;
```

### Güvenlik Özellikleri

#### SQL Injection Koruması
Parsql, SQL injection saldırılarına karşı güvenli bir şekilde tasarlanmıştır:

- Parametreli sorgular otomatik olarak kullanılır, asla direk string birleştirme yapılmaz
- Tüm kullanıcı girdileri güvenli bir şekilde parametrize edilir
- Makrolar, SQL parametrelerini doğru bir şekilde işler ve güvenli bir format sağlar
- Her veritabanı adaptörü için uygun parametre işaretleyiciler (`$1`, `?`, vb.) otomatik olarak uygulanır
- SQL yazarken elle string birleştirme gereksinimi ortadan kaldırılmıştır
- Asenkron bağlamlarda bile güvenlik önlemleri tam olarak korunur

```rust
// Güvenli parametre kullanımı örneği
#[derive(Queryable, FromRow, SqlParams)]
#[table("users")]
#[where_clause("username = $ AND status = $")]
struct UserQuery {
    username: String,
    status: i32,
}

// Parametreler güvenli bir şekilde yerleştirilir, 
// SQL injection riski olmaz
let query = UserQuery {
    username: user_input,
    status: 1,
};
```

### Öznitelikler
Sorgularınızı özelleştirmek için çeşitli öznitelikler kullanabilirsiniz:

- `#[table("tablo_adi")]` - Tablo adını belirtmek için
- `#[where_clause("id = $")]` - WHERE koşulunu belirtmek için
- `#[select("alan1, alan2")]` - SELECT ifadesini özelleştirmek için
- `#[update("alan1, alan2")]` - UPDATE ifadesini özelleştirmek için
- `#[join("LEFT JOIN tablo2 ON tablo1.id = tablo2.fk_id")]` - JOIN ifadeleri için
- `#[group_by("alan1")]` - GROUP BY ifadesi için
- `#[order_by("alan1 DESC")]` - ORDER BY ifadesi için
- `#[having("COUNT(*) > 5")]` - HAVING ifadesi için
- `#[limit(10)]` - LIMIT ifadesi için
- `#[offset(5)]` - OFFSET ifadesi için
- `#[returning("id")]` - INSERT/UPDATE işlemlerinden dönen değerleri belirtmek için

### SQL İzleme
Geliştirme sırasında oluşturulan SQL sorgularını izlemek için:

```sh
PARSQL_TRACE=1 cargo run
```

Bu, çalıştırılan tüm SQL sorgularını konsola yazdıracaktır.

## Basit Kullanım Örnekleri

### SQLite ile Kullanım

```rust
use parsql::prelude::*;

// Bir kayıt almak için
#[derive(Queryable, FromRow, SqlParams, Debug)]
#[table("users")]
#[where_clause("id = $")]
pub struct GetUser {
    pub id: i64,
    pub name: String,
    pub email: String,
}

impl GetUser {
    pub fn new(id: i64) -> Self {
        Self {
            id,
            name: Default::default(),
            email: Default::default(),
        }
    }
}

// Yeni kayıt eklemek için
#[derive(Insertable, SqlParams)]
#[table("users")]
pub struct InsertUser {
    pub name: String,
    pub email: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let conn = Connection::open("test.db")?;
    
    let insert_user = InsertUser {
        name: "Ali".to_string(),
        email: "ali@example.com".to_string(),
    };
    
    let id = insert(&conn, insert_user)?;
    println!("Eklenen kayıt ID: {}", id);
    
    let get_user = GetUser::new(id);
    let user = fetch(&conn, get_user)?;
    println!("Kullanıcı: {:?}", user);
    
    Ok(())
}
```

### Deadpool PostgreSQL ile Asenkron Bağlantı Havuzu Kullanımı

```rust
use parsql::prelude::*;
use deadpool_postgres::{Config, Runtime};

#[derive(Queryable, FromRow, SqlParams, Debug)]
#[table("users")]
#[where_clause("id = $")]
pub struct GetUser {
    pub id: i64,
    pub name: String,
    pub email: String,
}

#[derive(Insertable, SqlParams)]
#[table("users")]
pub struct InsertUser {
    pub name: String,
    pub email: String,
}

#[derive(Updateable, SqlParams)]
#[table("users")]
#[update("name, email")]
#[where_clause("id = $")]
pub struct UpdateUser {
    pub id: i64,
    pub name: String,
    pub email: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Bağlantı havuzu oluşturma
    let mut cfg = Config::new();
    cfg.host = Some("localhost".to_string());
    cfg.user = Some("postgres".to_string());
    cfg.password = Some("postgres".to_string());
    cfg.dbname = Some("test".to_string());
    
    let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls)?;
    
    // Extension method kullanarak kayıt ekleme
    let insert_user = InsertUser {
        name: "Ali".to_string(),
        email: "ali@example.com".to_string(),
    };
    let rows_affected = pool.insert(insert_user).await?;
    println!("Eklenen kayıt sayısı: {}", rows_affected);
    
    // Transaction kullanımı
    let client = pool.get().await?;
    let tx = client.transaction().await?;
    
    // Transaction içinde extension method kullanarak güncelleme
    let update_user = UpdateUser {
        id: 1,
        name: "Ali Güncellendi".to_string(),
        email: "ali.updated@example.com".to_string(),
    };
    let rows_affected = tx.update(update_user).await?;
    
    // Başarılı olursa commit
    tx.commit().await?;
    
    Ok(())
}
```

## Performans İpuçları

- Aynı SQL yapısına sahip sorguları tekrar kullanarak sorgu planı ön belleğinden yararlanın
- Yoğun veritabanı uygulamaları için bağlantı havuzları kullanın
- Büyük veri kümeleri için `get_all` yerine sayfalama (limit ve offset) kullanın
- Filtreleri veritabanı seviyesinde uygulayın, uygulamanızda değil

## Veritabanı Migrasyonları

Parsql, basit ve tip güvenli bir migrasyon sistemi içerir:

```rust
use parsql::prelude::*;

// Migration tanımlama
pub struct CreateUsersTable;

impl Migration for CreateUsersTable {
    fn version(&self) -> i64 { 20240101120000 }
    fn name(&self) -> &str { "create_users_table" }
    
    fn up(&self, conn: &mut dyn MigrationConnection) -> Result<()> {
        conn.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR(255))")
    }
    
    fn down(&self, conn: &mut dyn MigrationConnection) -> Result<()> {
        conn.execute("DROP TABLE users")
    }
}

// Migration çalıştırma
let mut runner = MigrationRunner::new();
runner.add_migration(Box::new(CreateUsersTable));
runner.run(&mut conn)?;
```

### CLI Aracı

Parsql CLI ile migration yönetimi kolaylaşır:

```bash
# Kurulum
cargo install parsql-cli

# Proje başlatma
parsql init

# Migration oluşturma
parsql migrate create "create users table"

# Migration çalıştırma
parsql migrate run

# Durum kontrolü
parsql migrate status --detailed

# Geri alma
parsql migrate rollback --to 20240101000000
```

## Detaylı Dökümantasyon

Her veritabanı adaptörü için daha detaylı bilgi ve örnekler, ilgili alt paketlerin README dosyalarında bulunmaktadır:

- [SQLite Dökümantasyonu]./parsql-sqlite/README.md
- [PostgreSQL Dökümantasyonu]./parsql-postgres/README.md
- [Tokio PostgreSQL Dökümantasyonu]./parsql-tokio-postgres/README.md
- [Deadpool PostgreSQL Dökümantasyonu]./parsql-deadpool-postgres/README.md
- [Migration Sistemi]./parsql-migrations/README.md
- [CLI Aracı]./parsql-cli/README.md

## Lisans

Bu proje MIT lisansı altında lisanslanmıştır.