2024-06-10 07:17:43 +08:00
|
|
|
import { dbToTypes } from "../data/datatypes";
|
2024-05-16 11:44:39 +08:00
|
|
|
import i18n from "../i18n/i18n";
|
2024-06-10 07:17:43 +08:00
|
|
|
import { isFunction } from "./utils";
|
2024-04-10 09:57:07 +08:00
|
|
|
|
2024-06-10 07:17:43 +08:00
|
|
|
function checkDefault(field, database) {
|
2024-03-12 19:52:01 +08:00
|
|
|
if (field.default === "") return true;
|
|
|
|
|
2024-04-24 16:49:00 +08:00
|
|
|
if (isFunction(field.default)) return true;
|
|
|
|
|
2024-04-24 23:37:50 +08:00
|
|
|
if (!field.notNull && field.default.toLowerCase() === "null") return true;
|
|
|
|
|
2024-06-10 07:17:43 +08:00
|
|
|
return dbToTypes[database][field.type].checkDefault(field);
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
|
2024-03-16 02:55:43 +08:00
|
|
|
export function getIssues(diagram) {
|
2024-03-12 19:52:01 +08:00
|
|
|
const issues = [];
|
|
|
|
const duplicateTableNames = {};
|
|
|
|
|
|
|
|
diagram.tables.forEach((table) => {
|
|
|
|
if (table.name === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("table_w_no_name"));
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (duplicateTableNames[table.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("duplicate_table_by_name", { tableName: table.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateTableNames[table.name] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const duplicateFieldNames = {};
|
|
|
|
let hasPrimaryKey = false;
|
|
|
|
|
|
|
|
table.fields.forEach((field) => {
|
|
|
|
if (field.primary) {
|
|
|
|
hasPrimaryKey = true;
|
|
|
|
}
|
|
|
|
if (field.name === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("empty_field_name", { tableName: table.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (field.type === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("empty_field_type", { tableName: table.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
} else if (field.type === "ENUM" || field.type === "SET") {
|
|
|
|
if (!field.values || field.values.length === 0) {
|
|
|
|
issues.push(
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("no_values_for_field", {
|
|
|
|
tableName: table.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
type: field.type,
|
|
|
|
}),
|
2024-03-12 19:52:01 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-10 07:17:43 +08:00
|
|
|
if (!checkDefault(field, diagram.database)) {
|
2024-03-12 19:52:01 +08:00
|
|
|
issues.push(
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("default_doesnt_match_type", {
|
|
|
|
tableName: table.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
}),
|
2024-03-12 19:52:01 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field.notNull && field.default.toLowerCase() === "null") {
|
|
|
|
issues.push(
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("not_null_is_null", {
|
|
|
|
tableName: table.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
}),
|
2024-03-12 19:52:01 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (duplicateFieldNames[field.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("duplicate_fields", {
|
|
|
|
tableName: table.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateFieldNames[field.name] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const duplicateIndices = {};
|
|
|
|
table.indices.forEach((index) => {
|
|
|
|
if (duplicateIndices[index.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("duplicate_index", {
|
|
|
|
tableName: table.name,
|
|
|
|
indexName: index.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateIndices[index.name] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
table.indices.forEach((index) => {
|
|
|
|
if (index.fields.length === 0) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("empty_index", {
|
|
|
|
tableName: table.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!hasPrimaryKey) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("no_primary_key", { tableName: table.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const duplicateTypeNames = {};
|
|
|
|
diagram.types.forEach((type) => {
|
|
|
|
if (type.name === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("type_with_no_name"));
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (duplicateTypeNames[type.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("duplicate_types", { typeName: type.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateTypeNames[type.name] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type.fields.length === 0) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(i18n.t("type_w_no_fields", { typeName: type.name }));
|
2024-03-12 19:52:01 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const duplicateFieldNames = {};
|
|
|
|
type.fields.forEach((field) => {
|
|
|
|
if (field.name === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("empty_type_field_name", {
|
|
|
|
typeName: type.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (field.type === "") {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("empty_type_field_type", {
|
|
|
|
typeName: type.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
} else if (field.type === "ENUM" || field.type === "SET") {
|
|
|
|
if (!field.values || field.values.length === 0) {
|
|
|
|
issues.push(
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("no_values_for_type_field", {
|
|
|
|
typeName: type.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
type: field.type,
|
|
|
|
}),
|
2024-03-12 19:52:01 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (duplicateFieldNames[field.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("duplicate_type_fields", {
|
|
|
|
typeName: type.name,
|
|
|
|
fieldName: field.name,
|
|
|
|
});
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateFieldNames[field.name] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const duplicateFKName = {};
|
|
|
|
diagram.relationships.forEach((r) => {
|
|
|
|
if (duplicateFKName[r.name]) {
|
2024-05-16 11:44:39 +08:00
|
|
|
issues.push(
|
|
|
|
i18n.t("duplicate_reference", {
|
|
|
|
refName: r.name,
|
|
|
|
}),
|
|
|
|
);
|
2024-03-12 19:52:01 +08:00
|
|
|
} else {
|
|
|
|
duplicateFKName[r.name] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const visitedTables = new Set();
|
|
|
|
|
|
|
|
function checkCircularRelationships(tableId, visited = []) {
|
|
|
|
if (visited.includes(tableId)) {
|
|
|
|
issues.push(
|
2024-05-16 11:44:39 +08:00
|
|
|
i18n.t("circular_dependency", {
|
|
|
|
refName: diagram.tables[tableId].name,
|
|
|
|
}),
|
2024-03-12 19:52:01 +08:00
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
visited.push(tableId);
|
|
|
|
visitedTables.add(tableId);
|
|
|
|
|
|
|
|
diagram.relationships.forEach((r) => {
|
|
|
|
if (r.startTableId === tableId && r.startTableId !== r.endTableId) {
|
|
|
|
checkCircularRelationships(r.endTableId, [...visited]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
diagram.tables.forEach((table) => {
|
|
|
|
if (!visitedTables.has(table.id)) {
|
|
|
|
checkCircularRelationships(table.id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return issues;
|
|
|
|
}
|