# Model/cache 手册

本手册是 `rzcli model gen` 的查阅入口。扩展说明保留在旧路径：[Model/cache generation](../model-cache.md)。

## 能力概览

`rzcli model gen` 从 SQL schema 生成：

- entity struct
- repository trait
- 可选 SQLx repository
- cache key helper
- 可选 Redis/L1/L2 cache alias
- 可选 cache-aside repository

## CLI

默认命令保持 MySQL/goctl SQL 子集和 SQLite SQLx backend：

```bash
cargo run -p rs-zero-cli -- model gen \
  -s examples/model-cache/schema.sql \
  -d target/generated \
  --with-sqlx \
  --with-redis-cache
```

显式选择 MySQL SQLx backend：

```bash
cargo run -p rs-zero-cli -- model gen \
  -s examples/model-cache/schema.sql \
  -d target/generated \
  --with-sqlx \
  --sqlx-backend mysql \
  --with-redis-cache
```

PostgreSQL schema 使用显式方言。未指定 `--sqlx-backend` 时，`--dialect postgres --with-sqlx` 默认生成 `rs_zero::db::PostgresDatabasePool`：

```bash
cargo run -p rs-zero-cli -- model gen \
  -s tests/fixtures/postgres/model/user.sql \
  -d target/generated \
  --dialect postgres \
  --with-sqlx \
  --with-redis-cache
```

## 生成的 repository

启用 `--with-sqlx` 后，`src/repository.rs` 会包含：

- `Sqlx{Entity}Repository::new(pool)`。
- 主键和唯一索引的 `find_by_*` 方法，返回 `DatabaseResult<Option<Entity>>`。
- 普通非唯一索引的 `find_all_by_*` 方法，返回 `DatabaseResult<Vec<Entity>>`。
- `save` 和主键 `delete_by_*` 方法。

启用 `--with-sqlx --with-redis-cache` 后，还会生成 `Cached{Entity}Repository<S>`。它包装 SQLx repository 与 `rs_zero::cache::CacheAside<S>`：

- 主键和唯一索引读取走 cache-aside。
- `save` 后删除主键和唯一索引 key。
- `delete_by_*` 会删除主键 key；如删除前读取到实体，也会删除唯一索引 key。
- 普通非唯一索引不会生成单对象 cache key，避免把多行结果错误缓存为单条记录。

示例 wiring：

```rust
use rs_zero::cache::{CacheAside, CacheAsideConfig, LruCacheStore, TwoLevelCacheStore};
use rs_zero::cache::redis::{RedisCacheConfig, RedisCacheStore};
use user_model::repository::{CachedUserRepository, SqlxUserRepository};

let sql_repo = SqlxUserRepository::new(pool);
let l1 = LruCacheStore::new(10_000)?;
let l2 = RedisCacheStore::new(RedisCacheConfig::default())?;
let cache = CacheAside::new(TwoLevelCacheStore::new(l1, l2), CacheAsideConfig::default());
let repo = CachedUserRepository::new(sql_repo, cache, "user-service");
let user = repo.find_by_id(42).await?;
```

## SQL parser 边界

支持常见 MySQL `CREATE TABLE` 子集，包含字段 metadata、table metadata、primary/unique/normal index 和复合索引。MySQL SQLx backend 需显式传 `--sqlx-backend mysql`，会生成 `rs_zero::db::MySqlDatabasePool`。

PostgreSQL 支持常见 `CREATE TABLE` 子集：双引号标识符、schema-qualified table name、`SERIAL` / `BIGSERIAL`、`GENERATED ... AS IDENTITY`、table-level constraint、`CREATE INDEX`、`COMMENT ON TABLE/COLUMN` 和常见字段类型映射。

完整 SQL grammar、数据库 introspection、迁移管理和 ORM 不是当前目标。

## 相关测试

- `cargo test -p rs-zero-cli --test model_codegen_integration`
- `cargo test -p rs-zero-cli --test model_adapter_codegen`
- `cargo test -p rs-zero-cli --test goctl_model_compat`
- `cargo test -p rs-zero-cli --test model_mysql_cli`
- `cargo test -p rs-zero-cli --test model_postgres_codegen`
- `cargo test -p rs-zero-cli --test model_postgres_cli`
- `cargo check -p rs-zero --no-default-features --features db-mysql,cache-redis`
- `cargo check -p rs-zero --no-default-features --features db-postgres,cache-redis`
