dbtasker 2.5.1 → 3.0.0

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/altercolumn.js ADDED
@@ -0,0 +1,595 @@
1
+ const fncs = require("./function");
2
+ const cstyler = require("cstyler");
3
+
4
+
5
+
6
+ function isValidToBeForeignkey(refColData, columnData) {
7
+ try {
8
+ if (refColData.columntype.toUpperCase() !== columnData.columntype.toUpperCase()) {
9
+ return false;
10
+ }
11
+ if (Array.isArray(refColData.length_values) !== Array.isArray(columnData.length_values)) {
12
+ return false;
13
+ } else if (Array.isArray(refColData.length_values) && Array.isArray(columnData.length_values)) {
14
+ if (!fncs.isSameArray(refColData.length_values, columnData.length_values)) {
15
+ return false;
16
+ }
17
+ } else {
18
+ if (refColData.length_values !== columnData.length_values) {
19
+ return false;
20
+ }
21
+ }
22
+ if ((refColData.unsigned || false) !== (columnData.unsigned || false)) {
23
+ return false;
24
+ }
25
+ if (["CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "ENUM", "SET"].includes(refColData.columntype.toUpperCase())) {
26
+ if ((refColData._charset_ || "") !== (columnData._charset_ || "")) {
27
+ return false;
28
+ }
29
+ if ((refColData._collate_ || "") !== (columnData._collate_ || "")) {
30
+ return false;
31
+ }
32
+ }
33
+ return true;
34
+ } catch (err) {
35
+ console.log(err);
36
+ return false;
37
+ }
38
+ }
39
+ async function isColumnDataSame(config, databaseName, tableName, columnName, columnData, columndetails, fkdetails,) {
40
+ // 1. Column type
41
+ if (columnData.columntype !== columndetails.columntype) {
42
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
43
+ console.log(cstyler.red("Column type do not match"));
44
+ return false;
45
+ }
46
+
47
+ // 2. Length / precision / enum-set values
48
+ if (columnData.length_value !== undefined) {
49
+ const a = columnData.length_value;
50
+ const b = columndetails.length_value;
51
+
52
+ // ENUM / SET → array of strings
53
+ if (['ENUM', 'SET'].includes(columnData.columntype)) {
54
+ if (!Array.isArray(a) || !Array.isArray(b)) {
55
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
56
+ console.log(cstyler.red("ENUM or SET values must be an array"));
57
+ return false;
58
+ }
59
+ if (a.length !== b.length) {
60
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
61
+ console.log(cstyler.red("ENUM or SET - value length are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(a), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(b),);
62
+ return false;
63
+ }
64
+
65
+ for (let i = 0; i < a.length; i++) {
66
+ if (!a.includes(b[i])) {
67
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
68
+ console.log(cstyler.red("ENUM or SET - Server and given value are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(a), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(b),);
69
+ return false;
70
+
71
+ }
72
+ }
73
+ }
74
+ // DECIMAL(p,s) → [number, number]
75
+ else if (Array.isArray(a)) {
76
+ if (!Array.isArray(b) || a.length !== b.length) {
77
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
78
+ console.log(cstyler.red("Decimal length value are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(a), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(b),);
79
+ return false;
80
+ }
81
+ if (a[0] !== b[0] || a[1] !== b[1]) {
82
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
83
+ console.log(cstyler.red("Decimal length value are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(a), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(b),);
84
+ return false;
85
+ }
86
+ }
87
+ // INT, VARCHAR, CHAR, etc. → number
88
+ else {
89
+ if (a !== b && a !== undefined) {
90
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
91
+ console.log(cstyler.red("Length value are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(a), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(b),);
92
+ return false;
93
+ }
94
+ }
95
+ }
96
+
97
+ // 3. UNSIGNED
98
+ if (typeof columnData.unsigned === "boolean" &&
99
+ columnData.unsigned !== columndetails.unsigned) {
100
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
101
+ console.log(cstyler.red("Unsigned have changed"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.unsigned), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.unsigned),);
102
+ return false;
103
+ }
104
+
105
+ // 4. ZEROFILL
106
+ if (typeof columnData.zerofill === "boolean" &&
107
+ columnData.zerofill !== columndetails.zerofill) {
108
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
109
+ console.log(cstyler.red("Zerofill have changed"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.zerofill), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.zerofill),);
110
+ return false;
111
+ }
112
+
113
+ // 5. NULL / NOT NULL
114
+ if (typeof columnData.nulls === "boolean" &&
115
+ columnData.nulls !== columndetails.nulls) {
116
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
117
+ console.log(cstyler.red("Null have changed"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.nulls), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.nulls),);
118
+ return false;
119
+ }
120
+
121
+ // 6. DEFAULT
122
+ const defA = columnData.defaults ?? null;
123
+ const defB = columndetails.defaults ?? null;
124
+ if (defA != defB) {
125
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
126
+ console.log(cstyler.red("Default need some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.defaults), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.defaults),);
127
+ return false;
128
+ }
129
+
130
+ // 7. INDEX (PRIMARY / UNIQUE / "")
131
+ const idxA = columnData.index ?? "";
132
+ const idxB = columndetails.index ?? "";
133
+ const realfk = idxB === "" && (idxA === "" || idxA === undefined);
134
+ if ((idxA === "" || idxA === undefined) && idxB === "KEY") {
135
+ // check if it is a referancing column
136
+ const getall = await fncs.getForeignKeyDetails(config, databaseName, tableName, columnName);
137
+ if (getall === null) {
138
+ console.error("Server error: Having problem finding referencing columns from ", cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(columnName));
139
+ return null;
140
+ }
141
+ if (!fncs.isJsonObject(getall)) {
142
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
143
+ console.log(cstyler.red("Index need some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.index), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.index),);
144
+ return false;
145
+ }
146
+ } else if (idxA !== idxB && !realfk) {
147
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
148
+ console.log(cstyler.red("Index are not same"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.index), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.index),);
149
+ console.log("fk exist:", fkdetails)
150
+ return false;
151
+ }
152
+
153
+ // 8. AUTO_INCREMENT
154
+ if ((columnData.autoincrement !== undefined && columnData.autoincrement !== columndetails.autoincrement) || (columnData.autoincrement === undefined && columndetails.autoincrement === true)) {
155
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
156
+ console.log(cstyler.red("Autoincrement have some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.autoincrement), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.autoincrement),);
157
+ return false;
158
+ }
159
+
160
+ // 9. COMMENT
161
+ const comA = columnData.comment ?? "";
162
+ const comB = columndetails.comment ?? "";
163
+ if (comA !== comB) {
164
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
165
+ console.log(cstyler.red("Comment have some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData.comment), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails.comment),);
166
+ return false;
167
+ }
168
+
169
+ // 10. CHARACTER SET
170
+ if (columnData._charset_ !== undefined &&
171
+ columnData._charset_ !== columndetails._charset_) {
172
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
173
+ console.log(cstyler.red("Character set have some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData._charset_), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails._charset_),);
174
+ return false;
175
+ }
176
+
177
+ // 11. COLLATION
178
+ if (columnData._collate_ !== undefined &&
179
+ columnData._collate_ !== columndetails._collate_) {
180
+ console.log(cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(columnName));
181
+ console.log(cstyler.red("Collate have some changes"), cstyler.hex("#00b7ff")("Given data:"), cstyler.hex("#ffffff")(columnData._collate_), cstyler.hex("#00b7ff")("Server data:"), cstyler.hex("#ffffff")(columndetails._collate_),);
182
+ return false;
183
+ }
184
+
185
+ return true;
186
+ }
187
+ // Identifier validator (letters, digits, underscore, dollar, max 64 chars)
188
+ const validIdent = name => typeof name === 'string' && /^[A-Za-z0-9$_]{1,64}$/.test(name);
189
+ async function alterColumnQuery(dbConfig, columndata, columnName, tableName, database, options = {}) {
190
+ try {
191
+ // Basic validation
192
+ if (!validIdent(columnName)) throw new Error('Invalid columnName');
193
+ if (!validIdent(tableName)) throw new Error('Invalid tableName');
194
+ if (!validIdent(database)) throw new Error('Invalid database');
195
+
196
+ if (!columndata || !columndata.columntype) {
197
+ throw new Error('columntype is required for MODIFY COLUMN');
198
+ }
199
+
200
+ if (typeof fncs.inspectColumnConstraint !== 'function') {
201
+ throw new Error('fncs.inspectColumnConstraint function not found in ./checkConstraints (require updated module)');
202
+ }
203
+
204
+ // Query the DB to see whether the column participates in any constraint/index/check.
205
+ // Default: loose=true meaning any constraint/index that includes the column counts.
206
+ const loose = options.loose !== false;
207
+ const info = await fncs.inspectColumnConstraint(dbConfig, database, tableName, columnName, { loose });
208
+
209
+ const columnHasConstraint = !!(info && info.found);
210
+
211
+ // Helper functions
212
+ const escapeSqlString = s => String(s).replace(/'/g, "''");
213
+ const quoteId = id => {
214
+ if (!validIdent(id)) throw new Error('Invalid identifier: ' + id);
215
+ return `\`${id}\``;
216
+ };
217
+
218
+ // Build column definition (same approach as previous function)
219
+ let colDef = `${quoteId(columnName)} ${columndata.columntype}`;
220
+
221
+ // length_value handling
222
+ if (columndata.hasOwnProperty('length_value')) {
223
+ const lv = columndata.length_value;
224
+ if (typeof lv === 'number') {
225
+ colDef += `(${lv})`;
226
+ } else if (Array.isArray(lv) && lv.length === 2 && lv.every(n => typeof n === 'number')) {
227
+ colDef += `(${lv[0]},${lv[1]})`;
228
+ } else if (Array.isArray(lv) && lv.every(s => typeof s === 'string')) {
229
+ const escaped = lv.map(v => `'${escapeSqlString(v)}'`);
230
+ colDef += `(${escaped.join(',')})`;
231
+ } else {
232
+ throw new Error('Invalid length_value');
233
+ }
234
+ }
235
+
236
+ // UNSIGNED / ZEROFILL
237
+ if (columndata.unsigned === true) colDef += ' UNSIGNED';
238
+ if (columndata.zerofill === true) colDef += ' ZEROFILL';
239
+
240
+ // CHARSET / COLLATE
241
+ if (columndata._charset_) {
242
+ if (!/^[A-Za-z0-9_]+$/.test(columndata._charset_)) throw new Error('Invalid charset');
243
+ colDef += ` CHARACTER SET ${columndata._charset_}`;
244
+ }
245
+ if (columndata._collate_) {
246
+ if (!/^[A-Za-z0-9_]+$/.test(columndata._collate_)) throw new Error('Invalid collate');
247
+ colDef += ` COLLATE ${columndata._collate_}`;
248
+ }
249
+
250
+ // NULL / NOT NULL (only include if explicitly provided)
251
+ if (columndata.hasOwnProperty('nulls')) {
252
+ if (columndata.nulls === false) colDef += ' NOT NULL';
253
+ else colDef += ' NULL';
254
+ }
255
+
256
+ // DEFAULT handling
257
+ if (columndata.hasOwnProperty('defaults')) {
258
+ const d = columndata.defaults;
259
+ if (d === null) {
260
+ colDef += ' DEFAULT NULL';
261
+ } else if (typeof d === 'number') {
262
+ colDef += ` DEFAULT ${d}`;
263
+ } else if (typeof d === 'boolean') {
264
+ colDef += ` DEFAULT ${d ? 1 : 0}`;
265
+ } else if (typeof d === 'string') {
266
+ if (columndata.defaults_is_expression === true) {
267
+ colDef += ` DEFAULT ${d}`;
268
+ } else if (/^CURRENT_TIMESTAMP$/i.test(d) && /^(TIMESTAMP|DATETIME)/i.test(columndata.columntype)) {
269
+ colDef += ` DEFAULT ${d.toUpperCase()}`;
270
+ } else {
271
+ colDef += ` DEFAULT '${escapeSqlString(d)}'`;
272
+ }
273
+ } else {
274
+ throw new Error('Unsupported default type');
275
+ }
276
+ }
277
+
278
+ // ON UPDATE
279
+ if (columndata.on_update && typeof columndata.on_update === 'string') {
280
+ if (columndata.on_update_is_expression === true) {
281
+ colDef += ` ON UPDATE ${columndata.on_update}`;
282
+ } else if (/^CURRENT_TIMESTAMP$/i.test(columndata.on_update)) {
283
+ colDef += ` ON UPDATE ${columndata.on_update.toUpperCase()}`;
284
+ } else {
285
+ throw new Error('Unsupported on_update value (must be expression-flagged)');
286
+ }
287
+ }
288
+
289
+ // AUTO_INCREMENT
290
+ if (columndata.autoincrement === true) {
291
+ colDef += ' AUTO_INCREMENT';
292
+ }
293
+
294
+ // COMMENT
295
+ if (columndata.comment) {
296
+ colDef += ` COMMENT '${escapeSqlString(columndata.comment)}'`;
297
+ }
298
+
299
+ // Build ALTER actions (we will return a single ALTER TABLE ... action list)
300
+ const actions = [];
301
+ actions.push(`MODIFY COLUMN ${colDef}`);
302
+
303
+ // Determine whether the caller wants a UNIQUE index/constraint
304
+ const wantsUnique = (
305
+ columndata.unique === true ||
306
+ (typeof columndata.index === 'string' && columndata.index.toUpperCase() === 'UNIQUE') ||
307
+ (typeof columndata.index === 'object' && (columndata.index.type || '').toUpperCase() === 'UNIQUE')
308
+ );
309
+
310
+ // If the caller asked for an index that's NOT UNIQUE, or asked for UNIQUE and column has no constraints,
311
+ // we add the appropriate ADD action. If the column already has any constraint/index and wantsUnique,
312
+ // we DO NOT add the UNIQUE (per your requirement).
313
+ if (columndata.index) {
314
+ // Helper to build column list string
315
+ const buildColsSql = cols => {
316
+ const arr = Array.isArray(cols) ? cols : [cols];
317
+ if (arr.length === 0) throw new Error('Index columns required');
318
+ arr.forEach(c => { if (!validIdent(c)) throw new Error('Invalid index column: ' + c); });
319
+ return arr.map(c => quoteId(c)).join(', ');
320
+ };
321
+
322
+ if (wantsUnique) {
323
+ if (columnHasConstraint) {
324
+ // Skip adding UNIQUE because column already participates in a constraint/index
325
+ if (options.log !== false) {
326
+ console.info(`Skipping ADD UNIQUE for ${database}.${tableName}.${columnName} because it already has constraints/indexes.`);
327
+ }
328
+ } else {
329
+ // Add UNIQUE on the column (single-column unique)
330
+ const idxName = (`uq_${tableName}_${columnName}`).slice(0, 64);
331
+ actions.push(`ADD UNIQUE KEY ${quoteId(idxName)} (${quoteId(columnName)})`);
332
+ }
333
+ } else {
334
+ // Non-unique index or other index types: honor the spec in columndata.index
335
+ if (typeof columndata.index === 'boolean' && columndata.index === true) {
336
+ actions.push(`ADD INDEX (${quoteId(columnName)})`);
337
+ } else if (typeof columndata.index === 'string') {
338
+ const t = columndata.index.toUpperCase();
339
+ if (t === 'PRIMARY') {
340
+ actions.push(`ADD PRIMARY KEY (${quoteId(columnName)})`);
341
+ } else if (['INDEX', 'FULLTEXT', 'SPATIAL'].includes(t)) {
342
+ actions.push(`ADD ${t} (${quoteId(columnName)})`);
343
+ } else {
344
+ throw new Error('Unsupported index type string: ' + columndata.index);
345
+ }
346
+ } else if (typeof columndata.index === 'object' && columndata.index !== null) {
347
+ const type = (columndata.index.type || 'INDEX').toUpperCase();
348
+ const colsSql = buildColsSql(columndata.index.columns || [columnName]);
349
+ let namePart = '';
350
+ if (type !== 'PRIMARY') {
351
+ const raw = (columndata.index.name || `idx_${tableName}_${columnName}`).slice(0, 64);
352
+ namePart = ` ${quoteId(raw)}`;
353
+ }
354
+ if (type === 'PRIMARY') actions.push(`ADD PRIMARY KEY (${colsSql})`);
355
+ else actions.push(`ADD ${type}${namePart} (${colsSql})`);
356
+ }
357
+ }
358
+ }
359
+
360
+ // Return single ALTER TABLE statement (no multi-statement)
361
+ const sql = `ALTER TABLE ${quoteId(tableName)} ${actions.join(', ')};`;
362
+ const runquery = await fncs.runQuery(dbConfig, database, sql);
363
+ return runquery;
364
+ } catch (err) {
365
+ console.error('alterColumnQuery error:', err.message);
366
+ return null;
367
+ }
368
+ }
369
+ async function addForeignKeyWithIndexQuery(config, databaseName, tableName, columnName, refTable, refColumn, options = {}) {
370
+ const {
371
+ onDelete = "RESTRICT",
372
+ onUpdate = "RESTRICT"
373
+ } = options;
374
+
375
+ const indexName = `idx_${tableName}_${columnName}`;
376
+
377
+ // Combine both ADD INDEX and ADD FOREIGN KEY into one ALTER TABLE statement
378
+ // Note: We use a comma to separate multiple actions in one query
379
+ const combinedQuery = `
380
+ ALTER TABLE \`${tableName}\`
381
+ ADD INDEX \`${indexName}\` (\`${columnName}\`),
382
+ ADD FOREIGN KEY (\`${columnName}\`)
383
+ REFERENCES \`${refTable}\` (\`${refColumn}\`)
384
+ ON DELETE ${onDelete}
385
+ ON UPDATE ${onUpdate}
386
+ `.trim();
387
+
388
+ // Now we only send one single command to runQuery
389
+ const runquery = await fncs.runQuery(config, databaseName, combinedQuery);
390
+ return runquery;
391
+ }
392
+ async function alterColumnIfNeeded(config, jsondata, forceupdatecolumn, separator) {
393
+ try {
394
+ console.log(cstyler.bold.yellow("Let's initiate Alter Column to table if needed..."));
395
+ for (const jsondb of Object.keys(jsondata)) {
396
+ const loopdb = fncs.perseTableNameWithLoop(jsondb, separator);
397
+ if (loopdb === false) {
398
+ console.error("There must be some mistake. Please re install the module.")
399
+ }
400
+ const databaseName = loopdb.loopname;
401
+ const getalltable = await fncs.getTableNames(config, databaseName);
402
+ if (getalltable === null) {
403
+ console.error(cstyler.red(`Failed to get table names for database ${databaseName}. Skipping...`));
404
+ return null;
405
+ }
406
+ for (const jsontable of Object.keys(jsondata[jsondb])) {
407
+ if (!fncs.isJsonObject(jsondata[jsondb][jsontable])) { continue; }
408
+ // parse loop table name
409
+ const looptable = fncs.perseTableNameWithLoop(jsontable, separator);
410
+ if (looptable === false) {
411
+ console.error("There must be some mistake. Please re install the module.")
412
+ }
413
+ const tableName = looptable.loopname;
414
+ // check if table exist
415
+ if (!getalltable.includes(tableName)) {
416
+ console.error(cstyler.red(`Table ${tableName} does not exist in database ${databaseName}. Skipping...`));
417
+ continue;
418
+ }
419
+ // get all columns from the table
420
+ const allcols = await fncs.getColumnNames(config, databaseName, tableName);
421
+ if (allcols === null) {
422
+ console.error(cstyler.red(`Failed to get column names for table ${tableName} in database ${databaseName}. Skipping...`));
423
+ return null;
424
+ }
425
+ for (const jsoncolumn of Object.keys(jsondata[jsondb][jsontable])) {
426
+ if (!fncs.isJsonObject(jsondata[jsondb][jsontable][jsoncolumn])) { continue; }
427
+ if (!allcols.includes(jsoncolumn)) {
428
+ // column does not exist, skip it
429
+ console.error(cstyler.red(`Column ${jsoncolumn} does not exist in table ${tableName} of database ${databaseName}. Skipping...`));
430
+ continue;
431
+ }
432
+ // lets add the column
433
+ const columndata = jsondata[jsondb][jsontable][jsoncolumn];
434
+ const serverdata = await fncs.getColumnDetails(config, databaseName, tableName, jsoncolumn);
435
+ const fkdetails = await fncs.getForeignKeyDetails(config, databaseName, tableName, jsoncolumn);
436
+ const getallrefcol = await fncs.findReferencingFromColumns(config, databaseName, tableName, jsoncolumn);
437
+ if (getallrefcol === null) {
438
+ console.error("Server error: Having problem finding referencing columns from ", cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
439
+ return null;
440
+ }
441
+ if (serverdata === null || fkdetails === null) {
442
+ console.error(cstyler.red(`Failed to get details for column ${jsoncolumn} in table ${tableName} of database ${databaseName}. Skipping...`));
443
+ return null;
444
+ }
445
+ const isColSame = await isColumnDataSame(config, databaseName, tableName, jsoncolumn, columndata, serverdata, fkdetails);
446
+ if (isColSame === null) {
447
+ return null;
448
+ }
449
+ if (!isColSame) {
450
+ console.log(cstyler.yellow("Column alteration needed for "), cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
451
+ if (forceupdatecolumn === true) {
452
+ if (getallrefcol.length > 0) {
453
+ // there are referencing columns, we need to drop foreign keys from referencing columns first
454
+ for (const refcol of getallrefcol) {
455
+ const dropfk = await fncs.removeForeignKeyFromColumn(config, refcol.child_schema, refcol.child_table, refcol.child_columns[0]);
456
+ const delkey = await fncs.removeForeignKeyConstraintFromColumn(config, refcol.child_schema, refcol.child_table, refcol.child_columns[0]);
457
+ if (dropfk === null || delkey === null) {
458
+ console.error("Having problem removing foreign key from ", cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(refcol.child_schema), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(refcol.child_table), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(refcol.child_columns[0]));
459
+ return null;
460
+ }
461
+ }
462
+ }
463
+ // lets update the column now
464
+ // first remove foreign key from the column if exist
465
+ if (fncs.isJsonObject(fkdetails)) {
466
+ const delfk = await fncs.removeForeignKeyFromColumn(config, databaseName, tableName, jsoncolumn);
467
+ const delkey = await fncs.removeForeignKeyConstraintFromColumn(config, databaseName, tableName, jsoncolumn);
468
+ if (delfk === null || delkey === null) {
469
+ console.error("There was an issue when removing foreign key from", cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn));
470
+ return null;
471
+ }
472
+ }
473
+ // now alter the column
474
+ const alterquery = await alterColumnQuery(config, columndata, jsoncolumn, tableName, databaseName);
475
+ if (alterquery === null) {
476
+ console.error("There was an issue when creating alter column for", cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn));
477
+ return null;
478
+ }
479
+ // now re add foreign key to the column if exist
480
+ if (columndata.hasOwnProperty("foreign_key")) {
481
+ const fkdata = columndata.foreign_key;
482
+ const fkquery = await addForeignKeyWithIndexQuery(config, databaseName, tableName, jsoncolumn, fkdata.table, fkdata.column, {
483
+ onDelete: fkdata.deleteOption,
484
+ onUpdate: fkdata.updateOption
485
+ });
486
+ if (fkquery === null) {
487
+ console.error("There was an issue when creating foreign key for", cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn));
488
+ return null;
489
+ }
490
+ }
491
+ if (getallrefcol.length > 0) {
492
+ // lets re add the foreign keys to referencing columns
493
+ for (const refcol of getallrefcol) {
494
+ // Re-add foreign key constraint to referencing columns
495
+ const readdfk = await addForeignKeyWithIndexQuery(config, refcol.child_schema, refcol.child_table, refcol.child_columns[0], refcol.parent_table, refcol.parent_columns[0], {
496
+ onDelete: refcol.delete_rule,
497
+ onUpdate: refcol.update_rule
498
+ });
499
+ if (readdfk === null) {
500
+ console.error("Having problem re adding foreign key to ", cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(refcol.child_schema), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(refcol.child_table), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(refcol.child_columns[0]));
501
+ return null;
502
+ }
503
+ }
504
+ }
505
+ } else {
506
+ // lets try to see if there is any referencing foreign key
507
+ if (getallrefcol.length > 0) {
508
+ console.error(cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn), cstyler.red("Column alteration needed but skipped due to forceupdatecolumn set to false and there are referencing foreign keys."));
509
+ } else {
510
+ // lets alter the column now
511
+ if (fncs.isJsonObject(fkdetails)) {
512
+ const delfk = await fncs.removeForeignKeyFromColumn(config, databaseName, tableName, jsoncolumn);
513
+ const delkey = await fncs.removeForeignKeyConstraintFromColumn(config, databaseName, tableName, jsoncolumn);
514
+ if (delfk === null || delkey === null) {
515
+ console.error(cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn), cstyler.red("There was an issue when removing foreign key",));
516
+ return null;
517
+ }
518
+ }
519
+ const alterquery = await alterColumnQuery(config, columndata, jsoncolumn, tableName, databaseName);
520
+ if (alterquery === null) {
521
+ console.error(cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn), cstyler.red("There was an issue when modifying column",));
522
+ return null;
523
+ }
524
+ if (columndata.hasOwnProperty("foreign_key")) {
525
+ const fkdata = columndata.foreign_key;
526
+ const fkquery = await addForeignKeyWithIndexQuery(config, databaseName, tableName, jsoncolumn, fkdata.table, fkdata.column, {
527
+ onDelete: fkdata.deleteOption,
528
+ onUpdate: fkdata.updateOption
529
+ });
530
+ if (fkquery === null) {
531
+ console.error(cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn), cstyler.red("There was an issue when creating foreign key",));
532
+ return null;
533
+ }
534
+ }
535
+ }
536
+ }
537
+ } else {
538
+ console.log(cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn), cstyler.yellow("Given column data and server data are same."), "Let's check foreign key now.");
539
+ // lets check if foreign key need update
540
+ if (fkdetails === false && !columndata.hasOwnProperty("foreign_key")) {
541
+ continue;
542
+ } else if (fkdetails === false && columndata.hasOwnProperty("foreign_key")) {
543
+ console.log(cstyler.yellow("Foreign key need to be added for "), cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
544
+ // need to add foreign key
545
+ const fkdata = columndata.foreign_key;
546
+ const addfk = await addForeignKeyWithIndexQuery(config, databaseName, tableName, jsoncolumn, fkdata.table, fkdata.column, {
547
+ onDelete: fkdata.deleteOption,
548
+ onUpdate: fkdata.updateOption
549
+ });
550
+ if (addfk === null) {
551
+ console.error("There was an issue when creating foreign key for", cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn));
552
+ return null;
553
+ }
554
+ } else if (fncs.isJsonObject(fkdetails) && columndata.hasOwnProperty("foreign_key")) {
555
+ // need to check if foreign key details are same
556
+ const fkdt = columndata.foreign_key;
557
+ if (fkdetails.table === fkdt.table &&
558
+ fkdetails.column === fkdt.column &&
559
+ fkdetails.deleteOption === fkdt.deleteOption &&
560
+ (fkdt.updateOption === undefined ||fkdetails.updateOption === fkdt.updateOption)) {
561
+ continue;
562
+ }
563
+ console.log(cstyler.yellow("Foreign key need to be updated for "), cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
564
+ console.log(cstyler.yellow("Foreign key details are different, updating foreign key for "), cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
565
+ // need to update foreign key
566
+ const dropfk = await fncs.removeForeignKeyFromColumn(config, databaseName, tableName, jsoncolumn);
567
+ if (dropfk === null) {
568
+ console.error("Having problem removing foreign key from ", cstyler.blue("Database: "), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue(" Table: "), cstyler.hex("#00d9ffff")(tableName), cstyler.blue(" Column Name: "), cstyler.hex("#00d9ffff")(jsoncolumn));
569
+ return null;
570
+ }
571
+ const fkdata = columndata.foreign_key;
572
+ const addfk = await addForeignKeyWithIndexQuery(config, databaseName, tableName, jsoncolumn, fkdata.table, fkdata.column, {
573
+ onDelete: fkdata.deleteOption,
574
+ onUpdate: fkdata.updateOption
575
+ });
576
+ if (addfk === null) {
577
+ console.error("There was an issue when creating foreign key for", cstyler.blue("Database:"), cstyler.hex("#00d9ffff")(databaseName), cstyler.blue("Table:"), cstyler.hex("#00d9ffff")(tableName), cstyler.blue("Column:"), cstyler.hex("#00d9ffff")(jsoncolumn));
578
+ return null;
579
+ }
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ console.log(cstyler.cyan("Altering Column to tables are completed successfully."));
586
+ return true;
587
+ } catch (err) {
588
+ console.error(err.message);
589
+ return null;
590
+ }
591
+ }
592
+
593
+ module.exports = {
594
+ alterColumnIfNeeded
595
+ }