@javalabs/prisma-client 1.0.3 → 1.0.6
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/scripts/data-migration/batch-migrator.d.ts +14 -19
- package/dist/scripts/data-migration/batch-migrator.js +98 -297
- package/dist/scripts/data-migration/batch-migrator.js.map +1 -1
- package/dist/scripts/data-migration/data-transformer.d.ts +16 -7
- package/dist/scripts/data-migration/data-transformer.js +169 -133
- package/dist/scripts/data-migration/data-transformer.js.map +1 -1
- package/dist/scripts/data-migration/db-connector.d.ts +6 -1
- package/dist/scripts/data-migration/db-connector.js +44 -8
- package/dist/scripts/data-migration/db-connector.js.map +1 -1
- package/dist/scripts/data-migration/dependency-resolver.d.ts +10 -10
- package/dist/scripts/data-migration/dependency-resolver.js +92 -211
- package/dist/scripts/data-migration/dependency-resolver.js.map +1 -1
- package/dist/scripts/data-migration/foreign-key-manager.d.ts +6 -5
- package/dist/scripts/data-migration/foreign-key-manager.js +108 -18
- package/dist/scripts/data-migration/foreign-key-manager.js.map +1 -1
- package/dist/scripts/data-migration/migration-config.json +63 -0
- package/dist/scripts/data-migration/migration-tool.d.ts +25 -6
- package/dist/scripts/data-migration/migration-tool.js +78 -38
- package/dist/scripts/data-migration/migration-tool.js.map +1 -1
- package/dist/scripts/data-migration/multi-source-migrator.d.ts +17 -0
- package/dist/scripts/data-migration/multi-source-migrator.js +130 -0
- package/dist/scripts/data-migration/multi-source-migrator.js.map +1 -0
- package/dist/scripts/data-migration/schema-utils.d.ts +3 -3
- package/dist/scripts/data-migration/schema-utils.js +62 -19
- package/dist/scripts/data-migration/schema-utils.js.map +1 -1
- package/dist/scripts/data-migration/tenant-migrator.js +9 -2
- package/dist/scripts/data-migration/tenant-migrator.js.map +1 -1
- package/dist/scripts/data-migration/typecast-manager.d.ts +7 -3
- package/dist/scripts/data-migration/typecast-manager.js +169 -25
- package/dist/scripts/data-migration/typecast-manager.js.map +1 -1
- package/dist/scripts/data-migration/types.d.ts +68 -2
- package/dist/scripts/fix-table-indexes.d.ts +26 -0
- package/dist/scripts/fix-table-indexes.js +460 -0
- package/dist/scripts/fix-table-indexes.js.map +1 -0
- package/dist/scripts/multi-db-migration.d.ts +1 -0
- package/dist/scripts/multi-db-migration.js +55 -0
- package/dist/scripts/multi-db-migration.js.map +1 -0
- package/dist/scripts/run-migration.js +41 -75
- package/dist/scripts/run-migration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/migration-config.json +40 -72
- package/{migration-config-public.json → migration-config.json.bk} +14 -14
- package/package.json +6 -3
- package/prisma/migrations/20250422001248_add_bank_account_id/migration.sql +458 -0
- package/prisma/migrations/20250422001957_add_bank_account_id_relations/migration.sql +14 -0
- package/prisma/schema.prisma +13 -12
- package/src/scripts/data-migration/batch-migrator.ts +192 -513
- package/src/scripts/data-migration/data-transformer.ts +252 -203
- package/src/scripts/data-migration/db-connector.ts +66 -13
- package/src/scripts/data-migration/dependency-resolver.ts +121 -266
- package/src/scripts/data-migration/foreign-key-manager.ts +214 -32
- package/src/scripts/data-migration/migration-config.json +63 -0
- package/src/scripts/data-migration/migration-tool.ts +377 -225
- package/src/scripts/data-migration/schema-utils.ts +94 -32
- package/src/scripts/data-migration/tenant-migrator.ts +12 -5
- package/src/scripts/data-migration/typecast-manager.ts +186 -31
- package/src/scripts/data-migration/types.ts +78 -5
- package/src/scripts/dumps/source_dump_20250428_145606.sql +323 -0
- package/src/scripts/fix-table-indexes.ts +602 -0
- package/src/scripts/post-migration-validator.ts +206 -107
- package/src/scripts/run-migration.ts +87 -101
|
@@ -7,244 +7,125 @@ class DependencyResolver {
|
|
|
7
7
|
this.sourcePool = sourcePool;
|
|
8
8
|
this.targetPool = targetPool;
|
|
9
9
|
this.logger = new common_1.Logger("DependencyResolver");
|
|
10
|
-
this.
|
|
10
|
+
this.visitedTables = new Set();
|
|
11
|
+
this.temporaryMark = new Set();
|
|
12
|
+
this.tableOrder = [];
|
|
13
|
+
}
|
|
14
|
+
setConfig(config) {
|
|
15
|
+
this.config = config;
|
|
11
16
|
}
|
|
12
17
|
async analyzeDependencies() {
|
|
13
18
|
try {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
table
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
this.logger.log("Iniciando análisis de dependencias...");
|
|
20
|
+
const tables = await this.getAllTables();
|
|
21
|
+
this.visitedTables.clear();
|
|
22
|
+
this.temporaryMark.clear();
|
|
23
|
+
this.tableOrder.length = 0;
|
|
24
|
+
const priorityOrder = this.getPriorityOrder(tables);
|
|
25
|
+
for (const priorityGroup of priorityOrder) {
|
|
26
|
+
for (const table of priorityGroup) {
|
|
27
|
+
if (!this.visitedTables.has(table)) {
|
|
28
|
+
await this.visit(table);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
25
31
|
}
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
.sort((a, b) => (a.level || 0) - (b.level || 0))
|
|
29
|
-
.map((dep) => dep.table);
|
|
30
|
-
this.logger.log(`Migration order: ${sortedTables.join(" -> ")}`);
|
|
31
|
-
return sortedTables;
|
|
32
|
+
this.logger.log(`Orden de migración determinado: ${this.tableOrder.join(" -> ")}`);
|
|
33
|
+
return this.tableOrder;
|
|
32
34
|
}
|
|
33
35
|
catch (error) {
|
|
34
|
-
this.logger.error(`Error
|
|
36
|
+
this.logger.error(`Error analizando dependencias: ${error.message}`);
|
|
35
37
|
throw error;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
invoices: ["transactions"],
|
|
45
|
-
credit_requests: ["users", "invoices"],
|
|
46
|
-
notifications: ["users", "transactions"],
|
|
47
|
-
pending_references: ["users", "providers"],
|
|
48
|
-
daily_logs: ["transactions"],
|
|
49
|
-
transaction_updates: ["transactions"],
|
|
50
|
-
toku: ["transactions"],
|
|
51
|
-
providers: ["countries"],
|
|
52
|
-
users: ["countries"],
|
|
40
|
+
getPriorityOrder(tables) {
|
|
41
|
+
var _a, _b, _c, _d, _e, _f;
|
|
42
|
+
const priorities = {
|
|
43
|
+
high: new Set(((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.migrationPriorities) === null || _b === void 0 ? void 0 : _b.high) || []),
|
|
44
|
+
medium: new Set(((_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.migrationPriorities) === null || _d === void 0 ? void 0 : _d.medium) || []),
|
|
45
|
+
low: new Set(((_f = (_e = this.config) === null || _e === void 0 ? void 0 : _e.migrationPriorities) === null || _f === void 0 ? void 0 : _f.low) || []),
|
|
53
46
|
};
|
|
54
|
-
|
|
47
|
+
const highPriority = tables.filter((t) => priorities.high.has(t));
|
|
48
|
+
const mediumPriority = tables.filter((t) => priorities.medium.has(t));
|
|
49
|
+
const lowPriority = tables.filter((t) => priorities.low.has(t));
|
|
50
|
+
const noPriority = tables.filter((t) => !priorities.high.has(t) &&
|
|
51
|
+
!priorities.medium.has(t) &&
|
|
52
|
+
!priorities.low.has(t));
|
|
53
|
+
return [highPriority, mediumPriority, noPriority, lowPriority];
|
|
54
|
+
}
|
|
55
|
+
async visit(table, path = []) {
|
|
56
|
+
if (this.temporaryMark.has(table)) {
|
|
57
|
+
const cycle = [...path, table].join(" -> ");
|
|
58
|
+
this.logger.warn(`Detectado ciclo de dependencias: ${cycle}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (this.visitedTables.has(table)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.temporaryMark.add(table);
|
|
65
|
+
path.push(table);
|
|
66
|
+
const dependencies = await this.getTableDependencies(table);
|
|
67
|
+
for (const dep of dependencies) {
|
|
68
|
+
if (!this.visitedTables.has(dep)) {
|
|
69
|
+
await this.visit(dep, [...path]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
this.temporaryMark.delete(table);
|
|
73
|
+
this.visitedTables.add(table);
|
|
74
|
+
this.tableOrder.push(table);
|
|
55
75
|
}
|
|
56
|
-
async
|
|
76
|
+
async getAllTables() {
|
|
57
77
|
const query = `
|
|
58
78
|
SELECT table_name
|
|
59
79
|
FROM information_schema.tables
|
|
60
80
|
WHERE table_schema = 'public'
|
|
61
81
|
AND table_type = 'BASE TABLE'
|
|
62
|
-
AND table_name NOT IN ('_prisma_migrations', 'schema_migrations')
|
|
63
82
|
`;
|
|
64
83
|
const result = await this.sourcePool.query(query);
|
|
65
84
|
return result.rows.map((row) => row.table_name);
|
|
66
85
|
}
|
|
67
|
-
async
|
|
86
|
+
async getTableDependencies(table) {
|
|
87
|
+
var _a, _b, _c;
|
|
88
|
+
const dependencies = new Set();
|
|
89
|
+
const configDeps = ((_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.tables) === null || _b === void 0 ? void 0 : _b[table]) === null || _c === void 0 ? void 0 : _c.dependencies) || [];
|
|
90
|
+
configDeps.forEach((dep) => dependencies.add(dep));
|
|
91
|
+
const query = `
|
|
92
|
+
SELECT
|
|
93
|
+
ccu.table_name AS foreign_table
|
|
94
|
+
FROM
|
|
95
|
+
information_schema.table_constraints tc
|
|
96
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
97
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
98
|
+
WHERE
|
|
99
|
+
tc.constraint_type = 'FOREIGN KEY'
|
|
100
|
+
AND tc.table_name = $1
|
|
101
|
+
AND tc.table_schema = 'public'
|
|
102
|
+
`;
|
|
68
103
|
try {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
ccu.table_name AS foreign_table_name,
|
|
72
|
-
kcu.column_name AS column_name
|
|
73
|
-
FROM
|
|
74
|
-
information_schema.table_constraints AS tc
|
|
75
|
-
JOIN information_schema.constraint_column_usage AS ccu
|
|
76
|
-
ON ccu.constraint_name = tc.constraint_name
|
|
77
|
-
JOIN information_schema.key_column_usage AS kcu
|
|
78
|
-
ON kcu.constraint_name = tc.constraint_name
|
|
79
|
-
WHERE
|
|
80
|
-
tc.constraint_type = 'FOREIGN KEY'
|
|
81
|
-
AND tc.table_name = $1
|
|
82
|
-
AND tc.table_schema = 'public'
|
|
83
|
-
`;
|
|
84
|
-
const implicitDependencyQuery = `
|
|
85
|
-
SELECT DISTINCT
|
|
86
|
-
c.column_name,
|
|
87
|
-
c.udt_name,
|
|
88
|
-
c.column_default,
|
|
89
|
-
c.data_type
|
|
90
|
-
FROM
|
|
91
|
-
information_schema.columns c
|
|
92
|
-
WHERE
|
|
93
|
-
c.table_schema = 'public'
|
|
94
|
-
AND c.table_name = $1
|
|
95
|
-
AND (
|
|
96
|
-
-- Common ID patterns
|
|
97
|
-
c.column_name LIKE '%_id'
|
|
98
|
-
OR c.column_name LIKE '%_ids'
|
|
99
|
-
OR c.column_name LIKE 'id_%'
|
|
100
|
-
-- Reference patterns
|
|
101
|
-
OR c.column_name LIKE '%_ref%'
|
|
102
|
-
OR c.column_name LIKE '%_key'
|
|
103
|
-
OR c.column_name LIKE '%_code'
|
|
104
|
-
-- Relationship patterns
|
|
105
|
-
OR c.column_name LIKE '%_by'
|
|
106
|
-
OR c.column_name LIKE '%_to'
|
|
107
|
-
OR c.column_name LIKE '%_from'
|
|
108
|
-
OR c.column_name LIKE 'parent_%'
|
|
109
|
-
OR c.column_name LIKE 'child_%'
|
|
110
|
-
-- JSON/JSONB columns that might contain references
|
|
111
|
-
OR (c.data_type IN ('json', 'jsonb') AND c.column_name LIKE '%_data')
|
|
112
|
-
-- Array columns that might contain IDs
|
|
113
|
-
OR (c.data_type = 'ARRAY' AND c.column_name LIKE '%_ids')
|
|
114
|
-
-- Enum columns that might indicate relationships
|
|
115
|
-
OR (c.udt_name LIKE 'enum_%' AND c.column_name LIKE '%_type')
|
|
116
|
-
)
|
|
117
|
-
`;
|
|
118
|
-
const referencedTablesQuery = `
|
|
119
|
-
SELECT DISTINCT
|
|
120
|
-
obj_description(c.table_name::regclass, 'pg_class') as table_comment
|
|
121
|
-
FROM
|
|
122
|
-
information_schema.columns c
|
|
123
|
-
WHERE
|
|
124
|
-
c.table_schema = 'public'
|
|
125
|
-
AND c.table_name = $1
|
|
126
|
-
`;
|
|
127
|
-
const [fkResult, implicitResult, referencedResult] = await Promise.all([
|
|
128
|
-
this.sourcePool.query(foreignKeyQuery, [tableName]),
|
|
129
|
-
this.sourcePool.query(implicitDependencyQuery, [tableName]),
|
|
130
|
-
this.sourcePool.query(referencedTablesQuery, [tableName]),
|
|
131
|
-
]);
|
|
132
|
-
const allDependencies = new Set();
|
|
133
|
-
fkResult.rows.forEach((row) => allDependencies.add(row.foreign_table_name));
|
|
134
|
-
implicitResult.rows.forEach((row) => {
|
|
135
|
-
const columnName = row.column_name;
|
|
136
|
-
const potentialTable = this.inferTableNameFromColumn(columnName);
|
|
137
|
-
if (potentialTable) {
|
|
138
|
-
allDependencies.add(potentialTable);
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
referencedResult.rows.forEach((row) => {
|
|
142
|
-
if (row.table_comment) {
|
|
143
|
-
const referencedTables = this.parseTableComment(row.table_comment);
|
|
144
|
-
referencedTables.forEach((table) => allDependencies.add(table));
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
implicitResult.rows.forEach((row) => {
|
|
148
|
-
var _a;
|
|
149
|
-
if (row.data_type === "json" || row.data_type === "jsonb") {
|
|
150
|
-
const potentialRefs = this.extractJsonReferences(row.column_name);
|
|
151
|
-
potentialRefs.forEach((ref) => allDependencies.add(ref));
|
|
152
|
-
}
|
|
153
|
-
if ((_a = row.udt_name) === null || _a === void 0 ? void 0 : _a.startsWith("enum_")) {
|
|
154
|
-
const enumTable = this.inferTableFromEnum(row.udt_name);
|
|
155
|
-
if (enumTable)
|
|
156
|
-
allDependencies.add(enumTable);
|
|
157
|
-
}
|
|
158
|
-
if (row.data_type === "ARRAY") {
|
|
159
|
-
const arrayTable = this.inferTableFromArrayColumn(row.column_name);
|
|
160
|
-
if (arrayTable)
|
|
161
|
-
allDependencies.add(arrayTable);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
return Array.from(allDependencies);
|
|
104
|
+
const result = await this.sourcePool.query(query, [table]);
|
|
105
|
+
result.rows.forEach((row) => dependencies.add(row.foreign_table));
|
|
165
106
|
}
|
|
166
107
|
catch (error) {
|
|
167
|
-
this.logger.
|
|
168
|
-
return [];
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
inferTableFromEnum(enumType) {
|
|
172
|
-
const parts = enumType.split("_");
|
|
173
|
-
if (parts.length > 1) {
|
|
174
|
-
return parts[1];
|
|
175
|
-
}
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
inferTableFromArrayColumn(columnName) {
|
|
179
|
-
if (columnName.endsWith("_ids")) {
|
|
180
|
-
return columnName.slice(0, -4) + "s";
|
|
181
|
-
}
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
extractJsonReferences(columnName) {
|
|
185
|
-
const refs = [];
|
|
186
|
-
const parts = columnName.split("_");
|
|
187
|
-
if (parts.length > 1) {
|
|
188
|
-
const potentialTable = parts[0] + "s";
|
|
189
|
-
refs.push(potentialTable);
|
|
108
|
+
this.logger.warn(`Error obteniendo dependencias para ${table}: ${error.message}`);
|
|
190
109
|
}
|
|
191
|
-
return
|
|
110
|
+
return Array.from(dependencies);
|
|
192
111
|
}
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
parseTableComment(comment) {
|
|
208
|
-
const referencesMatch = comment.match(/References:\s*([^;]+)/i);
|
|
209
|
-
if (referencesMatch) {
|
|
210
|
-
return referencesMatch[1]
|
|
211
|
-
.split(",")
|
|
212
|
-
.map((table) => table.trim())
|
|
213
|
-
.filter((table) => table.length > 0);
|
|
214
|
-
}
|
|
215
|
-
return [];
|
|
216
|
-
}
|
|
217
|
-
assignLevels() {
|
|
218
|
-
const visited = new Set();
|
|
219
|
-
const visiting = new Set();
|
|
220
|
-
const visit = (tableName, level = 0) => {
|
|
221
|
-
var _a;
|
|
222
|
-
if (visiting.has(tableName)) {
|
|
223
|
-
this.logger.warn(`Circular dependency detected involving table: ${tableName}`);
|
|
224
|
-
return level;
|
|
225
|
-
}
|
|
226
|
-
if (visited.has(tableName)) {
|
|
227
|
-
return ((_a = this.dependencyGraph.get(tableName)) === null || _a === void 0 ? void 0 : _a.level) || 0;
|
|
228
|
-
}
|
|
229
|
-
visiting.add(tableName);
|
|
230
|
-
const node = this.dependencyGraph.get(tableName);
|
|
231
|
-
if (!node)
|
|
232
|
-
return level;
|
|
233
|
-
let maxDepLevel = level;
|
|
234
|
-
for (const dep of node.dependencies) {
|
|
235
|
-
const depLevel = visit(dep, level + 1);
|
|
236
|
-
maxDepLevel = Math.max(maxDepLevel, depLevel + 1);
|
|
237
|
-
}
|
|
238
|
-
node.level = maxDepLevel;
|
|
239
|
-
visited.add(tableName);
|
|
240
|
-
visiting.delete(tableName);
|
|
241
|
-
return maxDepLevel;
|
|
242
|
-
};
|
|
243
|
-
for (const tableName of this.dependencyGraph.keys()) {
|
|
244
|
-
if (!visited.has(tableName)) {
|
|
245
|
-
visit(tableName);
|
|
112
|
+
async validateDependencies(table, dependencies) {
|
|
113
|
+
for (const dep of dependencies) {
|
|
114
|
+
const query = `
|
|
115
|
+
SELECT EXISTS (
|
|
116
|
+
SELECT 1
|
|
117
|
+
FROM information_schema.tables
|
|
118
|
+
WHERE table_schema = 'public'
|
|
119
|
+
AND table_name = $1
|
|
120
|
+
)
|
|
121
|
+
`;
|
|
122
|
+
const result = await this.sourcePool.query(query, [dep]);
|
|
123
|
+
if (!result.rows[0].exists) {
|
|
124
|
+
this.logger.warn(`Dependencia ${dep} no encontrada para tabla ${table}`);
|
|
125
|
+
return false;
|
|
246
126
|
}
|
|
247
127
|
}
|
|
128
|
+
return true;
|
|
248
129
|
}
|
|
249
130
|
}
|
|
250
131
|
exports.DependencyResolver = DependencyResolver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/dependency-resolver.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;
|
|
1
|
+
{"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/dependency-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,15 +3,16 @@ import { DatabaseConnections } from "./types";
|
|
|
3
3
|
export declare class ForeignKeyManager {
|
|
4
4
|
private readonly connections;
|
|
5
5
|
private readonly logger;
|
|
6
|
+
private readonly dependencyCache;
|
|
6
7
|
constructor(connections: DatabaseConnections);
|
|
7
8
|
getForeignKeyDependencies(schemaName: string, tableName: string): Promise<Array<{
|
|
8
9
|
column: string;
|
|
9
10
|
foreignTable: string;
|
|
10
11
|
foreignColumn: string;
|
|
11
12
|
}>>;
|
|
12
|
-
checkForeignKeyDependencies(prisma: PrismaClient,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
checkForeignKeyDependencies(prisma: PrismaClient, tenantId: string, record: any, dependencies: any[]): Promise<string[]>;
|
|
14
|
+
private checkSourceDependency;
|
|
15
|
+
private checkDependencyExists;
|
|
16
|
+
verifyDependencies(tableName: string, record: any, tenantId: string): Promise<boolean>;
|
|
17
|
+
private checkTableExists;
|
|
17
18
|
}
|
|
@@ -6,9 +6,15 @@ class ForeignKeyManager {
|
|
|
6
6
|
constructor(connections) {
|
|
7
7
|
this.connections = connections;
|
|
8
8
|
this.logger = new common_1.Logger("ForeignKeyManager");
|
|
9
|
+
this.dependencyCache = new Map();
|
|
9
10
|
}
|
|
10
11
|
async getForeignKeyDependencies(schemaName, tableName) {
|
|
12
|
+
const cacheKey = `${schemaName}.${tableName}`;
|
|
13
|
+
if (this.dependencyCache.has(cacheKey)) {
|
|
14
|
+
return this.dependencyCache.get(cacheKey);
|
|
15
|
+
}
|
|
11
16
|
try {
|
|
17
|
+
this.logger.log(`Obteniendo dependencias de llaves foráneas para ${schemaName}.${tableName}`);
|
|
12
18
|
const query = `
|
|
13
19
|
SELECT
|
|
14
20
|
kcu.column_name,
|
|
@@ -31,39 +37,123 @@ class ForeignKeyManager {
|
|
|
31
37
|
schemaName,
|
|
32
38
|
tableName,
|
|
33
39
|
]);
|
|
34
|
-
|
|
40
|
+
const dependencies = rows.map((row) => ({
|
|
35
41
|
column: row.column_name,
|
|
36
42
|
foreignTable: row.foreign_table_name,
|
|
37
43
|
foreignColumn: row.foreign_column_name,
|
|
38
44
|
}));
|
|
45
|
+
this.logger.log(`Encontradas ${dependencies.length} dependencias para ${schemaName}.${tableName}:
|
|
46
|
+
${dependencies
|
|
47
|
+
.map((d) => `\n - ${d.column} -> ${d.foreignTable}.${d.foreignColumn}`)
|
|
48
|
+
.join("")}`);
|
|
49
|
+
this.dependencyCache.set(cacheKey, dependencies);
|
|
50
|
+
return dependencies;
|
|
39
51
|
}
|
|
40
52
|
catch (error) {
|
|
41
|
-
this.logger.error(`Error
|
|
53
|
+
this.logger.error(`Error obteniendo dependencias de ${schemaName}.${tableName}: ${error.message}`);
|
|
42
54
|
return [];
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
|
-
async checkForeignKeyDependencies(prisma,
|
|
57
|
+
async checkForeignKeyDependencies(prisma, tenantId, record, dependencies) {
|
|
46
58
|
const missingDependencies = [];
|
|
59
|
+
const recordId = record.id || "unknown";
|
|
60
|
+
this.logger.debug(`Verificando dependencias para registro ${recordId} en tenant ${tenantId}`);
|
|
47
61
|
for (const dep of dependencies) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
const { table, column, references } = dep;
|
|
63
|
+
const foreignKeyValue = record[column];
|
|
64
|
+
if (foreignKeyValue === null) {
|
|
65
|
+
this.logger.debug(`Dependencia ${table}.${references} es nula para registro ${recordId}, continuando`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const sourceExists = await this.checkSourceDependency(table, references, foreignKeyValue);
|
|
69
|
+
if (!sourceExists) {
|
|
70
|
+
this.logger.debug(`Registro ${recordId}: Dependencia ${table}.${references}=${foreignKeyValue} no existe en origen, ignorando`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const exists = await this.checkDependencyExists(prisma, tenantId, table, references, foreignKeyValue);
|
|
74
|
+
if (!exists) {
|
|
75
|
+
const depString = `${table}.${references}=${foreignKeyValue}`;
|
|
76
|
+
this.logger.debug(`Registro ${recordId}: Dependencia ${depString} existe en origen pero falta en destino`);
|
|
77
|
+
missingDependencies.push(depString);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.logger.debug(`Registro ${recordId}: Dependencia ${table}.${references}=${foreignKeyValue} verificada OK`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (missingDependencies.length > 0) {
|
|
84
|
+
this.logger.debug(`Registro ${recordId}: Faltan ${missingDependencies.length} dependencias:
|
|
85
|
+
${missingDependencies.map((dep) => `\n - ${dep}`).join("")}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.logger.debug(`Registro ${recordId}: Todas las dependencias OK`);
|
|
89
|
+
}
|
|
90
|
+
return missingDependencies;
|
|
91
|
+
}
|
|
92
|
+
async checkSourceDependency(table, column, value) {
|
|
93
|
+
try {
|
|
94
|
+
const result = await this.connections.sourcePool.query(`SELECT 1 FROM "${table}" WHERE "${column}" = $1 LIMIT 1`, [value]);
|
|
95
|
+
const exists = result.rows.length > 0;
|
|
96
|
+
this.logger.debug(`Verificación en origen ${table}.${column}=${value}: ${exists ? "EXISTE" : "NO EXISTE"}`);
|
|
97
|
+
return exists;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.logger.error(`Error verificando en origen ${table}.${column}=${value}: ${error.message}`);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async checkDependencyExists(prisma, tenantId, table, column, value) {
|
|
105
|
+
try {
|
|
106
|
+
const result = await prisma.$queryRawUnsafe(`SELECT 1 FROM "${tenantId}"."${table}" WHERE "${column}" = $1 LIMIT 1`, value);
|
|
107
|
+
const exists = Array.isArray(result) && result.length > 0;
|
|
108
|
+
this.logger.debug(`Verificación en destino ${tenantId}.${table}.${column}=${value}: ${exists ? "EXISTE" : "NO EXISTE"}`);
|
|
109
|
+
return exists;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
this.logger.error(`Error verificando en destino ${tenantId}.${table}.${column}=${value}: ${error.message}`);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async verifyDependencies(tableName, record, tenantId) {
|
|
117
|
+
try {
|
|
118
|
+
const dependencies = await this.getForeignKeyDependencies(tableName, tableName);
|
|
119
|
+
for (const dep of dependencies) {
|
|
120
|
+
const { foreignTable, foreignColumn } = dep;
|
|
121
|
+
const tableExists = await this.checkTableExists(foreignTable);
|
|
122
|
+
if (!tableExists) {
|
|
123
|
+
this.logger.warn(`Table ${foreignTable} does not exist, skipping dependency check`);
|
|
124
|
+
continue;
|
|
59
125
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
126
|
+
const foreignKeyValue = record[foreignColumn];
|
|
127
|
+
if (foreignKeyValue) {
|
|
128
|
+
const exists = await this.checkDependencyExists(this.connections.targetPrisma, tenantId, foreignTable, foreignColumn, foreignKeyValue);
|
|
129
|
+
if (!exists) {
|
|
130
|
+
this.logger.warn(`Valor ${foreignKeyValue} no existe en ${foreignTable}.${foreignColumn}`);
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
63
133
|
}
|
|
64
134
|
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
this.logger.error(`Error verifying dependencies: ${error.message}`);
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async checkTableExists(tableName) {
|
|
143
|
+
try {
|
|
144
|
+
const result = await this.connections.sourcePool.query(`SELECT EXISTS (
|
|
145
|
+
SELECT FROM information_schema.tables
|
|
146
|
+
WHERE table_schema = 'public'
|
|
147
|
+
AND table_name = $1
|
|
148
|
+
)`, [tableName]);
|
|
149
|
+
const exists = result.rows[0].exists;
|
|
150
|
+
this.logger.debug(`Verificación de existencia de tabla ${tableName}: ${exists ? "EXISTE" : "NO EXISTE"}`);
|
|
151
|
+
return exists;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
this.logger.error(`Error verificando existencia de tabla ${tableName}: ${error.message}`);
|
|
155
|
+
return false;
|
|
65
156
|
}
|
|
66
|
-
return missingDependencies;
|
|
67
157
|
}
|
|
68
158
|
}
|
|
69
159
|
exports.ForeignKeyManager = ForeignKeyManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foreign-key-manager.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/foreign-key-manager.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAIxC,MAAa,iBAAiB;
|
|
1
|
+
{"version":3,"file":"foreign-key-manager.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/foreign-key-manager.ts"],"names":[],"mappings":"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"}
|