mpyw/gorm-purity-survey
GitHub: mpyw/gorm-purity-survey
系统性调研并记录 GORM 在 77 个补丁版本中 `*gorm.DB` 方法行为(纯洁性/可变性)的破坏性变更,为开发者提供版本兼容性参考与安全使用指南。
Stars: 0 | Forks: 0
# gorm-purity-survey
**记录 GORM 在不同补丁版本中 `*gorm.DB` 方法行为破坏性变更的调研。**
## 快速链接
- **[USAGE_GUIDE.md](./USAGE_GUIDE.md)** - 实用指南:“哪个版本会因为什么模式而破坏?”
- **[purity/REPORT.md](./purity/REPORT.md)** - 完整的纯洁性调研结果
- **[methods/REPORT.md](./methods/REPORT.md)** - 各版本方法枚举
## 目的
本项目**记录并公开** GORM 不稳定的 API 行为:
- 破坏性变更发生在 **补丁版本** 中(例如 v1.25.11 → v1.25.12)
- 方法语义(纯洁/不纯洁,可变/不可变)在无通知的情况下发生改变
- 没有关于这些行为变更的明确文档
本次调研作为 GORM 危险的版本控制做法的**证据**。
## 问题
GORM 的方法行为在各个补丁版本中发生过多次变更:
```
// This code's behavior depends on which GORM version you're using:
q := db.Where("active = ?", true)
q.Where("role = ?", "admin").Find(&admins)
q.Where("role = ?", "user").Find(&users) // Does this include "admin"? DEPENDS ON VERSION.
```
## 关键发现
### 特定版本的破坏性变更
| 版本 | 变更 | 影响 |
|---------|--------|--------|
| **v1.20.7** | Session 克隆:1→2 | Session() 现在完全隔离 |
| **v1.20.8** | Preload 回调克隆:1→2 | Preload 回调现在已隔离 |
| **v1.21.8** | Delete/Update 变为纯洁 | 丢弃返回值是安全的 |
| **v1.23.2** | Begin 克隆:2→1 | Begin() 的隔离度低于 Session() |
| **v1.25.7** | Limit/Offset 变为纯洁 | 丢弃返回值是安全的 |
| **v1.30.0** | **Preload 回调克隆:2→0** | **退化:#7662** |
### 纯洁性分类
基于对全部 77 个版本(v1.20.0 ~ v1.31.1)的测试:
| 类别 | 符号 | 数量 (v1.31.1) |
|----------|--------|-----------------|
| 纯洁 | ✅ | 26 个方法 |
| 不纯洁-累积 | ☠️ | ~15 个方法 |
| 不纯洁-覆盖 | ⚠️ | ~6 个方法 |
**不纯洁-累积(危险)**:`Where`, `Or`, `Not`, `Order`, `Joins`
**不纯洁-覆盖(较不危险)**:`Select`, `Distinct`
### 黄金法则
**在分支 `*gorm.DB` 之前,务必调用 `Session(&gorm.Session{})`。**
```
// SAFE in all versions
base := db.Session(&gorm.Session{})
base.Where("x").Find(&r1) // OK
base.Where("y").Find(&r2) // OK - no interference
```
有关详细模式,请参阅 [USAGE_GUIDE.md](./USAGE_GUIDE.md)。
## 调研范围
- **版本**:77 个版本(v1.20.0 ~ v1.31.1)
- **目标**:`*gorm.DB` 的所有公共方法
- **测试**:纯洁性分类、不可变返回值、回调隔离
## 调研结果
### 方法枚举 (methods/)
| 版本 | `*gorm.DB` 方法 |
|---------|-------------------|
| v1.20.0 | 70 |
| v1.21.0 | 73 |
| v1.25.11 | 76 |
| v1.31.1 | 77 |
新增的方法:`CreateInBatches` (v1.20.7), `ToSQL` (v1.22.3), `Connection` (v1.22.5), `InnerJoins` (v1.24.3), `MapColumns` (v1.25.11)
### 纯洁性测试结果 (purity/)
完整结果详见 [purity/REPORT.md](./purity/REPORT.md),包括:
- 各版本每个方法的纯洁/不纯洁状态
- 返回值和回调的克隆值 (0/1/2)
- 不纯洁模式(累积与覆盖)
- 特定版本的退化
## 目录结构
```
gorm-purity-survey/
├── README.md # This file
├── USAGE_GUIDE.md # Practical usage patterns guide
├── CLAUDE.md # Development instructions
│
├── methods/ # Method enumeration results
│ ├── REPORT.md # Summary report
│ └── v*.json # Per-version method lists
│
├── purity/ # Purity test results
│ ├── REPORT.md # Full survey report
│ └── v*.json # Per-version purity data
│
├── scripts/
│ ├── methods/ # Enumeration code
│ ├── purity/ # Purity test code
│ ├── *-run.sh # Single version scripts
│ ├── *-all.sh # Parallel all-version scripts
│ └── *-generate-*.py # Report generators
│
├── Dockerfile.methods # Method enumeration container
├── Dockerfile.purity # Purity testing container
└── versions.txt # All 77 GORM versions
```
## 运行调研
```
# 方法枚举(全部 77 个版本,4 并行)
./scripts/methods-all.sh 4
./scripts/methods-generate-markdown.sh > methods/REPORT.md
# Purity 测试(全部 77 个版本,4 并行)
./scripts/purity-all.sh 4
python3 scripts/purity-generate-markdown.py > purity/REPORT.md
# 单版本
./scripts/methods-run.sh v1.31.1
./scripts/purity-run.sh v1.31.1
```
## 参考
- [gormreuse](https://github.com/mpyw/gormreuse) - GORM `*gorm.DB` 复用 linter
- [GORM 文档](https://gorm.io/docs/)
- [GORM GitHub](https://github.com/go-gorm/gorm)
### GORM 关键 Issue
- [#7662](https://github.com/go-gorm/gorm/issues/7662) - Preload 回调 clone=0 (v1.30.0+)
- [#7594](https://github.com/go-gorm/gorm/issues/7594) - InnerJoins+Preload 重复 JOIN
- [#7027](https://github.com/go-gorm/gorm/pull/7027) - AfterQuery Joins 清除修复
标签:API稳定性, EVTX分析, Go, GORM, ORM, Ruby工具, 兼容性分析, 应用安全, 日志审计, 行为测试, 请求拦截, 逆向工具