@meadmin/cli 1.3.7 → 1.3.8
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/dist/commanders/index.js +4 -2
- package/dist/commanders/update.d.ts +3 -0
- package/dist/commanders/update.js +132 -0
- package/dist/update/backup.d.ts +21 -0
- package/dist/update/backup.js +120 -0
- package/dist/update/merge.d.ts +7 -0
- package/dist/update/merge.js +432 -0
- package/dist/update/planner.d.ts +17 -0
- package/dist/update/planner.js +116 -0
- package/dist/update/rules.d.ts +12 -0
- package/dist/update/rules.js +55 -0
- package/dist/update/source.d.ts +10 -0
- package/dist/update/source.js +750 -0
- package/dist/update/sql.d.ts +12 -0
- package/dist/update/sql.js +589 -0
- package/dist/update/template.d.ts +20 -0
- package/dist/update/template.js +147 -0
- package/package.json +4 -4
- package/template/update.defaults.json +29 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type UpdateSql = {
|
|
2
|
+
content: string;
|
|
3
|
+
manual: string[];
|
|
4
|
+
tables: {
|
|
5
|
+
table: string;
|
|
6
|
+
rows: number;
|
|
7
|
+
keys: string[];
|
|
8
|
+
}[];
|
|
9
|
+
};
|
|
10
|
+
/** 仅生成待人工审阅的 SQL 文本;不连接数据库,不执行 SQL。 */
|
|
11
|
+
export declare function generateUpdateSql(source: string, version: string): UpdateSql;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
function fail(message) {
|
|
2
|
+
throw new Error(message);
|
|
3
|
+
}
|
|
4
|
+
function word(token, value) {
|
|
5
|
+
return token?.kind === 'word' && token.text.toUpperCase() === value;
|
|
6
|
+
}
|
|
7
|
+
function symbol(token, value) {
|
|
8
|
+
return token?.kind === 'symbol' && token.text === value;
|
|
9
|
+
}
|
|
10
|
+
// 先确定语句边界,再解析白名单语法;字面量与注释中的分隔符不参与切分。
|
|
11
|
+
function scan(source) {
|
|
12
|
+
const statements = [];
|
|
13
|
+
let tokens = [];
|
|
14
|
+
let depth = 0;
|
|
15
|
+
let i = 0;
|
|
16
|
+
const add = (kind, start) => {
|
|
17
|
+
tokens.push({ kind, text: source.slice(start, i), start, end: i });
|
|
18
|
+
};
|
|
19
|
+
const finish = () => {
|
|
20
|
+
if (tokens.length)
|
|
21
|
+
statements.push({ tokens, start: tokens[0].start });
|
|
22
|
+
tokens = [];
|
|
23
|
+
};
|
|
24
|
+
if (source.includes('\0'))
|
|
25
|
+
fail('源文件含 NUL 字符');
|
|
26
|
+
while (i < source.length) {
|
|
27
|
+
const start = i;
|
|
28
|
+
const c = source[i];
|
|
29
|
+
if (/\s/.test(c)) {
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
else if (source.startsWith('--', i)) {
|
|
33
|
+
while (i < source.length && !/[\r\n]/.test(source[i]))
|
|
34
|
+
i++;
|
|
35
|
+
}
|
|
36
|
+
else if (source.startsWith('/*', i)) {
|
|
37
|
+
let nesting = 1;
|
|
38
|
+
i += 2;
|
|
39
|
+
while (i < source.length && nesting) {
|
|
40
|
+
if (source.startsWith('/*', i)) {
|
|
41
|
+
nesting++;
|
|
42
|
+
i += 2;
|
|
43
|
+
}
|
|
44
|
+
else if (source.startsWith('*/', i)) {
|
|
45
|
+
nesting--;
|
|
46
|
+
i += 2;
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
i++;
|
|
50
|
+
}
|
|
51
|
+
if (nesting)
|
|
52
|
+
fail(`位置 ${start} 的块注释未闭合`);
|
|
53
|
+
}
|
|
54
|
+
else if (c === '"' || c === "'" || (/[eE]/.test(c) && source[i + 1] === "'")) {
|
|
55
|
+
const escaped = c !== '"' && c !== "'";
|
|
56
|
+
const quote = escaped ? "'" : c;
|
|
57
|
+
i += escaped ? 2 : 1;
|
|
58
|
+
let closed = false;
|
|
59
|
+
while (i < source.length) {
|
|
60
|
+
if (!escaped && quote === "'" && source[i] === '\\')
|
|
61
|
+
fail(`位置 ${start} 的普通字符串含反斜杠,无法确定会话转义规则`);
|
|
62
|
+
if (escaped && source[i] === '\\') {
|
|
63
|
+
i += 2;
|
|
64
|
+
}
|
|
65
|
+
else if (source[i] === quote) {
|
|
66
|
+
i++;
|
|
67
|
+
if (source[i] === quote)
|
|
68
|
+
i++;
|
|
69
|
+
else {
|
|
70
|
+
closed = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
if (!closed)
|
|
78
|
+
fail(`位置 ${start} 的引号未闭合`);
|
|
79
|
+
add(quote === '"' ? 'identifier' : 'string', start);
|
|
80
|
+
}
|
|
81
|
+
else if (c === '$' && /^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/.test(source.slice(i))) {
|
|
82
|
+
const delimiter = /^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/.exec(source.slice(i))[0];
|
|
83
|
+
const end = source.indexOf(delimiter, i + delimiter.length);
|
|
84
|
+
if (end < 0)
|
|
85
|
+
fail(`位置 ${start} 的 dollar quoting 未闭合`);
|
|
86
|
+
i = end + delimiter.length;
|
|
87
|
+
add('string', start);
|
|
88
|
+
}
|
|
89
|
+
else if (/[A-Za-z_\u0080-\uffff]/.test(c)) {
|
|
90
|
+
i++;
|
|
91
|
+
while (i < source.length && /[A-Za-z_0-9$\u0080-\uffff]/.test(source[i]))
|
|
92
|
+
i++;
|
|
93
|
+
add('word', start);
|
|
94
|
+
}
|
|
95
|
+
else if (/[0-9]/.test(c) || (c === '.' && /[0-9]/.test(source[i + 1] ?? ''))) {
|
|
96
|
+
const number = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/.exec(source.slice(i))[0];
|
|
97
|
+
i += number.length;
|
|
98
|
+
add('number', start);
|
|
99
|
+
}
|
|
100
|
+
else if (c === ';') {
|
|
101
|
+
if (tokens.some((token, n) => word(token, 'BEGIN') && word(tokens[n + 1], 'ATOMIC')))
|
|
102
|
+
fail('不支持 BEGIN ATOMIC 函数体,整个源文件转人工');
|
|
103
|
+
if (depth)
|
|
104
|
+
fail(`位置 ${start} 的括号内出现语句分隔符`);
|
|
105
|
+
const copy = word(tokens[0], 'COPY') && tokens.some((token, n) => word(token, 'FROM') && word(tokens[n + 1], 'STDIN'));
|
|
106
|
+
finish();
|
|
107
|
+
i++;
|
|
108
|
+
if (copy) {
|
|
109
|
+
// COPY 的行数据不是 SQL,必须整体跳过,不能将其中的 INSERT 当作语句。
|
|
110
|
+
const headerEnd = /^[ \t]*(?:\r\n|\n|\r)/.exec(source.slice(i));
|
|
111
|
+
if (!headerEnd)
|
|
112
|
+
fail('COPY FROM STDIN 后缺少数据换行');
|
|
113
|
+
i += headerEnd[0].length;
|
|
114
|
+
const terminator = /^\\\.[ \t]*(?:\r\n|\n|\r|$)/m.exec(source.slice(i));
|
|
115
|
+
if (!terminator)
|
|
116
|
+
fail('COPY FROM STDIN 缺少 \\. 结束标记');
|
|
117
|
+
i += terminator.index + terminator[0].length;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
if (c === '\\')
|
|
122
|
+
fail(`位置 ${start} 含不支持的 psql 命令或反斜杠`);
|
|
123
|
+
if (c === '(')
|
|
124
|
+
depth++;
|
|
125
|
+
if (c === ')' && --depth < 0)
|
|
126
|
+
fail(`位置 ${start} 的右括号没有匹配`);
|
|
127
|
+
i += source.startsWith('::', i) ? 2 : 1;
|
|
128
|
+
add('symbol', start);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (depth)
|
|
132
|
+
fail('源文件括号未闭合');
|
|
133
|
+
finish();
|
|
134
|
+
return statements;
|
|
135
|
+
}
|
|
136
|
+
class Cursor {
|
|
137
|
+
tokens;
|
|
138
|
+
pos = 0;
|
|
139
|
+
constructor(tokens) {
|
|
140
|
+
this.tokens = tokens;
|
|
141
|
+
}
|
|
142
|
+
take(value) {
|
|
143
|
+
if (word(this.tokens[this.pos], value) || symbol(this.tokens[this.pos], value)) {
|
|
144
|
+
this.pos++;
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
expect(value) {
|
|
150
|
+
if (!this.take(value))
|
|
151
|
+
fail(`预期 ${value},语法不在支持范围`);
|
|
152
|
+
}
|
|
153
|
+
identifier() {
|
|
154
|
+
const token = this.tokens[this.pos++];
|
|
155
|
+
if (!token || (token.kind !== 'word' && token.kind !== 'identifier'))
|
|
156
|
+
fail('需要简单列名或表名');
|
|
157
|
+
const name = token.kind === 'identifier' ? token.text.slice(1, -1).replace(/""/g, '"') : token.text.toLowerCase();
|
|
158
|
+
if (!name || new TextEncoder().encode(name).length > 63)
|
|
159
|
+
fail('标识符为空或超过 PostgreSQL 默认 63 字节限制');
|
|
160
|
+
return name;
|
|
161
|
+
}
|
|
162
|
+
name() {
|
|
163
|
+
const parts = [this.identifier()];
|
|
164
|
+
if (this.take('.'))
|
|
165
|
+
parts.push(this.identifier());
|
|
166
|
+
if (symbol(this.tokens[this.pos], '.'))
|
|
167
|
+
fail('不支持超过 schema.table 的名称');
|
|
168
|
+
return parts;
|
|
169
|
+
}
|
|
170
|
+
list() {
|
|
171
|
+
this.expect('(');
|
|
172
|
+
const names = [this.identifier()];
|
|
173
|
+
while (this.take(','))
|
|
174
|
+
names.push(this.identifier());
|
|
175
|
+
this.expect(')');
|
|
176
|
+
if (new Set(names).size !== names.length)
|
|
177
|
+
fail('键或列列表包含重复列');
|
|
178
|
+
return names;
|
|
179
|
+
}
|
|
180
|
+
end() {
|
|
181
|
+
if (this.pos !== this.tokens.length)
|
|
182
|
+
fail('包含复杂索引、约束选项或额外子语句');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function quote(name) {
|
|
186
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
187
|
+
}
|
|
188
|
+
function sqlName(parts) {
|
|
189
|
+
return parts.map(quote).join('.');
|
|
190
|
+
}
|
|
191
|
+
function label(parts) {
|
|
192
|
+
return parts.map((part) => (/^[a-z_][a-z_0-9]*$/.test(part) ? part : quote(part))).join('.');
|
|
193
|
+
}
|
|
194
|
+
function tableId(parts) {
|
|
195
|
+
return JSON.stringify(parts);
|
|
196
|
+
}
|
|
197
|
+
function groups(tokens) {
|
|
198
|
+
const result = [];
|
|
199
|
+
let start = 0;
|
|
200
|
+
let depth = 0;
|
|
201
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
202
|
+
if (symbol(tokens[i], '('))
|
|
203
|
+
depth++;
|
|
204
|
+
if (symbol(tokens[i], ')'))
|
|
205
|
+
depth--;
|
|
206
|
+
if (symbol(tokens[i], ',') && depth === 0) {
|
|
207
|
+
result.push(tokens.slice(start, i));
|
|
208
|
+
start = i + 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
result.push(tokens.slice(start));
|
|
212
|
+
if (result.some((group) => !group.length))
|
|
213
|
+
fail('列表中存在空项');
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
function parenthesized(cursor) {
|
|
217
|
+
cursor.expect('(');
|
|
218
|
+
const start = cursor.pos;
|
|
219
|
+
let depth = 1;
|
|
220
|
+
while (cursor.pos < cursor.tokens.length) {
|
|
221
|
+
const token = cursor.tokens[cursor.pos++];
|
|
222
|
+
if (symbol(token, '('))
|
|
223
|
+
depth++;
|
|
224
|
+
if (symbol(token, ')') && --depth === 0)
|
|
225
|
+
return cursor.tokens.slice(start, cursor.pos - 1);
|
|
226
|
+
}
|
|
227
|
+
return fail('括号未闭合');
|
|
228
|
+
}
|
|
229
|
+
// 只允许内建标量类型,避免自定义类型转换间接调用函数。
|
|
230
|
+
function scalarType(cursor) {
|
|
231
|
+
if (word(cursor.tokens[cursor.pos], 'PG_CATALOG') && symbol(cursor.tokens[cursor.pos + 1], '.'))
|
|
232
|
+
cursor.pos += 2;
|
|
233
|
+
const token = cursor.tokens[cursor.pos++];
|
|
234
|
+
if (token?.kind !== 'word')
|
|
235
|
+
fail('不支持自定义或带引号的类型');
|
|
236
|
+
const type = token.text.toLowerCase();
|
|
237
|
+
const simple = new Set(['text', 'varchar', 'char', 'bpchar', 'smallint', 'integer', 'bigint', 'int', 'int2', 'int4', 'int8', 'numeric', 'decimal', 'real', 'float4', 'float8', 'boolean', 'bool', 'date', 'time', 'timetz', 'timestamp', 'timestamptz', 'json', 'jsonb', 'uuid', 'bytea', 'serial', 'bigserial', 'smallserial']);
|
|
238
|
+
if (type === 'character')
|
|
239
|
+
cursor.take('VARYING');
|
|
240
|
+
else if (type === 'double')
|
|
241
|
+
cursor.expect('PRECISION');
|
|
242
|
+
else if (!simple.has(type))
|
|
243
|
+
fail(`不支持类型 ${type}`);
|
|
244
|
+
if (symbol(cursor.tokens[cursor.pos], '(')) {
|
|
245
|
+
const modifiers = groups(parenthesized(cursor));
|
|
246
|
+
if (modifiers.length > 2 || modifiers.some((group) => group.length !== 1 || group[0].kind !== 'number' || !/^\d+$/.test(group[0].text)))
|
|
247
|
+
fail('类型参数必须是简单整数');
|
|
248
|
+
}
|
|
249
|
+
if (type === 'timestamp' || type === 'time') {
|
|
250
|
+
if (cursor.take('WITH') || cursor.take('WITHOUT')) {
|
|
251
|
+
cursor.expect('TIME');
|
|
252
|
+
cursor.expect('ZONE');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function literal(cursor) {
|
|
257
|
+
const signed = cursor.take('+') || cursor.take('-');
|
|
258
|
+
const token = cursor.tokens[cursor.pos++];
|
|
259
|
+
if (!token)
|
|
260
|
+
fail('VALUES 中缺少字面量');
|
|
261
|
+
const isNull = word(token, 'NULL');
|
|
262
|
+
if (signed ? token.kind !== 'number' : token.kind !== 'number' && token.kind !== 'string' && !isNull && !word(token, 'TRUE') && !word(token, 'FALSE')) {
|
|
263
|
+
fail('VALUES 仅允许标量字面量,拒绝函数、DEFAULT、表达式和危险子语句');
|
|
264
|
+
}
|
|
265
|
+
if (cursor.take('::')) {
|
|
266
|
+
const start = cursor.pos;
|
|
267
|
+
scalarType(cursor);
|
|
268
|
+
if (cursor.tokens.slice(start, cursor.pos).some((item) => item.kind === 'word' && /^(?:smallserial|serial|bigserial)$/i.test(item.text)))
|
|
269
|
+
fail('VALUES 不支持 serial 类型转换');
|
|
270
|
+
}
|
|
271
|
+
return isNull;
|
|
272
|
+
}
|
|
273
|
+
function constraint(cursor) {
|
|
274
|
+
if (cursor.take('CONSTRAINT'))
|
|
275
|
+
cursor.identifier();
|
|
276
|
+
const primary = cursor.take('PRIMARY');
|
|
277
|
+
if (primary)
|
|
278
|
+
cursor.expect('KEY');
|
|
279
|
+
else
|
|
280
|
+
cursor.expect('UNIQUE');
|
|
281
|
+
const columns = cursor.list();
|
|
282
|
+
if (cursor.take('NOT'))
|
|
283
|
+
cursor.expect('DEFERRABLE');
|
|
284
|
+
cursor.end();
|
|
285
|
+
return { columns, primary };
|
|
286
|
+
}
|
|
287
|
+
function column(tokens, table) {
|
|
288
|
+
const cursor = new Cursor(tokens);
|
|
289
|
+
const name = cursor.identifier();
|
|
290
|
+
if (table.columns.has(name))
|
|
291
|
+
fail(`重复列 ${quote(name)}`);
|
|
292
|
+
scalarType(cursor);
|
|
293
|
+
let notNull = false;
|
|
294
|
+
while (cursor.pos < tokens.length) {
|
|
295
|
+
if (cursor.take('CONSTRAINT'))
|
|
296
|
+
cursor.identifier();
|
|
297
|
+
if (cursor.take('NOT')) {
|
|
298
|
+
if (cursor.take('NULL'))
|
|
299
|
+
notNull = true;
|
|
300
|
+
else
|
|
301
|
+
cursor.expect('DEFERRABLE');
|
|
302
|
+
}
|
|
303
|
+
else if (cursor.take('NULL')) {
|
|
304
|
+
if (notNull)
|
|
305
|
+
fail('列同时声明 NULL 和 NOT NULL');
|
|
306
|
+
}
|
|
307
|
+
else if (cursor.take('PRIMARY')) {
|
|
308
|
+
cursor.expect('KEY');
|
|
309
|
+
table.keys.push({ columns: [name], primary: true });
|
|
310
|
+
}
|
|
311
|
+
else if (cursor.take('UNIQUE')) {
|
|
312
|
+
table.keys.push({ columns: [name], primary: false });
|
|
313
|
+
}
|
|
314
|
+
else if (cursor.take('DEFAULT')) {
|
|
315
|
+
literal(cursor);
|
|
316
|
+
}
|
|
317
|
+
else if (cursor.take('CHECK')) {
|
|
318
|
+
parenthesized(cursor);
|
|
319
|
+
}
|
|
320
|
+
else
|
|
321
|
+
fail(`列 ${quote(name)} 存在不支持的约束、默认值或生成表达式`);
|
|
322
|
+
}
|
|
323
|
+
table.columns.set(name, notNull);
|
|
324
|
+
}
|
|
325
|
+
function createTable(cursor, table) {
|
|
326
|
+
const definitions = groups(parenthesized(cursor));
|
|
327
|
+
cursor.end();
|
|
328
|
+
for (const definition of definitions) {
|
|
329
|
+
const item = new Cursor(definition);
|
|
330
|
+
if (item.take('CONSTRAINT'))
|
|
331
|
+
item.identifier();
|
|
332
|
+
const first = item.tokens[item.pos];
|
|
333
|
+
if (word(first, 'PRIMARY') || word(first, 'UNIQUE'))
|
|
334
|
+
table.keys.push(constraint(item));
|
|
335
|
+
else if (word(first, 'CHECK') || word(first, 'FOREIGN')) {
|
|
336
|
+
// CHECK / FOREIGN KEY 不提供判重键,也不进入生成结果。
|
|
337
|
+
}
|
|
338
|
+
else if (word(first, 'EXCLUDE'))
|
|
339
|
+
fail('不支持 EXCLUDE 约束');
|
|
340
|
+
else
|
|
341
|
+
column(definition, table);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function alterTable(cursor, table) {
|
|
345
|
+
for (const action of groups(cursor.tokens.slice(cursor.pos))) {
|
|
346
|
+
const item = new Cursor(action);
|
|
347
|
+
if (item.take('ADD')) {
|
|
348
|
+
table.keys.push(constraint(item));
|
|
349
|
+
}
|
|
350
|
+
else if (item.take('ALTER')) {
|
|
351
|
+
item.expect('COLUMN');
|
|
352
|
+
const name = item.identifier();
|
|
353
|
+
item.expect('SET');
|
|
354
|
+
item.expect('NOT');
|
|
355
|
+
item.expect('NULL');
|
|
356
|
+
item.end();
|
|
357
|
+
if (!table.columns.has(name))
|
|
358
|
+
fail(`未知列 ${quote(name)}`);
|
|
359
|
+
table.columns.set(name, true);
|
|
360
|
+
}
|
|
361
|
+
else
|
|
362
|
+
fail('ALTER TABLE 仅支持添加简单 PRIMARY KEY / UNIQUE 或设置 NOT NULL');
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function indexKey(cursor) {
|
|
366
|
+
if (cursor.take('USING'))
|
|
367
|
+
cursor.expect('BTREE');
|
|
368
|
+
const columns = cursor.list();
|
|
369
|
+
cursor.end();
|
|
370
|
+
return { columns, primary: false };
|
|
371
|
+
}
|
|
372
|
+
function chooseKey(table, unknownIndexProblems) {
|
|
373
|
+
if (table.problems.length)
|
|
374
|
+
fail(`表定义无法安全判重:${table.problems.join(';')}`);
|
|
375
|
+
const primaryKeys = table.keys.filter((key) => key.primary);
|
|
376
|
+
if (primaryKeys.length > 1)
|
|
377
|
+
fail('存在多个 PRIMARY KEY 定义,无法安全判重');
|
|
378
|
+
if (primaryKeys.length) {
|
|
379
|
+
const primary = primaryKeys[0];
|
|
380
|
+
for (const name of primary.columns) {
|
|
381
|
+
if (!table.columns.has(name))
|
|
382
|
+
fail(`主键引用未知列 ${quote(name)}`);
|
|
383
|
+
}
|
|
384
|
+
// id 主键或复合主键确定后,不再用其他唯一键参与候选选择。
|
|
385
|
+
return primary.columns;
|
|
386
|
+
}
|
|
387
|
+
const indexProblems = [...table.indexProblems, ...unknownIndexProblems];
|
|
388
|
+
if (indexProblems.length)
|
|
389
|
+
fail(`无主键且唯一索引无法安全判重:${indexProblems.join(';')}`);
|
|
390
|
+
const candidates = new Map();
|
|
391
|
+
for (const key of table.keys) {
|
|
392
|
+
for (const name of key.columns) {
|
|
393
|
+
if (!table.columns.has(name))
|
|
394
|
+
fail(`判重键引用未知列 ${quote(name)}`);
|
|
395
|
+
if (!table.columns.get(name))
|
|
396
|
+
fail(`唯一键 ${quote(name)} 可为 NULL,无法可靠判重`);
|
|
397
|
+
}
|
|
398
|
+
// 同一列集合的重复索引不是不同候选键;保留首次声明的列顺序。
|
|
399
|
+
const id = JSON.stringify([...key.columns].sort());
|
|
400
|
+
if (!candidates.has(id))
|
|
401
|
+
candidates.set(id, key.columns);
|
|
402
|
+
}
|
|
403
|
+
if (!candidates.size)
|
|
404
|
+
fail('没有 PRIMARY KEY 或非 nullable 的简单唯一键,无法判重(不凭 id 列名推断)');
|
|
405
|
+
if (candidates.size !== 1)
|
|
406
|
+
fail('存在多个候选键,需人工选择冲突目标');
|
|
407
|
+
return [...candidates.values()][0];
|
|
408
|
+
}
|
|
409
|
+
function parseInsert(cursor, table, keys, source) {
|
|
410
|
+
const columns = cursor.list();
|
|
411
|
+
if (columns.some((name) => !table.columns.has(name)))
|
|
412
|
+
fail('INSERT 包含表定义中不存在的列');
|
|
413
|
+
const positions = keys.map((key) => columns.indexOf(key));
|
|
414
|
+
if (positions.includes(-1))
|
|
415
|
+
fail('INSERT 缺少判重键列');
|
|
416
|
+
cursor.expect('VALUES');
|
|
417
|
+
const start = cursor.tokens[cursor.pos]?.start;
|
|
418
|
+
let end;
|
|
419
|
+
let rows = 0;
|
|
420
|
+
do {
|
|
421
|
+
const values = groups(parenthesized(cursor));
|
|
422
|
+
if (values.length !== columns.length)
|
|
423
|
+
fail('VALUES 值数量与 INSERT 列数量不一致');
|
|
424
|
+
const nulls = values.map((value) => {
|
|
425
|
+
const item = new Cursor(value);
|
|
426
|
+
const isNull = literal(item);
|
|
427
|
+
item.end();
|
|
428
|
+
return isNull;
|
|
429
|
+
});
|
|
430
|
+
if (positions.some((position) => nulls[position]))
|
|
431
|
+
fail('VALUES 判重键含 NULL,整条批量 INSERT 转人工');
|
|
432
|
+
rows++;
|
|
433
|
+
end = cursor.tokens[cursor.pos - 1].end;
|
|
434
|
+
} while (cursor.take(','));
|
|
435
|
+
cursor.end();
|
|
436
|
+
return {
|
|
437
|
+
sql: `INSERT INTO ${sqlName(table.parts)} (${columns.map(quote).join(', ')}) VALUES ${source.slice(start, end)}\nON CONFLICT (${keys.map(quote).join(', ')}) DO NOTHING;`,
|
|
438
|
+
rows,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
/** 仅生成待人工审阅的 SQL 文本;不连接数据库,不执行 SQL。 */
|
|
442
|
+
export function generateUpdateSql(source, version) {
|
|
443
|
+
const manual = [];
|
|
444
|
+
const output = [];
|
|
445
|
+
const summaries = new Map();
|
|
446
|
+
const tables = new Map();
|
|
447
|
+
const header = `-- 更新 SQL,版本 ${JSON.stringify(version).replace(/[\u2028\u2029]/g, ' ')}
|
|
448
|
+
-- 仅生成文本,不自动执行。请按以下顺序操作:
|
|
449
|
+
-- 1. 先备份数据库,再编译更新后的后端代码。
|
|
450
|
+
-- 2. 手动执行 pnpm exec meadmin sync '*' 同步表结构(默认读取 dist,alter:true)。
|
|
451
|
+
-- 3. 对照现有数据库谨慎比较 update.sql 和 manual 清单,确认后再手动执行 update.sql。
|
|
452
|
+
-- 判重优先使用 id 主键或其他主键(含复合主键),仅无主键时使用非空简单唯一键。
|
|
453
|
+
-- 仅跳过所选判重键的冲突;其他唯一冲突由数据库抛错,请人工核对处理。
|
|
454
|
+
-- 4. 数据更新后,手动修复菜单、组织、角色及其关联与权限。
|
|
455
|
+
BEGIN;
|
|
456
|
+
`;
|
|
457
|
+
const result = () => ({ content: `${header}${output.length ? '\n' + output.join('\n\n') + '\n' : ''}\nCOMMIT;\n`, manual, tables: [...summaries.values()] });
|
|
458
|
+
let statements;
|
|
459
|
+
try {
|
|
460
|
+
statements = scan(source);
|
|
461
|
+
}
|
|
462
|
+
catch (error) {
|
|
463
|
+
manual.push(`SQL 词法扫描失败:${error.message};整个源文件未生成 INSERT,请人工检查全部数据。`);
|
|
464
|
+
return result();
|
|
465
|
+
}
|
|
466
|
+
const report = (statement, message) => {
|
|
467
|
+
const line = source.slice(0, statement.start).split('\n').length;
|
|
468
|
+
manual.push(`第 ${line} 行:${message}`);
|
|
469
|
+
};
|
|
470
|
+
const definitions = new Set();
|
|
471
|
+
let unknownMetadata = false;
|
|
472
|
+
const unknownIndexProblems = [];
|
|
473
|
+
// 两遍收集元数据,支持 dump 在 INSERT 后声明约束和索引。
|
|
474
|
+
for (const statement of statements) {
|
|
475
|
+
const cursor = new Cursor(statement.tokens);
|
|
476
|
+
if (!cursor.take('CREATE') || !cursor.take('TABLE'))
|
|
477
|
+
continue;
|
|
478
|
+
definitions.add(statement);
|
|
479
|
+
let table;
|
|
480
|
+
try {
|
|
481
|
+
if (word(cursor.tokens[cursor.pos], 'IF'))
|
|
482
|
+
fail('不支持 CREATE TABLE IF NOT EXISTS,定义可能有歧义');
|
|
483
|
+
const parts = cursor.name();
|
|
484
|
+
const id = tableId(parts);
|
|
485
|
+
table = tables.get(id);
|
|
486
|
+
if (table)
|
|
487
|
+
fail('同名 CREATE TABLE 重复,定义有歧义');
|
|
488
|
+
table = { parts, columns: new Map(), keys: [], problems: [], indexProblems: [] };
|
|
489
|
+
tables.set(id, table);
|
|
490
|
+
createTable(cursor, table);
|
|
491
|
+
}
|
|
492
|
+
catch (error) {
|
|
493
|
+
const message = error.message;
|
|
494
|
+
if (table)
|
|
495
|
+
table.problems.push(message);
|
|
496
|
+
else
|
|
497
|
+
unknownMetadata = true;
|
|
498
|
+
report(statement, `${table ? label(table.parts) + ':' : ''}CREATE TABLE 转人工:${message}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
let unqualifiedUnsafe = false;
|
|
502
|
+
for (const statement of statements) {
|
|
503
|
+
if (definitions.has(statement))
|
|
504
|
+
continue;
|
|
505
|
+
const cursor = new Cursor(statement.tokens);
|
|
506
|
+
const alteration = word(cursor.tokens[0], 'ALTER') && word(cursor.tokens[1], 'TABLE');
|
|
507
|
+
const uniqueIndex = word(cursor.tokens[0], 'CREATE') && word(cursor.tokens[1], 'UNIQUE') && word(cursor.tokens[2], 'INDEX');
|
|
508
|
+
if (!alteration && !uniqueIndex)
|
|
509
|
+
continue;
|
|
510
|
+
definitions.add(statement);
|
|
511
|
+
let table;
|
|
512
|
+
try {
|
|
513
|
+
cursor.pos = alteration ? 2 : 3;
|
|
514
|
+
if (alteration)
|
|
515
|
+
cursor.take('ONLY');
|
|
516
|
+
else {
|
|
517
|
+
cursor.identifier();
|
|
518
|
+
cursor.expect('ON');
|
|
519
|
+
}
|
|
520
|
+
const parts = cursor.name();
|
|
521
|
+
table = tables.get(tableId(parts));
|
|
522
|
+
if (!table)
|
|
523
|
+
fail(`找不到 ${label(parts)} 的 CREATE TABLE`);
|
|
524
|
+
if (alteration)
|
|
525
|
+
alterTable(cursor, table);
|
|
526
|
+
else
|
|
527
|
+
table.keys.push(indexKey(cursor));
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
const message = error.message;
|
|
531
|
+
if (uniqueIndex) {
|
|
532
|
+
if (table)
|
|
533
|
+
table.indexProblems.push(message);
|
|
534
|
+
else
|
|
535
|
+
unknownIndexProblems.push(`无法定位的唯一索引:${message}`);
|
|
536
|
+
report(statement, `${table ? label(table.parts) + ':' : ''}唯一索引解析转人工:${message};若表有有效主键,仍可按主键生成 INSERT,其他唯一冲突由数据库抛错;无主键时暂停生成。`);
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
if (table)
|
|
540
|
+
table.problems.push(message);
|
|
541
|
+
else
|
|
542
|
+
unknownMetadata = true;
|
|
543
|
+
report(statement, `${table ? label(table.parts) + ':' : ''}键定义转人工:${message}`);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
// 不猜测 search_path,也不把不同 schema 的同名表合并。
|
|
548
|
+
for (const statement of statements) {
|
|
549
|
+
if (word(statement.tokens[0], 'SET') || word(statement.tokens[0], 'RESET') || (word(statement.tokens[0], 'SELECT') && statement.tokens.some((token) => word(token, 'SET_CONFIG'))))
|
|
550
|
+
unqualifiedUnsafe = true;
|
|
551
|
+
}
|
|
552
|
+
for (const statement of statements) {
|
|
553
|
+
if (definitions.has(statement))
|
|
554
|
+
continue;
|
|
555
|
+
const cursor = new Cursor(statement.tokens);
|
|
556
|
+
if (!cursor.take('INSERT')) {
|
|
557
|
+
if (word(statement.tokens[0], 'COMMENT') && word(statement.tokens[1], 'ON'))
|
|
558
|
+
continue;
|
|
559
|
+
if (statement.tokens.length === 1 && (word(statement.tokens[0], 'BEGIN') || word(statement.tokens[0], 'COMMIT')))
|
|
560
|
+
continue;
|
|
561
|
+
report(statement, `已移除非 INSERT 语句 ${statement.tokens[0].text.toUpperCase()},需人工检查(含 COPY / INSERT SELECT / 嵌套执行的内容不会提取)。`);
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
let parts;
|
|
565
|
+
try {
|
|
566
|
+
cursor.expect('INTO');
|
|
567
|
+
parts = cursor.name();
|
|
568
|
+
if (unknownMetadata)
|
|
569
|
+
fail('存在无法定位的键定义,所有 INSERT 暂停生成');
|
|
570
|
+
if (unqualifiedUnsafe && parts.length === 1)
|
|
571
|
+
fail('存在会话设置,未限定 schema 的表无法安全解析');
|
|
572
|
+
const table = tables.get(tableId(parts));
|
|
573
|
+
if (!table)
|
|
574
|
+
fail('找不到完全匹配(包括 schema)的 CREATE TABLE');
|
|
575
|
+
const keys = chooseKey(table, unknownIndexProblems);
|
|
576
|
+
const insert = parseInsert(cursor, table, keys, source);
|
|
577
|
+
output.push(insert.sql);
|
|
578
|
+
const id = tableId(parts);
|
|
579
|
+
const summary = summaries.get(id) ?? { table: label(parts), rows: 0, keys: [...keys] };
|
|
580
|
+
summary.rows += insert.rows;
|
|
581
|
+
summaries.set(id, summary);
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
report(statement, `${parts ? label(parts) + ':' : ''}整条 INSERT 转人工:${error.message}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return result();
|
|
588
|
+
}
|
|
589
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3FsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3VwZGF0ZS9zcWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBdUJBLFNBQVMsSUFBSSxDQUFDLE9BQWU7SUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQsU0FBUyxJQUFJLENBQUMsS0FBd0IsRUFBRSxLQUFhO0lBQ25ELE9BQU8sS0FBSyxFQUFFLElBQUksS0FBSyxNQUFNLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxLQUFLLENBQUM7QUFDdEUsQ0FBQztBQUVELFNBQVMsTUFBTSxDQUFDLEtBQXdCLEVBQUUsS0FBYTtJQUNyRCxPQUFPLEtBQUssRUFBRSxJQUFJLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxDQUFDO0FBQzFELENBQUM7QUFFRCxxQ0FBcUM7QUFDckMsU0FBUyxJQUFJLENBQUMsTUFBYztJQUMxQixNQUFNLFVBQVUsR0FBZ0IsRUFBRSxDQUFDO0lBQ25DLElBQUksTUFBTSxHQUFZLEVBQUUsQ0FBQztJQUN6QixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixNQUFNLEdBQUcsR0FBRyxDQUFDLElBQW1CLEVBQUUsS0FBYSxFQUFFLEVBQUU7UUFDakQsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLENBQUMsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLEdBQUcsRUFBRTtRQUNsQixJQUFJLE1BQU0sQ0FBQyxNQUFNO1lBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFL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Q0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsTUFBYztJQUM3QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMxQyxJQUFJLENBQUMsS0FBSztRQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNsQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ25DLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3RKLElBQUksQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBQ3pCLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNuQixJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sSUFBSSxxQ0FBcUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxD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
|