torm 0.4.0

A Tokio-based async ORM for Rust with GORM-like API, supporting SQLite, MySQL and PostgreSQL via native wire protocols
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
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
# TORM - Tokio ORM

TORM 是一个基于 Tokio 异步运行时的 Rust ORM(对象关系映射)库,提供类似 GORM 的功能,采用分层模块设计(数据库层 / ORM 层 / 工具层 / 监控层)。

## 🎯 核心特性

- **标准 SQLite 支持** - 基于 rusqlite,生成标准 SQLite 文件格式(可被 sqlite3 等工具直接读取)
-**纯 Rust 存储引擎** - 内置零依赖的内存存储引擎(StorageEngine)
-**PostgreSQL 支持** - 原生协议实现(cleartext / MD5 / SCRAM-SHA-256 认证、参数化查询)
-**MySQL 支持** - 原生协议实现(mysql_native_password / caching_sha2_password / sha256_password 认证、文本/二进制协议参数化查询)
-**异步/await 支持** - 完全基于 Tokio 异步运行时
-**多数据库支持** - MySQL、PostgreSQL、SQLite
-**流畅的查询构建器** - 提供简洁直观的查询 API
-**查询直接执行** - `insert` / `update` / `delete` 直接执行 SQL,通过 `return_sql()` 查看
-**高级查询** - JOIN、GROUP BY、HAVING、聚合函数
-**`SqlValue`** - `where_*` / `insert` / `update` 直接接受原生 Rust 值(`i32` / `f64` / `&str` / `bool` ...),通过 `Into<SqlValue>` 自动转换
-**Dapper 风格类型化映射** - `QueryExecutor::models::<M>()` 把查询结果自动映射回类型化 `Vec<M>`
-**模型 Trait** - 自动管理创建时间、更新时间等时间戳
-**`#[derive(Model)]`** - 从普通结构体自动生成 `Model` 实现,消除样板代码
-**GORM 风格模型 CRUD** - `Database` 上的 `create` / `first` / `last` / `all` / `update` / `delete`
-**自增主键** - `#[derive(Model)]` 自动标记整型主键自增,`id: 0` 自动分配并回填
-**事务支持** - 支持事务的创建、提交和回滚
-**连接池** - 支持 SQLite/MySQL/PostgreSQL 连接池
-**防 SQL 注入** - 标识符校验/引用、字符串转义、危险模式检测(`utils::sql_safety`-**日志与性能监控** - 内置日志系统和性能统计

## 📦 依赖

```toml
[dependencies]
tokio = "1.53"              # 异步运行时
rusqlite = { version = "0.30", features = ["bundled"] }  # SQLite(标准文件格式)
uuid = "1.0"                # UUID 生成
serde = "1.0"               # 序列化
serde_json = "1.0"          # JSON 支持
chrono = "0.4"              # 时间处理
async-trait = "0.1"         # 异步 trait
thiserror = "1.0"           # 错误派生
# PostgreSQL / MySQL 协议认证
sha2 = "0.10"               # PostgreSQL SCRAM-SHA-256 / MySQL caching_sha2_password
sha1 = "0.10"               # MySQL mysql_native_password 认证
md-5 = "0.10"               # PostgreSQL MD5 认证
hex = "0.4"                 # 字节/十六进制编码
base64 = "0.22"             # SCRAM base64 编码
# MySQL caching_sha2_password 全量认证的 RSA 加密(MySQL 8.0+)
rsa = "0.9"
num-bigint = "0.4"
rand = "0.8"
```

### 数据库层实现

| 功能 | 实现方式 | 状态 |
|------|----------|------|
| SQLite | rusqlite(标准文件格式) | ✅ 完整 |
| 内存存储引擎 | 纯 Rust StorageEngine | ✅ 完整 |
| MySQL | 自定义协议(原生实现) | ✅ 完整 |
| PostgreSQL | 自定义协议(原生实现) | ✅ 完整 |
| 类型安全 | SqlValue + 自动转换(`Into<SqlValue>`| ✅ 完整 |
| 类型化映射 | Dapper 风格:模型 CRUD 自动映射回类型化结构体 | ✅ 完整 |
| 自增主键 | `#[derive(Model)]` 自动标记整型主键自增 | ✅ 完整 |
| 事务支持 | 自定义实现 | ✅ 完整 |

## 🏗 模块结构

```
src/
├── lib.rs              # 模块声明与导出入口
├── db/                 # 数据库层
│   ├── db_types.rs     # SQL 类型系统 (SqlValue, Row, QueryResult)
│   ├── database.rs     # 连接抽象、事务、连接工厂、Database
│   ├── driver.rs       # DBDriver, Dsn
│   ├── error.rs        # TormError
│   ├── storage.rs      # 纯 Rust 内存存储引擎
│   ├── sqlite.rs       # SQLite 实现(rusqlite 后端)
│   ├── mysql.rs        # MySQL 协议实现
│   ├── postgresql.rs   # PostgreSQL 协议实现
│   └── pool.rs         # 连接池
├── orm/                # ORM 层
│   ├── model.rs        # Model trait
│   ├── query.rs        # Query/QueryBuilder
│   ├── advanced_query.rs # 高级查询 (JOIN/GROUP BY/聚合)
│   ├── relations.rs    # 关联关系
│   └── migration.rs    # 数据迁移
├── utils/              # 工具层(零依赖实现)
│   ├── simple_pool.rs  # 简单连接池
│   ├── simple_lru.rs   # LRU 缓存
│   ├── simple_error.rs # 简化错误
│   ├── simple_uuid.rs  # UUID/ID 生成
│   └── sql_safety.rs   # 防 SQL 注入(标识符、转义、检测)
└── monitoring/         # 监控层
    ├── logger.rs       # 日志系统
    └── performance.rs  # 性能监控
```

## 🚀 快速开始

### 基本使用

推荐的方式是**先定义 `#[derive(Model)]` 结构体,再用高层 ORM API**。所有 insert / query / update / delete 的值都是原生 Rust 类型,无需 `SqlValue`。

```rust
use torm::{Database, Model, Query};

// 定义模型;宏自动生成 schema、字段映射与 from_row。
#[derive(Debug, Clone, Model)]
#[model(table_name = "users")]
pub struct User {
    pub id: i64,        // 0 表示触发自增,create 后自动回填
    pub name: String,
    pub age: i32,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 创建 SQLite 数据库(标准 SQLite 文件格式)
    let db = Database::sqlite("mydb.db").await?;

    // 2. 依据模型 schema 自动建表
    db.auto_migrate::<User>().await?;

    // 3. 插入数据(id 自动分配并回填)
    let mut alice = User { id: 0, name: "Alice".into(), age: 25 };
    db.create(&mut alice).await?;

    // 4. 条件查询并自动映射回 Vec<User>
    let adults: Vec<User> = Query::new("users")
        .where_gte("age", 18)
        .query(&db)
        .models::<User>()
        .await?;
    for u in &adults {
        println!("{}: {}", u.name, u.age);
    }

    // 5. 更新(直接执行 SQL,返回影响行数)
    let affected = db.update(&mut alice, &[("age", 26)]).await?;

    db.close().await?;
    Ok(())
}
```

生成的 `mydb.db` 是标准 SQLite 文件,可用 `sqlite3 mydb.db` 直接查看:

```bash
$ sqlite3 mydb.db ".tables"
users
$ sqlite3 mydb.db "SELECT * FROM users;"
1|Alice|25
```

> 如果你偏好**低层 raw SQL**(例如任意查询),可使用 `db.execute(sql, &[SqlValue...])`——参见下文「类型安全的 SQL 值」章节。

### 类型安全的 SQL 值

```rust
let value: SqlValue = 42.into();                    // I32(42)
let value: SqlValue = "hello".into();               // String("hello")
let value: SqlValue = true.into();                  // Bool(true)
let value = SqlValue::DateTime(chrono::Utc::now()); // DateTime(...)

// SQL 字符串转换
let sql = value.to_sql_string();  // "42", "'hello'", "TRUE"
```

### 防 SQL 注入

`utils::sql_safety` 模块(在 crate 根目录重导出)提供了针对 SQL 注入的纵深防御。**参数化查询**(`?` / `$1` 占位符)是对**值**的第一道防线;但表名、列名等**标识符**仍会被直接拼接到 SQL 中。库已自动在 `Query` / `AdvancedQuery` / 模型 CRUD 中对标识符进行校验;对于自定义 SQL 拼接,可直接使用以下工具:

```rust
use torm::{
    SqlSanitizer, validate_identifier, quote_identifier,
    escape_string, contains_injection_pattern,
};

// 1. 拼接前先校验 / 引用标识符
assert_eq!(validate_identifier("user_name"), Ok("user_name".to_string()));
assert!(validate_identifier("name; DROP TABLE users").is_err());
assert_eq!(quote_identifier("select"), Some("`select`".to_string()));

// SqlSanitizer::identifier 返回可直接拼接的安全字符串
// (标识符不安全时回退为 "" 并打印告警)
let col = SqlSanitizer::identifier("user_name");
let query = format!("SELECT {} FROM users", col);   // 安全

// 2. 若必须内联值,对字符串字面量进行转义
let value = escape_string("O'Reilly");              // "O''Reilly"

// 3. 启发式审计原始 SQL 中的危险模式
// (自动跳过字符串字面量与注释,降低误报)
assert!(contains_injection_pattern("1 OR 1=1; DROP TABLE users").is_some());
assert!(contains_injection_pattern("SELECT * FROM users WHERE id = ?").is_none());
```

> **注意**`contains_injection_pattern` 是用于辅助审计的启发式工具,**不能替代**参数化查询。

### 查询构建器

`Query` 提供流畅的构建 API,既可以**直接对数据库执行**,也可以使用 `return_sql()` **查看生成的 SQL**。

```rust
use torm::{Database, Query};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::sqlite("mydb.db").await?;
    db.execute(
        "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)",
        &[],
    ).await?;

    // ---- 写操作直接执行(INSERT / UPDATE / DELETE)----
    // 条件值直接写原生 Rust 类型(i32 / f64 / &str / bool / String ...),
    // 无需再手动包装成 SqlValue::*。
    let q = Query::new("users").where_eq("name", "Alice");

    let affected = q.update(
        &{ let mut m = std::collections::HashMap::new();
           m.insert("age".to_string(), 31); m },
        &db,
    ).await?;                                // 直接执行 UPDATE,返回受影响行数

    // 查看最近一次操作的 SQL 与参数
    let (sql, params) = q.return_sql();
    // sql: "UPDATE users SET age = ? WHERE name = ?"

    // insert / delete 同样直接执行
    Query::new("users").insert(
        &[("name", "Bob"),
          ("age", 25)],
        &db,
    ).await?;
    Query::new("users").where_eq("age", 25).delete(&db).await?;

    // ---- 读操作:通过 query(db) 得到执行器,或通过 build() 得到 SqlStatement ----
    let result = Query::new("users").query(&db).select().await?;  // 直接执行 SELECT
    let total = Query::new("users").query(&db).count().await?     // 直接执行 SELECT COUNT(*)
        .rows.first().and_then(|r| r.get("COUNT(*)")).and_then(|v| v.as_i64()).unwrap_or(0);

    // build().query() 也可以,return_sql() 查看 SQL
    let result = Query::new("users").where_gt("age", 20).build()
        .query(&db).await?;                  // 直接执行 SELECT
    let (sql, _) = Query::new("users").count().return_sql();
    // sql: "SELECT COUNT(*) FROM users"

    Ok(())
}
```

所有 `where_*` / `update` / `insert` 的值都接受**原生 Rust 值**(`i32` / `i64` / `f32` / `f64` / `&str` / `String` / `bool` / `Vec<u8>` / `chrono::DateTime<Utc>` 以及无符号整型),通过 `Into<SqlValue>` 自动转换——完全无需手写 `SqlValue::Type(...)`。

`Query::query(db)` 返回一个 **`QueryExecutor`** 执行器,可链式选择读操作:

- `QueryExecutor::count()` - 执行 `SELECT COUNT(*)`,返回含 `COUNT(*)` 列的结果集
- `QueryExecutor::select()` - 执行 `SELECT *`
- `QueryExecutor::models::<M>()` - 执行 `SELECT *` 并把每一行通过 `Model` trait 自动映射回类型化的 `Vec<M>`(需 `#[derive(Model)]`
`Query` 的 `build()` / `count()` / `build_update()` 等也会返回一个 `SqlStatement`,它同时提供执行与查看两种能力:

- `SqlStatement::execute(&db)` / `SqlStatement::query(&db)` - 直接执行
- `SqlStatement::return_sql()` - 获取 `(sql, params)`- `Query::return_sql()` - 获取最近一次构建/执行的操作的 `(sql, params)`

> **注意**:SQLite 和 MySQL 使用 `?` 占位符,PostgreSQL 使用 `$1/$2/...`。执行时会自动转换。

### 使用派生宏定义模型

无需手写 `Model` 实现,只需给结构体加上 `#[derive(Model)]` 与 `#[model(table_name = "...")]` 属性。宏会自动生成 `columns()`、`from_row()`、主键访问器、时间戳访问器以及用于 `auto_migrate` 的 `schema()`——全程**零 `SqlValue`**。**整型主键会被自动标记为自增**(SQLite 生成 `AUTOINCREMENT`,MySQL 生成 `AUTO_INCREMENT`,PostgreSQL 生成 `SERIAL`),因此以 `id: 0` 插入模型时会自动分配主键并回写。

```rust
use torm::{Model, Timestamps};
use chrono::{DateTime, Utc};

#[derive(Debug, Clone, Model)]
#[model(table_name = "users")]
pub struct User {
    pub id: i64,                                        // 主键 -> id() / set_id()
    pub name: String,
    pub age: Option<i32>,
    #[model(column = "created_at")]
    pub created_at: Option<DateTime<Utc>>,              // 独立时间戳字段
    pub timestamps: Timestamps,                          // 或使用 Timestamps 结构体
    #[model(skip)]
    pub role_ids: Option<Vec<i64>>,                      // 非数据库字段,自动跳过
}
```

支持的字段类型:`String`、`bool`、`i8/i16/i32/i64`、`f32/f64`、`chrono::DateTime<Utc>`、`Uuid`、`Vec<u8>` 及其 `Option<...>` 包装。其他类型会自动跳过;使用 `#[model(skip)]` 显式排除某个字段,使用 `#[model(column = "...")]` 重命名数据库列名。

### Dapper 风格的类型化 CRUD

一旦派生出模型,**insert / query / update / delete 全程都不需要触碰 `SqlValue`**——值直接用原生 Rust 类型,结果返回类型化结构体(Dapper 风格的 `Query<T>`)。

```rust
use torm::{Database, Model, Query};

#[derive(Debug, Clone, Model)]
#[model(table_name = "users")]
pub struct User {
    pub id: i64,        // 0 表示触发自增,create 后自动回填
    pub name: String,
    pub email: String,
    pub age: i32,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::sqlite("app.db").await?;
    db.auto_migrate::<User>().await?;

    // 1. 插入:id = 0 触发自增,随后自动回填。
    let mut alice = User { id: 0, name: "Alice".into(), email: "a@e.com".into(), age: 25 };
    db.create(&mut alice).await?;
    println!("id = {}", alice.id); // 1

    // 2. 查询:把每一行自动映射回 Vec<User>。
    let adults: Vec<User> = Query::new("users")
        .where_gte("age", 18)
        .order_by_desc("age")
        .query(&db)
        .models::<User>()
        .await?;

    // 3. 更新:直接执行 SQL,返回受影响行数。
    let affected = db.update(&mut alice, &[("age", 26)]).await?;

    // 4. 按主键 / 全表读取,仍是类型化结果。
    let one: Option<User> = db.first::<User>(&alice.id.to_string()).await?;
    let last: Option<User> = db.last::<User>().await?;
    let all: Vec<User> = db.all::<User>().await?;

    // 5. 按模型删除。
    let n = db.delete(&mut alice).await?;
    Ok(())
}
```

`Database::update(model, &[(column, value), ...])` 会**立即执行 UPDATE** 并返回受影响行数。各列值类型**相同**时直接用原生类型(`i32`/`&str` 等);各列**类型不同**时把值统一为 `SqlValue`(如 `&[("age", SqlValue::I32(30)), ("email", SqlValue::String("x".into()))]`)。

### 连接池

```rust
use torm::Pool;

let config = torm::ConnectionConfig::sqlite("mydb.db")
    .with_max_connections(10);
let pool = Pool::sqlite("mydb.db", torm::PoolConfig::default()).await?;
let conn = pool.get_connection().await?;
```

### MySQL 连接

```rust
use torm::{Database, SqlValue};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接 MySQL(原生协议,支持 mysql_native_password / caching_sha2_password)
    let db = Database::mysql("localhost", 3306, "mydb", "odoo", "odoo").await?;

    // 参数化查询(COM_STMT_PREPARE / COM_STMT_EXECUTE 二进制协议)
    db.execute(
        "INSERT INTO users (name, age) VALUES (?, ?)",
        &[SqlValue::String("Alice".to_string()), SqlValue::I32(30)],
    ).await?;

    let result = db.query("SELECT * FROM users WHERE age > ?", &[SqlValue::I32(18)]).await?;
    for row in &result.rows {
        println!("{:?}", row.get("name"));
    }

    db.close().await?;
    Ok(())
}
```

## 📊 数据库支持状态

### ✅ SQLite(生产级,标准文件格式)
- 基于 rusqlite,生成标准 SQLite 文件(sqlite3 兼容)
- 完整的 CRUD 操作
- 参数化查询
- 事务支持
- 外键约束
- **状态**: 可用于生产环境

### ✅ 纯 Rust 内存引擎(StorageEngine)
- 零依赖内存数据库
- 自定义二进制持久化格式(TORMDB01)
- 完整的 CRUD + WHERE 条件(AND/OR/比较运算/LIKE)
- **状态**: 可用作轻量级内存数据库

### ✅ MySQL(原生协议,生产可用)
- 通过 `tokio::net::TcpStream` 建立真实 TCP 连接
- 完整的初始握手(Protocol 10)与握手响应
- 认证:`mysql_native_password``caching_sha2_password`(快速/全量认证,含 RSA 加密)、`sha256_password`
- AuthSwitchRequest / AuthMoreData 认证切换流程
- 文本协议(`COM_QUERY`)执行无参数查询
- 二进制协议(`COM_STMT_PREPARE` / `COM_STMT_EXECUTE`)支持参数化查询
- 列定义、文本行/二进制行解码、OK/EOF/Error 包
- 支持 `CLIENT_DEPRECATE_EOF`(MySQL 5.7+)与经典 EOF 协议
- 事务(BEGIN / COMMIT / ROLLBACK)
- **状态**: 可用于 MySQL 5.7+ 生产环境

### ✅ PostgreSQL(原生协议,生产可用)
- 通过 `tokio::net::TcpStream` 建立真实 TCP 连接
- 完整启动握手(StartupMessage,协议 3.0)
- 认证:cleartext、MD5、SCRAM-SHA-256(含服务端签名校验)
- 简单查询协议(`Q`),支持多语句 SQL
- 扩展查询协议(Parse/Bind/Describe/Execute/Sync),支持参数化语句
- 行解码:bool、int2/4/8、float4/8、text/varchar、bytea、json/jsonb、date/timestamp/timestamptz、numeric
- 事务(BEGIN / COMMIT / ROLLBACK)
- **状态**: 可用于 PostgreSQL 10+ 生产环境

## 🏃 运行示例

所有示例都遵循同一模式:**先定义 `#[derive(Model)]` 结构体,再用高层 ORM API 操作**——insert / query / update / delete 全程不触碰 `SqlValue`。

```bash
# Dapper 风格类型化 CRUD(定义结构体后 create / first / last / all / update / delete)
cargo run --example dapper_style

# 异步并发:结构体 + auto_migrate,并发查询自动映射回 Vec<Product>
cargo run --example async_concurrency

# 优雅的 Query 构建器:直接写原生 Rust 值,无需 SqlValue::Type(...)
cargo run --example ergonomic_query

# 完整集成:连接、自动建表、类型化 CRUD、计数
cargo run --example integration_example

# 基础使用(UUID / 错误处理 / 缓存 / 连接池)+ 类型化模型
cargo run --example basic_usage

# 完整功能演示 + 基于派生模型的文件持久化
cargo run --example complete_demo

# 高级功能(JOIN / GROUP BY / HAVING / 聚合)
cargo run --example advanced_features

# 运行测试
cargo test
```

PostgreSQL 示例(`postgresql_example.rs`)额外演示了**低层 raw SQL + `SqlValue`** 的参数化绑定,仅在绕过 ORM 手写 SQL 时才需要。

## 🔄 数据库迁移工具

TORM 内置 6 个独立的命令行工具(位于 `src/bin/`),基于 TORM 原生协议驱动,实现**数据库之间的表结构与数据迁移**。每个工具会自动发现源库的表、把表结构翻译为目标方言,并分批(每批一个事务)流式迁移数据。

| 工具 | 方向 |
|------|------|
| `mysql2postgresql` | MySQL → PostgreSQL |
| `postgresql2mysql` | PostgreSQL → MySQL |
| `sqlite2postgres` | SQLite → PostgreSQL |
| `postgres2sqlite` | PostgreSQL → SQLite |
| `mysql2sqlite` | MySQL → SQLite |
| `sqlite2mysql` | SQLite → MySQL|

### 构建

```bash
cargo build --release
```

### 用法

```bash
# MySQL → PostgreSQL
./target/release/mysql2postgresql \
  --mhost 127.0.0.1 --mport 3306 --mdb mydb --muser root --mpass pw \
  --phost 127.0.0.1 --pport 5432 --pdb mydb --puser postgres --ppass pw

# PostgreSQL → MySQL
./target/release/postgresql2mysql \
  --phost 127.0.0.1 --pport 5432 --pdb mydb --puser postgres --ppass pw \
  --mhost 127.0.0.1 --mport 3306 --mdb mydb --muser root --mpass pw

# SQLite → PostgreSQL(SQLite 文件为位置参数)
./target/release/sqlite2postgres /path/to/data.db \
  --phost 127.0.0.1 --pport 5432 --pdb mydb --puser postgres --ppass pw

# PostgreSQL → SQLite
./target/release/postgres2sqlite /path/to/output.db \
  --phost 127.0.0.1 --pport 5432 --pdb mydb --puser postgres --ppass pw
```

不带任何参数运行时,工具会打印帮助信息。

### 通用参数

| 参数 | 说明 |
|------|------|
| `--tables t1,t2` | 只迁移指定表(默认全部) |
| `--batch N` | 每批迁移行数(默认 `1000`|
| `--create-only` | 只建表不迁数据 |
| `--data-only` | 只迁数据跳过建表 |

### 行为说明

- **表结构翻译**:MySQL/PostgreSQL 类型映射为目标方言;自增列映射为 PostgreSQL 的 `SERIAL`/`BIGSERIAL`、MySQL 的 `AUTO_INCREMENT`、SQLite 的 `INTEGER PRIMARY KEY AUTOINCREMENT`。复合 `UNIQUE` 约束保留为表级约束。
- **稳定分批**:读取按主键 `ORDER BY`,保证 `LIMIT/OFFSET` 分页不重复、不遗漏。
- **JSON 与大文本**`json`/`jsonb`/`text`/`varchar` 映射为 MySQL 的 `LONGTEXT`(PostgreSQL / SQLite 为 `TEXT`)以避免截断;作为 key 的列按需降级为 `VARCHAR(255)`- **大小写敏感**:MySQL 目标表使用 `utf8mb4_bin` 排序规则,使 `UNIQUE`/主键语义与 PostgreSQL 一致(区分大小写),避免误判仅大小写不同的值为重复。
- **默认值**:PostgreSQL 的函数式默认值(如 `timezone('utc', now())`)会归一化为 `CURRENT_TIMESTAMP`
## 🛠 技术栈

### 外部依赖
- **异步运行时**: Tokio 1.53+
- **SQLite 实现**: rusqlite 0.30(bundled)
- **UUID 生成**: uuid 1.0
- **序列化**: Serde 1.0
- **时间处理**: Chrono 0.4

### 自定义实现
- **纯 Rust 存储引擎**: StorageEngine(零依赖内存数据库)
- **MySQL 协议**: MySqlConnection(原生协议实现)
- **PostgreSQL 协议**: PostgresConnection(原生协议实现)
- **数据类型系统**: SqlValue, Row, QueryResult
- **连接抽象**: DatabaseConnection trait
- **事务系统**: Transaction
- **连接池**: Pool / SimplePool
- **工具库**: SimpleUuid, SimpleLruCache, SimpleError, SqlSanitizer(防 SQL 注入)

## 📚 文档

- [README.md]README.md - English README
- [README.zh.md]README.zh.md - 中文 README
- [DATABASE_REPLACEMENT.md]DATABASE_REPLACEMENT.md - 数据库层替换详情
- [DEPENDENCY_OPTIMIZATION.md]DEPENDENCY_OPTIMIZATION.md - 依赖优化详情
- [PROJECT_SUMMARY.md]PROJECT_SUMMARY.md - 项目总结

## 🎓 学习价值

TORM 展示了:
- 如何用 Rust 实现数据库协议
- 类型安全的数据库抽象设计
- 异步 I/O 和网络编程
- MySQL 和 PostgreSQL 协议基础
- 生产级的 SQLite 实现
- 零依赖工具库的实现(UUID、LRU 缓存、连接池)

## 🎯 适用场景

### 生产环境
- ✅ SQLite 应用(移动、桌面、轻量级 Web)
- ✅ 需要标准 SQLite 文件格式的项目(可与其他 SQLite 工具互操作)
- ✅ MySQL 应用(Web 服务、企业应用,支持 MySQL 5.7+)
- ✅ PostgreSQL 应用(Web 服务、企业应用,支持 PostgreSQL 10+)
- ✅ 对依赖有严格控制的项目

### 学习开发
- ✅ 数据库协议学习
- ✅ Rust 异步编程学习
- ✅ ORM 设计模式学习

## 📝 许可证

MIT

## 🤝 贡献

欢迎提交 Issue 和 Pull Request!