schema-dsl 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +1 -3
- package/README.md +69 -7
- package/docs/FEATURE-INDEX.md +1 -1
- package/docs/INDEX.md +31 -2
- package/docs/export-guide.md +3 -0
- package/docs/export-limitations.md +551 -0
- package/docs/mongodb-exporter.md +16 -0
- package/docs/mysql-exporter.md +16 -0
- package/docs/postgresql-exporter.md +14 -0
- package/docs/schema-utils-chaining.md +146 -0
- package/docs/schema-utils.md +7 -9
- package/docs/validate-async.md +480 -0
- package/examples/array-dsl-example.js +1 -1
- package/examples/express-integration.js +376 -0
- package/examples/new-features-comparison.js +315 -0
- package/examples/schema-utils-chaining.examples.js +250 -0
- package/examples/simple-example.js +2 -2
- package/index.js +13 -1
- package/lib/adapters/DslAdapter.js +47 -1
- package/lib/core/Validator.js +60 -0
- package/lib/errors/ValidationError.js +191 -0
- package/lib/utils/SchemaUtils.js +170 -38
- package/package.json +1 -1
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# 数据库导出限制说明
|
|
2
|
+
|
|
3
|
+
> **重要提示**: 在使用 schema-dsl 导出数据库 Schema 功能时,请仔细阅读本文档,了解哪些特性可以导出,哪些不支持。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📑 目录
|
|
8
|
+
|
|
9
|
+
- [核心原则](#核心原则)
|
|
10
|
+
- [不支持导出的特性](#不支持导出的特性)
|
|
11
|
+
- [部分支持的特性](#部分支持的特性)
|
|
12
|
+
- [完全支持的特性](#完全支持的特性)
|
|
13
|
+
- [数据库特定限制](#数据库特定限制)
|
|
14
|
+
- [最佳实践建议](#最佳实践建议)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 核心原则
|
|
19
|
+
|
|
20
|
+
**schema-dsl 的数据库导出功能遵循以下原则**:
|
|
21
|
+
|
|
22
|
+
1. ✅ **静态结构优先**: 只导出固定的、静态的 Schema 定义
|
|
23
|
+
2. ❌ **动态逻辑不导出**: 运行时条件逻辑、动态计算等无法转换为数据库约束
|
|
24
|
+
3. ⚠️ **约束映射有限**: 数据库原生约束能力有限,部分高级约束会被忽略或简化
|
|
25
|
+
4. 🎯 **类型映射为主**: 主要关注类型定义和基础约束(长度、范围、必填等)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 不支持导出的特性
|
|
30
|
+
|
|
31
|
+
以下 schema-dsl 特性**无法导出到数据库 Schema**(会被忽略):
|
|
32
|
+
|
|
33
|
+
### 1. 条件验证逻辑 ❌
|
|
34
|
+
|
|
35
|
+
#### `dsl.match()` - 条件字段映射
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// ❌ 无法导出
|
|
39
|
+
const schema = dsl({
|
|
40
|
+
contactType: 'email|phone',
|
|
41
|
+
contact: dsl.match('contactType', {
|
|
42
|
+
email: 'email!',
|
|
43
|
+
phone: 'phone:cn!'
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**原因**: 数据库不支持"根据 A 字段值决定 B 字段类型"的动态约束。
|
|
49
|
+
|
|
50
|
+
**替代方案**:
|
|
51
|
+
- 导出为最宽松的类型(`VARCHAR(255)`)
|
|
52
|
+
- 验证逻辑保留在应用层(使用 SchemaIO 验证器)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
#### `dsl.if()` - 条件验证
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
// ❌ 无法导出
|
|
60
|
+
const schema = dsl({
|
|
61
|
+
isVip: 'boolean',
|
|
62
|
+
discount: dsl.if('isVip', 'number:10-100!', 'number:0-10')
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**原因**: 同上,数据库不支持条件约束。
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### 2. 复杂的 JSON Schema 关键字 ❌
|
|
71
|
+
|
|
72
|
+
以下 JSON Schema 高级特性无法导出:
|
|
73
|
+
|
|
74
|
+
| 关键字 | 说明 | 导出行为 |
|
|
75
|
+
|--------|------|----------|
|
|
76
|
+
| `allOf` | 所有 Schema 都满足 | ❌ 忽略 |
|
|
77
|
+
| `anyOf` | 满足任一 Schema | ❌ 忽略 |
|
|
78
|
+
| `oneOf` | 仅满足一个 Schema | ❌ 忽略 |
|
|
79
|
+
| `not` | 不满足某 Schema | ❌ 忽略 |
|
|
80
|
+
| `if/then/else` | 条件 Schema | ❌ 忽略 |
|
|
81
|
+
| `dependencies` | 字段依赖关系 | ❌ 忽略 |
|
|
82
|
+
|
|
83
|
+
**示例**:
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// ❌ 这些结构无法导出
|
|
87
|
+
const schema = {
|
|
88
|
+
type: 'object',
|
|
89
|
+
allOf: [
|
|
90
|
+
{ properties: { name: { type: 'string' } } },
|
|
91
|
+
{ properties: { age: { type: 'number' } } }
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### 3. 自定义验证器 ❌
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
// ❌ 自定义验证器无法导出
|
|
102
|
+
const schema = dsl('string:3-32!')
|
|
103
|
+
.custom((value) => value.startsWith('USER_'))
|
|
104
|
+
.messages({ 'string.custom': '必须以 USER_ 开头' });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**原因**: 数据库无法执行 JavaScript 函数。
|
|
108
|
+
|
|
109
|
+
**替代方案**:
|
|
110
|
+
- 使用 `pattern` 正则表达式(如果可表达)
|
|
111
|
+
- 验证逻辑保留在应用层
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### 4. 自定义错误消息 ❌
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// ❌ 错误消息无法导出
|
|
119
|
+
const schema = dsl('email!')
|
|
120
|
+
.messages({
|
|
121
|
+
'string.format': '请输入有效的邮箱地址'
|
|
122
|
+
})
|
|
123
|
+
.label('用户邮箱');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**导出行为**:
|
|
127
|
+
- ✅ `label()` 会导出为 `COMMENT`(MySQL/PostgreSQL)
|
|
128
|
+
- ❌ `messages()` 会被忽略(数据库不存储错误消息)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### 5. 嵌套对象的深度约束 ⚠️
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// ⚠️ 嵌套对象会简化为 JSON/JSONB 类型
|
|
136
|
+
const schema = dsl({
|
|
137
|
+
profile: {
|
|
138
|
+
bio: 'string:500',
|
|
139
|
+
avatar: 'url',
|
|
140
|
+
social: {
|
|
141
|
+
twitter: 'url',
|
|
142
|
+
github: 'url'
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**导出行为**:
|
|
149
|
+
- MongoDB: ✅ 完整支持嵌套验证
|
|
150
|
+
- MySQL: ❌ 导出为 `JSON` 类型,内部约束丢失
|
|
151
|
+
- PostgreSQL: ❌ 导出为 `JSONB` 类型,内部约束丢失
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 部分支持的特性
|
|
156
|
+
|
|
157
|
+
以下特性在不同数据库中支持程度不同:
|
|
158
|
+
|
|
159
|
+
### 1. 正则表达式约束 ⚠️
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
const schema = dsl('string!')
|
|
163
|
+
.pattern(/^[A-Z][a-z]+$/);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| 数据库 | 支持程度 | 导出结果 |
|
|
167
|
+
|--------|----------|----------|
|
|
168
|
+
| MongoDB | ✅ 完全支持 | `pattern: "^[A-Z][a-z]+$"` |
|
|
169
|
+
| MySQL | ❌ 不支持 | 忽略 |
|
|
170
|
+
| PostgreSQL | ❌ 不支持 | 忽略 |
|
|
171
|
+
|
|
172
|
+
**注意**: MySQL 和 PostgreSQL 没有原生的正则约束,需在应用层验证。
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### 2. 数值范围约束 ⚠️
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
const schema = dsl('number:18-120');
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| 数据库 | 支持程度 | 导出结果 |
|
|
183
|
+
|--------|----------|----------|
|
|
184
|
+
| MongoDB | ✅ 完全支持 | `minimum: 18, maximum: 120` |
|
|
185
|
+
| MySQL | ❌ 不支持 | 忽略 |
|
|
186
|
+
| PostgreSQL | ✅ 支持 | `CHECK (age BETWEEN 18 AND 120)` |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### 3. 字符串长度约束 ⚠️
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const schema = dsl('string:3-32');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
| 数据库 | 支持程度 | 导出结果 |
|
|
197
|
+
|--------|----------|----------|
|
|
198
|
+
| MongoDB | ✅ 完全支持 | `minLength: 3, maxLength: 32` |
|
|
199
|
+
| MySQL | ⚠️ 仅 maxLength | `VARCHAR(32)` |
|
|
200
|
+
| PostgreSQL | ✅ 完全支持 | `VARCHAR(32) CHECK (LENGTH(...) >= 3)` |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### 4. 枚举约束 ⚠️
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
const schema = dsl('active|inactive|banned');
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
| 数据库 | 支持程度 | 导出结果 |
|
|
211
|
+
|--------|----------|----------|
|
|
212
|
+
| MongoDB | ✅ 完全支持 | `enum: ['active', 'inactive', 'banned']` |
|
|
213
|
+
| MySQL | ❌ 不支持 | `VARCHAR(255)` |
|
|
214
|
+
| PostgreSQL | ✅ 支持 | `CHECK (status IN (...))` |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### 5. 数组约束 ⚠️
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const schema = dsl('array!1-10<string:3-32>');
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
| 数据库 | 支持程度 | 导出结果 |
|
|
225
|
+
|--------|----------|----------|
|
|
226
|
+
| MongoDB | ✅ 完全支持 | `type: array, minItems: 1, maxItems: 10, items: {...}` |
|
|
227
|
+
| MySQL | ❌ 简化 | `JSON` |
|
|
228
|
+
| PostgreSQL | ❌ 简化 | `JSONB` |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 完全支持的特性
|
|
233
|
+
|
|
234
|
+
以下特性在所有数据库中都能良好导出:
|
|
235
|
+
|
|
236
|
+
### ✅ 基础类型
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
dsl({
|
|
240
|
+
name: 'string!',
|
|
241
|
+
age: 'number',
|
|
242
|
+
active: 'boolean',
|
|
243
|
+
createdAt: 'datetime!'
|
|
244
|
+
})
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**所有数据库都支持类型映射**。
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### ✅ 必填约束
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
dsl({
|
|
255
|
+
email: 'email!', // 必填
|
|
256
|
+
phone: 'phone:cn' // 可选
|
|
257
|
+
})
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**导出为**:
|
|
261
|
+
- MongoDB: `required: ['email']`
|
|
262
|
+
- MySQL/PostgreSQL: `NOT NULL` / `NULL`
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### ✅ 默认值(仅 MySQL/PostgreSQL)
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
const schema = dsl('boolean')
|
|
270
|
+
.default(false);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**导出为**:
|
|
274
|
+
- MongoDB: ❌ 不支持 `default`
|
|
275
|
+
- MySQL/PostgreSQL: ✅ `DEFAULT false`
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### ✅ 字段描述
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
const schema = dsl('string!')
|
|
283
|
+
.description('用户登录名');
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**导出为**:
|
|
287
|
+
- MongoDB: `description: "用户登录名"`
|
|
288
|
+
- MySQL: `COMMENT '用户登录名'`
|
|
289
|
+
- PostgreSQL: `COMMENT ON COLUMN ... IS '用户登录名'`
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## 数据库特定限制
|
|
294
|
+
|
|
295
|
+
### MongoDB
|
|
296
|
+
|
|
297
|
+
| 限制 | 说明 |
|
|
298
|
+
|------|------|
|
|
299
|
+
| ❌ 不支持 `default` | MongoDB JSON Schema 不支持默认值 |
|
|
300
|
+
| ❌ 不支持外键 | 需在应用层实现引用完整性 |
|
|
301
|
+
| ✅ 最完整的约束支持 | 正则、范围、枚举、数组约束都支持 |
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### MySQL
|
|
306
|
+
|
|
307
|
+
| 限制 | 说明 |
|
|
308
|
+
|------|------|
|
|
309
|
+
| ❌ 不支持正则 | 无法导出 `pattern` 约束 |
|
|
310
|
+
| ❌ 不支持数值范围 | 无法导出 `minimum/maximum` |
|
|
311
|
+
| ❌ 不支持枚举 CHECK | 枚举导出为普通 `VARCHAR` |
|
|
312
|
+
| ⚠️ 字符串长度仅 maxLength | `minLength` 会被忽略 |
|
|
313
|
+
| ❌ 对象/数组简化为 JSON | 内部结构约束丢失 |
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### PostgreSQL
|
|
318
|
+
|
|
319
|
+
| 限制 | 说明 |
|
|
320
|
+
|------|------|
|
|
321
|
+
| ❌ 不支持正则 | 无法导出 `pattern` 约束 |
|
|
322
|
+
| ✅ 支持 CHECK 约束 | 可导出范围、枚举、长度约束 |
|
|
323
|
+
| ❌ 对象/数组简化为 JSONB | 内部结构约束丢失 |
|
|
324
|
+
| ✅ 完整的注释支持 | `COMMENT ON COLUMN` |
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 最佳实践建议
|
|
329
|
+
|
|
330
|
+
### 1. 分层验证策略 🎯
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
┌─────────────────────────────────────────┐
|
|
334
|
+
│ 应用层(SchemaIO 完整验证) │
|
|
335
|
+
│ - 条件逻辑(match/if) │
|
|
336
|
+
│ - 自定义验证器 │
|
|
337
|
+
│ - 复杂约束(正则、范围等) │
|
|
338
|
+
│ - 友好的错误消息 │
|
|
339
|
+
└─────────────────────────────────────────┘
|
|
340
|
+
↓
|
|
341
|
+
┌─────────────────────────────────────────┐
|
|
342
|
+
│ 数据库层(基础约束) │
|
|
343
|
+
│ - 类型定义(string/number/boolean) │
|
|
344
|
+
│ - NOT NULL 约束 │
|
|
345
|
+
│ - 主键/外键 │
|
|
346
|
+
│ - 简单长度限制(maxLength) │
|
|
347
|
+
└─────────────────────────────────────────┘
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**原则**:
|
|
351
|
+
- 数据库:防止数据损坏的最后一道防线
|
|
352
|
+
- 应用层:完整的业务逻辑验证
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
### 2. 明确导出前的预期 📋
|
|
357
|
+
|
|
358
|
+
在使用导出功能前,请先检查 Schema 是否包含不支持的特性:
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
const { dsl, exporters } = require('schema-dsl');
|
|
362
|
+
|
|
363
|
+
// ❌ 不适合导出的 Schema(包含条件逻辑)
|
|
364
|
+
const conditionalSchema = dsl({
|
|
365
|
+
type: 'email|phone',
|
|
366
|
+
value: dsl.match('type', {
|
|
367
|
+
email: 'email!',
|
|
368
|
+
phone: 'phone:cn!'
|
|
369
|
+
})
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// ✅ 适合导出的 Schema(静态定义)
|
|
373
|
+
const staticSchema = dsl({
|
|
374
|
+
id: 'uuid!',
|
|
375
|
+
email: 'email!',
|
|
376
|
+
phone: 'string:11',
|
|
377
|
+
status: 'active|inactive',
|
|
378
|
+
createdAt: 'datetime!'
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// 导出前先了解限制
|
|
382
|
+
const exporter = new exporters.MySQLExporter();
|
|
383
|
+
const ddl = exporter.export('users', staticSchema);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### 3. 使用描述说明约束 📝
|
|
389
|
+
|
|
390
|
+
对于无法导出的约束,使用 `description()` 在数据库中留下说明:
|
|
391
|
+
|
|
392
|
+
```javascript
|
|
393
|
+
const schema = dsl('string!')
|
|
394
|
+
.pattern(/^[A-Z][a-z]+$/)
|
|
395
|
+
.description('首字母大写,其余小写(正则:^[A-Z][a-z]+$)');
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**导出为**:
|
|
399
|
+
|
|
400
|
+
```sql
|
|
401
|
+
-- MySQL
|
|
402
|
+
`name` VARCHAR(255) NOT NULL COMMENT '首字母大写,其余小写(正则:^[A-Z][a-z]+$)'
|
|
403
|
+
|
|
404
|
+
-- PostgreSQL
|
|
405
|
+
COMMENT ON COLUMN users.name IS '首字母大写,其余小写(正则:^[A-Z][a-z]+$)';
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### 4. 保留完整 Schema 定义 💾
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// schemas/user.js
|
|
414
|
+
const { dsl } = require('schema-dsl');
|
|
415
|
+
|
|
416
|
+
// 完整定义(包含所有验证逻辑)
|
|
417
|
+
const userSchema = dsl({
|
|
418
|
+
username: 'string:3-32!'
|
|
419
|
+
.pattern(/^[a-zA-Z0-9_]+$/)
|
|
420
|
+
.messages({ 'string.pattern': '只能包含字母数字下划线' })
|
|
421
|
+
.description('用户登录名'),
|
|
422
|
+
|
|
423
|
+
contactType: 'email|phone',
|
|
424
|
+
contact: dsl.match('contactType', {
|
|
425
|
+
email: 'email!',
|
|
426
|
+
phone: 'phone:cn!'
|
|
427
|
+
})
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
module.exports = {
|
|
431
|
+
// 应用层使用完整 Schema
|
|
432
|
+
full: userSchema,
|
|
433
|
+
|
|
434
|
+
// 数据库导出使用简化 Schema
|
|
435
|
+
db: dsl({
|
|
436
|
+
username: 'string:3-32!'.description('用户登录名'),
|
|
437
|
+
contactType: 'email|phone',
|
|
438
|
+
contact: 'string!'.description('邮箱或手机号(根据 contactType)')
|
|
439
|
+
})
|
|
440
|
+
};
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
### 5. 文档化不兼容特性 📖
|
|
446
|
+
|
|
447
|
+
在项目文档中明确说明哪些验证逻辑在数据库层不生效:
|
|
448
|
+
|
|
449
|
+
```markdown
|
|
450
|
+
## 数据验证说明
|
|
451
|
+
|
|
452
|
+
### 应用层验证(SchemaIO)
|
|
453
|
+
- ✅ `contact` 字段根据 `contactType` 动态验证
|
|
454
|
+
- ✅ 用户名正则验证(`^[a-zA-Z0-9_]+$`)
|
|
455
|
+
- ✅ 自定义业务规则验证
|
|
456
|
+
|
|
457
|
+
### 数据库层约束
|
|
458
|
+
- ✅ `username` 长度限制(3-32 字符)
|
|
459
|
+
- ✅ 必填字段约束
|
|
460
|
+
- ❌ 动态类型验证(依赖应用层)
|
|
461
|
+
- ❌ 正则表达式验证(依赖应用层)
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## 常见问题
|
|
467
|
+
|
|
468
|
+
### Q1: 为什么 `dsl.match()` 不能导出?
|
|
469
|
+
|
|
470
|
+
**A**: 数据库不支持"根据字段 A 的值决定字段 B 的类型"这种动态约束。数据库 Schema 在创建时就固定了,无法运行时改变。
|
|
471
|
+
|
|
472
|
+
**解决方案**:
|
|
473
|
+
- 导出为最宽松的类型(如 `VARCHAR(255)`)
|
|
474
|
+
- 应用层使用完整 Schema 验证
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
### Q2: MySQL 不支持正则,怎么办?
|
|
479
|
+
|
|
480
|
+
**A**: MySQL 的 `CHECK` 约束不支持正则表达式。
|
|
481
|
+
|
|
482
|
+
**解决方案**:
|
|
483
|
+
1. 应用层验证(推荐)
|
|
484
|
+
2. 使用触发器(不推荐,复杂且难维护)
|
|
485
|
+
3. 在 `COMMENT` 中说明约束规则
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
### Q3: 嵌套对象导出后丢失约束?
|
|
490
|
+
|
|
491
|
+
**A**: MySQL/PostgreSQL 将嵌套对象导出为 `JSON`/`JSONB` 类型,内部约束无法表达。
|
|
492
|
+
|
|
493
|
+
**解决方案**:
|
|
494
|
+
- MongoDB: 完整支持嵌套验证
|
|
495
|
+
- MySQL/PostgreSQL: 应用层验证
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
### Q4: 如何检查 Schema 是否适合导出?
|
|
500
|
+
|
|
501
|
+
**A**: 以下特性**不适合**导出:
|
|
502
|
+
|
|
503
|
+
```javascript
|
|
504
|
+
// ❌ 包含条件逻辑
|
|
505
|
+
dsl.match(...)
|
|
506
|
+
dsl.if(...)
|
|
507
|
+
|
|
508
|
+
// ❌ 包含自定义验证器
|
|
509
|
+
.custom(...)
|
|
510
|
+
|
|
511
|
+
// ❌ 复杂的 allOf/anyOf/oneOf
|
|
512
|
+
{ allOf: [...] }
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
**适合导出**的特性:
|
|
516
|
+
|
|
517
|
+
```javascript
|
|
518
|
+
// ✅ 基础类型 + 简单约束
|
|
519
|
+
dsl('string:3-32!')
|
|
520
|
+
dsl('number:0-100')
|
|
521
|
+
dsl('email!')
|
|
522
|
+
dsl('active|inactive|banned')
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## 总结
|
|
528
|
+
|
|
529
|
+
| 特性 | MongoDB | MySQL | PostgreSQL |
|
|
530
|
+
|------|---------|-------|------------|
|
|
531
|
+
| 基础类型 | ✅ | ✅ | ✅ |
|
|
532
|
+
| 必填约束 | ✅ | ✅ | ✅ |
|
|
533
|
+
| 长度约束 | ✅ | ⚠️ 仅 max | ✅ |
|
|
534
|
+
| 数值范围 | ✅ | ❌ | ✅ |
|
|
535
|
+
| 正则表达式 | ✅ | ❌ | ❌ |
|
|
536
|
+
| 枚举 | ✅ | ❌ | ✅ |
|
|
537
|
+
| 条件逻辑 | ❌ | ❌ | ❌ |
|
|
538
|
+
| 自定义验证器 | ❌ | ❌ | ❌ |
|
|
539
|
+
| 嵌套对象 | ✅ | ⚠️ JSON | ⚠️ JSONB |
|
|
540
|
+
| 字段描述 | ✅ | ✅ | ✅ |
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
## 相关文档
|
|
545
|
+
|
|
546
|
+
- [数据库导出指南](export-guide.md)
|
|
547
|
+
- [MongoDB 导出器](mongodb-exporter.md)
|
|
548
|
+
- [MySQL 导出器](mysql-exporter.md)
|
|
549
|
+
- [PostgreSQL 导出器](postgresql-exporter.md)
|
|
550
|
+
- [最佳实践](best-practices.md)
|
|
551
|
+
|
package/docs/mongodb-exporter.md
CHANGED
|
@@ -270,10 +270,26 @@ async function createValidatedCollection() {
|
|
|
270
270
|
|
|
271
271
|
---
|
|
272
272
|
|
|
273
|
+
## 导出限制
|
|
274
|
+
|
|
275
|
+
⚠️ **重要提示**: 并非所有 SchemaIO 特性都能导出到数据库 Schema。
|
|
276
|
+
|
|
277
|
+
**不支持导出的特性**:
|
|
278
|
+
- ❌ 条件验证逻辑(`dsl.match()`, `dsl.if()`)
|
|
279
|
+
- ❌ 自定义验证器(`.custom()`)
|
|
280
|
+
- ❌ 复杂 JSON Schema 关键字(`allOf`, `anyOf`, `oneOf`)
|
|
281
|
+
- ❌ 自定义错误消息(`.messages()`)
|
|
282
|
+
|
|
283
|
+
**详细说明**: 请阅读 [导出限制说明文档](export-limitations.md)
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
273
287
|
## 相关文档
|
|
274
288
|
|
|
275
289
|
- [数据库导出指南](export-guide.md)
|
|
276
290
|
- [MySQL 导出器](mysql-exporter.md)
|
|
277
291
|
- [PostgreSQL 导出器](postgresql-exporter.md)
|
|
278
292
|
- [TypeConverter](type-converter.md)
|
|
293
|
+
- [**导出限制说明**](export-limitations.md) ⚠️
|
|
294
|
+
|
|
279
295
|
|
package/docs/mysql-exporter.md
CHANGED
|
@@ -248,10 +248,26 @@ CREATE INDEX `idx_users_status` ON `users` (`status`);
|
|
|
248
248
|
|
|
249
249
|
---
|
|
250
250
|
|
|
251
|
+
## 导出限制
|
|
252
|
+
|
|
253
|
+
⚠️ **重要提示**: MySQL 对约束的支持有限。
|
|
254
|
+
|
|
255
|
+
**MySQL 不支持的特性**:
|
|
256
|
+
- ❌ 正则表达式约束(`pattern`)
|
|
257
|
+
- ❌ 数值范围约束(`minimum/maximum`)
|
|
258
|
+
- ❌ 枚举 CHECK 约束(导出为普通 `VARCHAR`)
|
|
259
|
+
- ❌ 字符串最小长度(`minLength`)
|
|
260
|
+
- ❌ 条件验证逻辑(`dsl.match()`, `dsl.if()`)
|
|
261
|
+
|
|
262
|
+
**详细说明**: 请阅读 [导出限制说明文档](export-limitations.md)
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
251
266
|
## 相关文档
|
|
252
267
|
|
|
253
268
|
- [数据库导出指南](export-guide.md)
|
|
254
269
|
- [MongoDB 导出器](mongodb-exporter.md)
|
|
255
270
|
- [PostgreSQL 导出器](postgresql-exporter.md)
|
|
256
271
|
- [TypeConverter](type-converter.md)
|
|
272
|
+
- [**导出限制说明**](export-limitations.md) ⚠️
|
|
257
273
|
|
|
@@ -281,10 +281,24 @@ exporter.generateIndex('users', 'metadata', { method: 'gin' });
|
|
|
281
281
|
|
|
282
282
|
---
|
|
283
283
|
|
|
284
|
+
## 导出限制
|
|
285
|
+
|
|
286
|
+
⚠️ **重要提示**: PostgreSQL 虽然支持 CHECK 约束,但仍有部分特性无法导出。
|
|
287
|
+
|
|
288
|
+
**PostgreSQL 不支持的特性**:
|
|
289
|
+
- ❌ 正则表达式约束(`pattern`)
|
|
290
|
+
- ❌ 嵌套对象约束(导出为 `JSONB`,内部约束丢失)
|
|
291
|
+
- ❌ 条件验证逻辑(`dsl.match()`, `dsl.if()`)
|
|
292
|
+
|
|
293
|
+
**详细说明**: 请阅读 [导出限制说明文档](export-limitations.md)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
284
297
|
## 相关文档
|
|
285
298
|
|
|
286
299
|
- [数据库导出指南](export-guide.md)
|
|
287
300
|
- [MongoDB 导出器](mongodb-exporter.md)
|
|
288
301
|
- [MySQL 导出器](mysql-exporter.md)
|
|
289
302
|
- [TypeConverter](type-converter.md)
|
|
303
|
+
- [**导出限制说明**](export-limitations.md) ⚠️
|
|
290
304
|
|