## [ERR-20260430-007] cleanupByPrefix 对 boolean 列做 LIKE 报 operator 不存在

### 现象

PR #199 加的 `cleanupByPrefix(prismaInstance, options)` 在 meeting-attendance 测试 afterEach 里报：

```
PrismaClientKnownRequestError: 
  code: 'P2010',
  meta: {
    code: '42883',
    message: 'ERROR: operator does not exist: boolean ~~ text\n
             HINT: No operator matches the given name and argument types.
             You might need to add explicit type casts.'
  }
```

`~~` 是 PostgreSQL 的 `LIKE` 操作符内部表示。

### 根因

`cleanupByPrefix` 从 `information_schema.columns` 取所有 `column_name IN ('code','name','username','email','slug')` 的列，然后逐列做：

```sql
DELETE FROM "schema"."table" WHERE "column_name" LIKE 't_%'
```

但同名列**不一定都是字符串类型**——例如 `platform_meeting_attendance.outlook_event_snapshot` 有列 `name` (boolean，表示 'is name field')；或某些表有 `code` (int，表示状态码)。同名 boolean 列做 LIKE 直接 SQL 报错。

site-attendance 模块测试不踩到（schema 里同名列都是 string），所以 PR #199 + PR #203 都过 CI；meeting-attendance 撞上 → afterEach 抛错。

### 修法

`information_schema.columns` 查询里加 `data_type` 过滤：

```sql
SELECT table_name, column_name
FROM information_schema.columns
WHERE table_schema = $1
  AND column_name = ANY($2::text[])
  AND data_type IN ('character varying', 'text', 'character', 'citext')
```

`citext` 留着兜底——项目目前没用，但加 PostgreSQL 通常有这扩展。

### 复用建议

- **写「按列名扫表」的工具时，一定加 `data_type` 过滤**——同名列不同类型在大型 schema 里很常见
- **第一个 PR 验证只覆盖一个简单模块就过 CI** ≠ 真没 bug。复杂 schema 上跑一遍才算
- API 函数的边界条件测试应该包含「同名 boolean / int 列在表里」的场景

### 后续

- 修复跟随 meeting-attendance 迁移失败的发现一起 ship（不再单独跑 PR #199 加 follow-up，而是这次顺手修 + 沉淀 learning）

### 上下文

- PR #199 加 cleanupByPrefix API
- meeting-attendance 迁移尝试触发（`refactor/cleanup-helper-meeting-attendance` 分支已弃，因 FK ON DELETE RESTRICT 决定不迁该模块）
- 关联 issue #165
