init
This commit is contained in:
parent
55ff56a1a7
commit
8bf5813876
152
converter.js
152
converter.js
@ -217,35 +217,82 @@ class PG2DMConverter {
|
|||||||
*/
|
*/
|
||||||
removeEmptyPartition(sql) {
|
removeEmptyPartition(sql) {
|
||||||
let converted = sql;
|
let converted = sql;
|
||||||
|
let removedCount = 0;
|
||||||
|
|
||||||
// 移除空的PARTITION BY子句
|
// 1. 移除 PARTITION BY LIST (column) 后面没有具体分区的情况
|
||||||
// 格式1: )\nPARTITION BY (\n)\n;
|
// 格式: )\nPARTITION BY LIST (\n "column"\n)\n;
|
||||||
// 格式2: ) PARTITION BY ();
|
const listPattern = /\)\s*PARTITION\s+BY\s+LIST\s*\([^)]+\)\s*;/gi;
|
||||||
|
const listMatches = converted.match(listPattern);
|
||||||
|
if (listMatches) {
|
||||||
|
converted = converted.replace(listPattern, ');');
|
||||||
|
removedCount += listMatches.length;
|
||||||
|
this.log(`移除 ${listMatches.length} 个空的PARTITION BY LIST子句`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 移除 PARTITION BY RANGE (column) 后面没有具体分区的情况
|
||||||
|
const rangePattern = /\)\s*PARTITION\s+BY\s+RANGE\s*\([^)]+\)\s*;/gi;
|
||||||
|
const rangeMatches = converted.match(rangePattern);
|
||||||
|
if (rangeMatches) {
|
||||||
|
converted = converted.replace(rangePattern, ');');
|
||||||
|
removedCount += rangeMatches.length;
|
||||||
|
this.log(`移除 ${rangeMatches.length} 个空的PARTITION BY RANGE子句`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 移除 PARTITION BY HASH (column) 后面没有具体分区的情况
|
||||||
|
const hashPattern = /\)\s*PARTITION\s+BY\s+HASH\s*\([^)]+\)\s*;/gi;
|
||||||
|
const hashMatches = converted.match(hashPattern);
|
||||||
|
if (hashMatches) {
|
||||||
|
converted = converted.replace(hashPattern, ');');
|
||||||
|
removedCount += hashMatches.length;
|
||||||
|
this.log(`移除 ${hashMatches.length} 个空的PARTITION BY HASH子句`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 移除空括号的PARTITION BY
|
||||||
converted = converted.replace(/\)\s*PARTITION\s+BY\s+\([^)]*\)\s*;/gi, ');\n');
|
converted = converted.replace(/\)\s*PARTITION\s+BY\s+\([^)]*\)\s*;/gi, ');\n');
|
||||||
|
|
||||||
const matches = sql.match(/PARTITION\s+BY\s+\(/gi);
|
if (removedCount > 0) {
|
||||||
if (matches) {
|
this.log(`总共移除 ${removedCount} 个空的PARTITION BY子句`);
|
||||||
this.log(`移除 ${matches.length} 个空的PARTITION BY子句`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除索引注释(达梦不支持COMMENT ON INDEX)
|
* 移除所有COMMENT语句(达梦不支持COMMENT ON语法)
|
||||||
*/
|
*/
|
||||||
removeIndexComments(sql) {
|
removeIndexComments(sql) {
|
||||||
let converted = sql;
|
let converted = sql;
|
||||||
|
let totalRemoved = 0;
|
||||||
|
|
||||||
// 匹配并移除 COMMENT ON INDEX 语句
|
// 1. 移除 COMMENT ON COLUMN
|
||||||
// 格式: COMMENT ON INDEX "schema"."index_name" IS '注释内容';
|
const columnPattern = /COMMENT\s+ON\s+COLUMN\s+"[^"]+"\."[^"]+"\."[^"]+"\s+IS\s+'[^']*'\s*;/gi;
|
||||||
const commentPattern = /COMMENT\s+ON\s+INDEX\s+"[^"]+"\."[^"]+"\s+IS\s+'[^']*'\s*;/gi;
|
const columnMatches = sql.match(columnPattern);
|
||||||
|
if (columnMatches) {
|
||||||
|
converted = converted.replace(columnPattern, '');
|
||||||
|
totalRemoved += columnMatches.length;
|
||||||
|
this.log(`移除 ${columnMatches.length} 个列注释`);
|
||||||
|
}
|
||||||
|
|
||||||
const matches = sql.match(commentPattern);
|
// 2. 移除 COMMENT ON TABLE
|
||||||
if (matches) {
|
const tablePattern = /COMMENT\s+ON\s+TABLE\s+"[^"]+"\."[^"]+"\s+IS\s+'[^']*'\s*;/gi;
|
||||||
this.log(`移除 ${matches.length} 个索引注释(达梦不支持COMMENT ON INDEX语法)`);
|
const tableMatches = converted.match(tablePattern);
|
||||||
converted = converted.replace(commentPattern, '');
|
if (tableMatches) {
|
||||||
|
converted = converted.replace(tablePattern, '');
|
||||||
|
totalRemoved += tableMatches.length;
|
||||||
|
this.log(`移除 ${tableMatches.length} 个表注释`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 移除 COMMENT ON INDEX
|
||||||
|
const indexPattern = /COMMENT\s+ON\s+INDEX\s+"[^"]+"\."[^"]+"\s+IS\s+'[^']*'\s*;/gi;
|
||||||
|
const indexMatches = converted.match(indexPattern);
|
||||||
|
if (indexMatches) {
|
||||||
|
converted = converted.replace(indexPattern, '');
|
||||||
|
totalRemoved += indexMatches.length;
|
||||||
|
this.log(`移除 ${indexMatches.length} 个索引注释`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalRemoved > 0) {
|
||||||
|
this.log(`总共移除 ${totalRemoved} 个COMMENT语句(达梦不支持)`);
|
||||||
// 清理可能产生的多余空行
|
// 清理可能产生的多余空行
|
||||||
converted = converted.replace(/\n\n\n+/g, '\n\n');
|
converted = converted.replace(/\n\n\n+/g, '\n\n');
|
||||||
}
|
}
|
||||||
@ -253,6 +300,73 @@ class PG2DMConverter {
|
|||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除分区附加语句(达梦不支持ATTACH PARTITION)
|
||||||
|
*/
|
||||||
|
removeAttachPartition(sql) {
|
||||||
|
let converted = sql;
|
||||||
|
|
||||||
|
// 匹配 ALTER TABLE ... ATTACH PARTITION ... FOR VALUES ...;
|
||||||
|
const attachPattern = /ALTER\s+TABLE\s+"[^"]+"\."[^"]+"\s+ATTACH\s+PARTITION\s+"[^"]+"\."[^"]+"\s+FOR\s+VALUES[^;]*;/gi;
|
||||||
|
|
||||||
|
const matches = sql.match(attachPattern);
|
||||||
|
if (matches) {
|
||||||
|
this.log(`移除 ${matches.length} 个ATTACH PARTITION语句(达梦不支持)`);
|
||||||
|
converted = converted.replace(attachPattern, '');
|
||||||
|
|
||||||
|
// 清理多余空行
|
||||||
|
converted = converted.replace(/\n\n\n+/g, '\n\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除与主键约束同名的唯一索引
|
||||||
|
* PostgreSQL导出时会同时包含索引和约束,但在达梦中会冲突
|
||||||
|
*/
|
||||||
|
removeDuplicatePrimaryKeyIndexes(sql) {
|
||||||
|
let converted = sql;
|
||||||
|
let removedCount = 0;
|
||||||
|
|
||||||
|
// 1. 提取所有主键约束的名称
|
||||||
|
const pkConstraintPattern = /ADD\s+CONSTRAINT\s+"([^"]+)"\s+PRIMARY\s+KEY/gi;
|
||||||
|
const constraintNames = new Set();
|
||||||
|
|
||||||
|
let match;
|
||||||
|
while ((match = pkConstraintPattern.exec(sql)) !== null) {
|
||||||
|
constraintNames.add(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraintNames.size === 0) {
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 移除与这些约束同名的UNIQUE INDEX
|
||||||
|
constraintNames.forEach(constraintName => {
|
||||||
|
// 匹配: CREATE UNIQUE INDEX "constraint_name" ON ...;
|
||||||
|
const indexPattern = new RegExp(
|
||||||
|
`CREATE\\s+UNIQUE\\s+INDEX\\s+"${constraintName}"\\s+ON\\s+[^;]+;`,
|
||||||
|
'gi'
|
||||||
|
);
|
||||||
|
|
||||||
|
const indexMatches = converted.match(indexPattern);
|
||||||
|
if (indexMatches) {
|
||||||
|
converted = converted.replace(indexPattern, '');
|
||||||
|
removedCount += indexMatches.length;
|
||||||
|
this.log(`移除与主键约束同名的唯一索引: ${constraintName}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (removedCount > 0) {
|
||||||
|
this.log(`总共移除 ${removedCount} 个与主键同名的唯一索引`);
|
||||||
|
// 清理多余空行
|
||||||
|
converted = converted.replace(/\n\n\n+/g, '\n\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 简化索引语法
|
* 简化索引语法
|
||||||
*/
|
*/
|
||||||
@ -438,7 +552,15 @@ class PG2DMConverter {
|
|||||||
this.log('步骤11: 移除索引注释...');
|
this.log('步骤11: 移除索引注释...');
|
||||||
converted = this.removeIndexComments(converted);
|
converted = this.removeIndexComments(converted);
|
||||||
|
|
||||||
// 12. 添加转换说明
|
// 12. 移除分区附加语句(达梦不支持ATTACH PARTITION)
|
||||||
|
this.log('步骤12: 移除分区附加语句...');
|
||||||
|
converted = this.removeAttachPartition(converted);
|
||||||
|
|
||||||
|
// 13. 移除与主键约束同名的唯一索引(避免冲突)
|
||||||
|
this.log('步骤13: 移除与主键约束同名的唯一索引...');
|
||||||
|
converted = this.removeDuplicatePrimaryKeyIndexes(converted);
|
||||||
|
|
||||||
|
// 14. 添加转换说明
|
||||||
if (config.output.addConversionComment) {
|
if (config.output.addConversionComment) {
|
||||||
converted = this.addConversionHeader(converted, originalFile);
|
converted = this.addConversionHeader(converted, originalFile);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user