Compare commits
2 Commits
cb8b0428b4
...
62bc866606
| Author | SHA1 | Date |
|---|---|---|
|
|
62bc866606 | |
|
|
eee2f7c874 |
|
|
@ -81,16 +81,6 @@ class MySqlTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
makeUpSchema() {
|
makeUpSchema() {
|
||||||
for (const entity in this.schema) {
|
for (const entity in this.schema) {
|
||||||
const { attributes, indexes } = this.schema[entity];
|
const { attributes, indexes } = this.schema[entity];
|
||||||
// 非特殊索引自动添加 $$deleteAt$$ (by qcqcqc)
|
|
||||||
for (const index of indexes || []) {
|
|
||||||
if (index.config?.type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const indexAttrNames = index.attributes.map(attr => attr.name);
|
|
||||||
if (!indexAttrNames.includes('$$deleteAt$$')) {
|
|
||||||
index.attributes.push({ name: '$$deleteAt$$' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const geoIndexes = [];
|
const geoIndexes = [];
|
||||||
for (const attr in attributes) {
|
for (const attr in attributes) {
|
||||||
if (attributes[attr].type === 'geometry') {
|
if (attributes[attr].type === 'geometry') {
|
||||||
|
|
|
||||||
|
|
@ -171,16 +171,6 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
makeUpSchema() {
|
makeUpSchema() {
|
||||||
for (const entity in this.schema) {
|
for (const entity in this.schema) {
|
||||||
const { attributes, indexes } = this.schema[entity];
|
const { attributes, indexes } = this.schema[entity];
|
||||||
// 非特殊索引自动添加 $$deleteAt$$
|
|
||||||
for (const index of indexes || []) {
|
|
||||||
if (index.config?.type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const indexAttrNames = index.attributes.map(attr => attr.name);
|
|
||||||
if (!indexAttrNames.includes('$$deleteAt$$')) {
|
|
||||||
index.attributes.push({ name: '$$deleteAt$$' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const geoIndexes = [];
|
const geoIndexes = [];
|
||||||
for (const attr in attributes) {
|
for (const attr in attributes) {
|
||||||
if (attributes[attr].type === 'geometry') {
|
if (attributes[attr].type === 'geometry') {
|
||||||
|
|
@ -1842,7 +1832,7 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
'double precision': 'double precision',
|
'double precision': 'double precision',
|
||||||
'boolean': 'boolean',
|
'boolean': 'boolean',
|
||||||
'text': 'text',
|
'text': 'text',
|
||||||
'jsonb': 'object', // 框架使用 jsonb 存储 object/array
|
'jsonb': 'object',
|
||||||
'json': 'object',
|
'json': 'object',
|
||||||
'bytea': 'bytea',
|
'bytea': 'bytea',
|
||||||
'character varying': 'varchar',
|
'character varying': 'varchar',
|
||||||
|
|
@ -1852,6 +1842,7 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
'date': 'date',
|
'date': 'date',
|
||||||
'uuid': 'uuid',
|
'uuid': 'uuid',
|
||||||
'geometry': 'geometry',
|
'geometry': 'geometry',
|
||||||
|
'numeric': 'decimal',
|
||||||
};
|
};
|
||||||
const mappedType = typeMap[type];
|
const mappedType = typeMap[type];
|
||||||
if (mappedType) {
|
if (mappedType) {
|
||||||
|
|
@ -1899,7 +1890,6 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
let attr;
|
let attr;
|
||||||
// 处理用户定义类型(枚举)
|
// 处理用户定义类型(枚举)
|
||||||
if (dataType === 'USER-DEFINED') {
|
if (dataType === 'USER-DEFINED') {
|
||||||
// 查询枚举值
|
|
||||||
const enumSql = `
|
const enumSql = `
|
||||||
SELECT e.enumlabel
|
SELECT e.enumlabel
|
||||||
FROM pg_type t
|
FROM pg_type t
|
||||||
|
|
@ -1917,23 +1907,42 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
else {
|
else {
|
||||||
// 构建完整的类型字符串
|
// 构建完整的类型字符串
|
||||||
let fullType = dataType;
|
let fullType = dataType;
|
||||||
if (maxLength) {
|
const integerTypes = ['bigint', 'integer', 'smallint', 'serial', 'bigserial', 'smallserial'];
|
||||||
|
if (maxLength && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${maxLength})`;
|
fullType = `${dataType}(${maxLength})`;
|
||||||
}
|
}
|
||||||
else if (precision !== null && scale !== null) {
|
else if (precision !== null && scale !== null && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${precision},${scale})`;
|
fullType = `${dataType}(${precision},${scale})`;
|
||||||
}
|
}
|
||||||
else if (precision !== null) {
|
else if (precision !== null && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${precision})`;
|
fullType = `${dataType}(${precision})`;
|
||||||
}
|
}
|
||||||
attr = this.reTranslateToAttribute(fullType);
|
attr = this.reTranslateToAttribute(fullType);
|
||||||
}
|
}
|
||||||
// 处理约束
|
// ========== 类型还原逻辑 ==========
|
||||||
attr.notNull = isNullable === 'NO';
|
// 框架将某些语义类型存储为 bigint,需要根据列名还原
|
||||||
// 处理默认值(简化处理,复杂的默认值可能需要更精细的解析)
|
if (attr.type === 'bigint') {
|
||||||
|
// 1. 检查是否是序列列
|
||||||
|
if (colName === '$$seq$$' || (defaultValue && defaultValue.includes('nextval'))) {
|
||||||
|
attr.type = 'sequence';
|
||||||
|
attr.sequenceStart = 10000; // 默认起始值
|
||||||
|
}
|
||||||
|
// 2. 检查是否是时间戳列
|
||||||
|
else if (['$$createAt$$', '$$updateAt$$', '$$deleteAt$$'].includes(colName)) {
|
||||||
|
attr.type = 'datetime';
|
||||||
|
}
|
||||||
|
// 3. 检查其他可能的时间类型列(根据命名约定)
|
||||||
|
else if (colName.endsWith('At') || colName.endsWith('Time')) {
|
||||||
|
// 可选:根据业务约定判断是否应该是 datetime
|
||||||
|
// 这里保守处理,只转换框架标准字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理约束 - 只在为 true 时添加
|
||||||
|
if (isNullable === 'NO') {
|
||||||
|
attr.notNull = true;
|
||||||
|
}
|
||||||
|
// 处理默认值
|
||||||
if (defaultValue && !defaultValue.includes('nextval')) {
|
if (defaultValue && !defaultValue.includes('nextval')) {
|
||||||
// 跳过序列默认值
|
|
||||||
// 简单处理:移除类型转换
|
|
||||||
let cleanDefault = defaultValue.replace(/::[a-z]+/gi, '').replace(/'/g, '');
|
let cleanDefault = defaultValue.replace(/::[a-z]+/gi, '').replace(/'/g, '');
|
||||||
if (cleanDefault === 'true') {
|
if (cleanDefault === 'true') {
|
||||||
attr.default = true;
|
attr.default = true;
|
||||||
|
|
@ -1944,13 +1953,26 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
else if (!isNaN(Number(cleanDefault))) {
|
else if (!isNaN(Number(cleanDefault))) {
|
||||||
attr.default = Number(cleanDefault);
|
attr.default = Number(cleanDefault);
|
||||||
}
|
}
|
||||||
else {
|
else if (cleanDefault !== '') {
|
||||||
attr.default = cleanDefault;
|
attr.default = cleanDefault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 检查是否是序列列(IDENTITY)
|
// 检查唯一约束
|
||||||
if (colName === '$$seq$$' || (defaultValue && defaultValue.includes('nextval'))) {
|
const uniqueSql = `
|
||||||
attr.sequenceStart = 10000; // 默认起始值
|
SELECT COUNT(*) as cnt
|
||||||
|
FROM pg_index ix
|
||||||
|
JOIN pg_class t ON t.oid = ix.indrelid
|
||||||
|
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
|
||||||
|
WHERE t.relname = '${tableName}'
|
||||||
|
AND a.attname = '${colName}'
|
||||||
|
AND ix.indisunique = true
|
||||||
|
AND NOT ix.indisprimary
|
||||||
|
AND array_length(ix.indkey, 1) = 1;
|
||||||
|
`;
|
||||||
|
const [uniqueResult] = await execFn(uniqueSql);
|
||||||
|
const uniqueCount = parseInt(uniqueResult[0]?.cnt || '0', 10);
|
||||||
|
if (uniqueCount > 0) {
|
||||||
|
attr.unique = true;
|
||||||
}
|
}
|
||||||
attributes[colName] = attr;
|
attributes[colName] = attr;
|
||||||
}
|
}
|
||||||
|
|
@ -2085,15 +2107,13 @@ class PostgreSQLTranslator extends sqlTranslator_1.SqlTranslator {
|
||||||
let sql = `"${attr}" `;
|
let sql = `"${attr}" `;
|
||||||
const { type, params, default: defaultValue, unique, notNull, sequenceStart, enumeration, } = attrDef;
|
const { type, params, default: defaultValue, unique, notNull, sequenceStart, enumeration, } = attrDef;
|
||||||
// 处理序列类型(IDENTITY)
|
// 处理序列类型(IDENTITY)
|
||||||
if (typeof sequenceStart === 'number') {
|
if (type === 'sequence' || (typeof sequenceStart === 'number')) {
|
||||||
sql += `bigint GENERATED BY DEFAULT AS IDENTITY (START WITH ${sequenceStart}) UNIQUE`;
|
sql += `bigint GENERATED BY DEFAULT AS IDENTITY (START WITH ${sequenceStart || 10000}) UNIQUE`;
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
// 处理枚举类型
|
// 处理枚举类型
|
||||||
if (type === 'enum') {
|
if (type === 'enum') {
|
||||||
(0, assert_1.default)(enumeration, 'Enum type requires enumeration values');
|
(0, assert_1.default)(enumeration, 'Enum type requires enumeration values');
|
||||||
// 注意:这里返回的是占位符,实际的枚举类型名在 translateCreateEntity 中确定
|
|
||||||
// 为了比较一致性,我们使用枚举值的字符串表示
|
|
||||||
sql += `enum(${enumeration.map(v => `'${v}'`).join(',')})`;
|
sql += `enum(${enumeration.map(v => `'${v}'`).join(',')})`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -109,16 +109,6 @@ export class MySqlTranslator<ED extends EntityDict & BaseEntityDict> extends Sql
|
||||||
private makeUpSchema() {
|
private makeUpSchema() {
|
||||||
for (const entity in this.schema) {
|
for (const entity in this.schema) {
|
||||||
const { attributes, indexes } = this.schema[entity];
|
const { attributes, indexes } = this.schema[entity];
|
||||||
// 非特殊索引自动添加 $$deleteAt$$ (by qcqcqc)
|
|
||||||
for (const index of indexes || []) {
|
|
||||||
if (index.config?.type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const indexAttrNames = index.attributes.map(attr => attr.name);
|
|
||||||
if (!indexAttrNames.includes('$$deleteAt$$')) {
|
|
||||||
index.attributes.push({ name: '$$deleteAt$$' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const geoIndexes: Index<ED[keyof ED]['OpSchema']>[] = [];
|
const geoIndexes: Index<ED[keyof ED]['OpSchema']>[] = [];
|
||||||
for (const attr in attributes) {
|
for (const attr in attributes) {
|
||||||
if (attributes[attr].type === 'geometry') {
|
if (attributes[attr].type === 'geometry') {
|
||||||
|
|
|
||||||
|
|
@ -210,16 +210,6 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
private makeUpSchema() {
|
private makeUpSchema() {
|
||||||
for (const entity in this.schema) {
|
for (const entity in this.schema) {
|
||||||
const { attributes, indexes } = this.schema[entity];
|
const { attributes, indexes } = this.schema[entity];
|
||||||
// 非特殊索引自动添加 $$deleteAt$$
|
|
||||||
for (const index of indexes || []) {
|
|
||||||
if (index.config?.type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const indexAttrNames = index.attributes.map(attr => attr.name);
|
|
||||||
if (!indexAttrNames.includes('$$deleteAt$$')) {
|
|
||||||
index.attributes.push({ name: '$$deleteAt$$' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const geoIndexes: Index<ED[keyof ED]['OpSchema']>[] = [];
|
const geoIndexes: Index<ED[keyof ED]['OpSchema']>[] = [];
|
||||||
for (const attr in attributes) {
|
for (const attr in attributes) {
|
||||||
if (attributes[attr].type === 'geometry') {
|
if (attributes[attr].type === 'geometry') {
|
||||||
|
|
@ -2119,7 +2109,7 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
'double precision': 'double precision',
|
'double precision': 'double precision',
|
||||||
'boolean': 'boolean',
|
'boolean': 'boolean',
|
||||||
'text': 'text',
|
'text': 'text',
|
||||||
'jsonb': 'object', // 框架使用 jsonb 存储 object/array
|
'jsonb': 'object',
|
||||||
'json': 'object',
|
'json': 'object',
|
||||||
'bytea': 'bytea',
|
'bytea': 'bytea',
|
||||||
'character varying': 'varchar',
|
'character varying': 'varchar',
|
||||||
|
|
@ -2129,6 +2119,7 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
'date': 'date',
|
'date': 'date',
|
||||||
'uuid': 'uuid',
|
'uuid': 'uuid',
|
||||||
'geometry': 'geometry',
|
'geometry': 'geometry',
|
||||||
|
'numeric': 'decimal',
|
||||||
};
|
};
|
||||||
|
|
||||||
const mappedType = typeMap[type];
|
const mappedType = typeMap[type];
|
||||||
|
|
@ -2179,6 +2170,7 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
|
|
||||||
const attributes: Attributes<any> = {};
|
const attributes: Attributes<any> = {};
|
||||||
|
|
||||||
|
|
||||||
for (const col of columnsResult) {
|
for (const col of columnsResult) {
|
||||||
const {
|
const {
|
||||||
column_name: colName,
|
column_name: colName,
|
||||||
|
|
@ -2195,7 +2187,6 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
|
|
||||||
// 处理用户定义类型(枚举)
|
// 处理用户定义类型(枚举)
|
||||||
if (dataType === 'USER-DEFINED') {
|
if (dataType === 'USER-DEFINED') {
|
||||||
// 查询枚举值
|
|
||||||
const enumSql = `
|
const enumSql = `
|
||||||
SELECT e.enumlabel
|
SELECT e.enumlabel
|
||||||
FROM pg_type t
|
FROM pg_type t
|
||||||
|
|
@ -2213,24 +2204,46 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
} else {
|
} else {
|
||||||
// 构建完整的类型字符串
|
// 构建完整的类型字符串
|
||||||
let fullType = dataType;
|
let fullType = dataType;
|
||||||
if (maxLength) {
|
|
||||||
|
const integerTypes = ['bigint', 'integer', 'smallint', 'serial', 'bigserial', 'smallserial'];
|
||||||
|
|
||||||
|
if (maxLength && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${maxLength})`;
|
fullType = `${dataType}(${maxLength})`;
|
||||||
} else if (precision !== null && scale !== null) {
|
} else if (precision !== null && scale !== null && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${precision},${scale})`;
|
fullType = `${dataType}(${precision},${scale})`;
|
||||||
} else if (precision !== null) {
|
} else if (precision !== null && !integerTypes.includes(dataType)) {
|
||||||
fullType = `${dataType}(${precision})`;
|
fullType = `${dataType}(${precision})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr = this.reTranslateToAttribute(fullType);
|
attr = this.reTranslateToAttribute(fullType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理约束
|
// ========== 类型还原逻辑 ==========
|
||||||
attr.notNull = isNullable === 'NO';
|
// 框架将某些语义类型存储为 bigint,需要根据列名还原
|
||||||
|
if (attr.type === 'bigint') {
|
||||||
|
// 1. 检查是否是序列列
|
||||||
|
if (colName === '$$seq$$' || (defaultValue && defaultValue.includes('nextval'))) {
|
||||||
|
attr.type = 'sequence';
|
||||||
|
attr.sequenceStart = 10000; // 默认起始值
|
||||||
|
}
|
||||||
|
// 2. 检查是否是时间戳列
|
||||||
|
else if (['$$createAt$$', '$$updateAt$$', '$$deleteAt$$'].includes(colName)) {
|
||||||
|
attr.type = 'datetime';
|
||||||
|
}
|
||||||
|
// 3. 检查其他可能的时间类型列(根据命名约定)
|
||||||
|
else if (colName.endsWith('At') || colName.endsWith('Time')) {
|
||||||
|
// 可选:根据业务约定判断是否应该是 datetime
|
||||||
|
// 这里保守处理,只转换框架标准字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 处理默认值(简化处理,复杂的默认值可能需要更精细的解析)
|
// 处理约束 - 只在为 true 时添加
|
||||||
|
if (isNullable === 'NO') {
|
||||||
|
attr.notNull = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理默认值
|
||||||
if (defaultValue && !defaultValue.includes('nextval')) {
|
if (defaultValue && !defaultValue.includes('nextval')) {
|
||||||
// 跳过序列默认值
|
|
||||||
// 简单处理:移除类型转换
|
|
||||||
let cleanDefault = defaultValue.replace(/::[a-z]+/gi, '').replace(/'/g, '');
|
let cleanDefault = defaultValue.replace(/::[a-z]+/gi, '').replace(/'/g, '');
|
||||||
if (cleanDefault === 'true') {
|
if (cleanDefault === 'true') {
|
||||||
attr.default = true;
|
attr.default = true;
|
||||||
|
|
@ -2238,14 +2251,27 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
attr.default = false;
|
attr.default = false;
|
||||||
} else if (!isNaN(Number(cleanDefault))) {
|
} else if (!isNaN(Number(cleanDefault))) {
|
||||||
attr.default = Number(cleanDefault);
|
attr.default = Number(cleanDefault);
|
||||||
} else {
|
} else if (cleanDefault !== '') {
|
||||||
attr.default = cleanDefault;
|
attr.default = cleanDefault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否是序列列(IDENTITY)
|
// 检查唯一约束
|
||||||
if (colName === '$$seq$$' || (defaultValue && defaultValue.includes('nextval'))) {
|
const uniqueSql = `
|
||||||
attr.sequenceStart = 10000; // 默认起始值
|
SELECT COUNT(*) as cnt
|
||||||
|
FROM pg_index ix
|
||||||
|
JOIN pg_class t ON t.oid = ix.indrelid
|
||||||
|
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
|
||||||
|
WHERE t.relname = '${tableName}'
|
||||||
|
AND a.attname = '${colName}'
|
||||||
|
AND ix.indisunique = true
|
||||||
|
AND NOT ix.indisprimary
|
||||||
|
AND array_length(ix.indkey, 1) = 1;
|
||||||
|
`;
|
||||||
|
const [uniqueResult] = await execFn(uniqueSql);
|
||||||
|
const uniqueCount = parseInt(uniqueResult[0]?.cnt || '0', 10);
|
||||||
|
if (uniqueCount > 0) {
|
||||||
|
attr.unique = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes[colName] = attr;
|
attributes[colName] = attr;
|
||||||
|
|
@ -2409,16 +2435,14 @@ export class PostgreSQLTranslator<ED extends EntityDict & BaseEntityDict> extend
|
||||||
} = attrDef;
|
} = attrDef;
|
||||||
|
|
||||||
// 处理序列类型(IDENTITY)
|
// 处理序列类型(IDENTITY)
|
||||||
if (typeof sequenceStart === 'number') {
|
if (type === 'sequence' || (typeof sequenceStart === 'number')) {
|
||||||
sql += `bigint GENERATED BY DEFAULT AS IDENTITY (START WITH ${sequenceStart}) UNIQUE`;
|
sql += `bigint GENERATED BY DEFAULT AS IDENTITY (START WITH ${sequenceStart || 10000}) UNIQUE`;
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理枚举类型
|
// 处理枚举类型
|
||||||
if (type === 'enum') {
|
if (type === 'enum') {
|
||||||
assert(enumeration, 'Enum type requires enumeration values');
|
assert(enumeration, 'Enum type requires enumeration values');
|
||||||
// 注意:这里返回的是占位符,实际的枚举类型名在 translateCreateEntity 中确定
|
|
||||||
// 为了比较一致性,我们使用枚举值的字符串表示
|
|
||||||
sql += `enum(${enumeration.map(v => `'${v}'`).join(',')})`;
|
sql += `enum(${enumeration.map(v => `'${v}'`).join(',')})`;
|
||||||
} else {
|
} else {
|
||||||
sql += this.populateDataTypeDef(type, params, enumeration);
|
sql += this.populateDataTypeDef(type, params, enumeration);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue