dbtasker 1.0.0 → 2.5.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/README.md +521 -0
- package/columnop.js +748 -0
- package/dbop.js +236 -0
- package/enginesupport.js +237 -0
- package/function.js +927 -157
- package/index.js +117 -69
- package/package.json +15 -5
- package/tables.js +0 -1
- package/validation.js +1329 -0
- package/app.js +0 -32
- package/backup-tableoperation.js +0 -717
- package/check.js +0 -18
- package/checker.js +0 -359
- package/tableOperations.js +0 -614
- package/user_tables.js +0 -1655
package/tableOperations.js
DELETED
|
@@ -1,614 +0,0 @@
|
|
|
1
|
-
const path = require("path");
|
|
2
|
-
const fs = require("fs/promises"); // Importing fs.promises for async operations
|
|
3
|
-
const { pool, DBInfo } = require("./server_setup.js"); // Import the promise-based pool
|
|
4
|
-
const fncs = require("./functions.js");
|
|
5
|
-
const { table, error } = require("console");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const jsonClientfilePath = path.join(__dirname, "../tables.json");
|
|
9
|
-
let matchDatabase = path.join(__dirname, "./readonly");
|
|
10
|
-
const dropTable = false;
|
|
11
|
-
const dropColumn = true;
|
|
12
|
-
const createTable = true;
|
|
13
|
-
const alterTable = true;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
//generate table query
|
|
23
|
-
function generateCreateTableQuery(databaseName, tableName, schemaObject, dbType = "mysql") {
|
|
24
|
-
const errors = [];
|
|
25
|
-
|
|
26
|
-
// Validate inputs
|
|
27
|
-
if (!databaseName || typeof databaseName !== "string") {
|
|
28
|
-
errors.push("Invalid database name.");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!tableName || typeof tableName !== "string") {
|
|
32
|
-
errors.push("Invalid table name.");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
!schemaObject ||
|
|
37
|
-
typeof schemaObject !== "object" ||
|
|
38
|
-
Array.isArray(schemaObject)
|
|
39
|
-
) {
|
|
40
|
-
errors.push("Invalid schema object.");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (errors.length > 0) {
|
|
44
|
-
throw new Error(errors.join("\n"));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const columns = [];
|
|
48
|
-
const foreignKeys = [];
|
|
49
|
-
|
|
50
|
-
for (let columnName in schemaObject) {
|
|
51
|
-
const columnInfo = schemaObject[columnName];
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
typeof columnInfo === "object" &&
|
|
55
|
-
columnInfo !== null &&
|
|
56
|
-
!Array.isArray(columnInfo)
|
|
57
|
-
) {
|
|
58
|
-
const type = columnInfo.type;
|
|
59
|
-
|
|
60
|
-
if (!type || typeof type.name !== "string") {
|
|
61
|
-
errors.push(`Invalid type for column: ${columnName}`);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
let columnDef = `"${columnName}" ${type.name}`;
|
|
66
|
-
|
|
67
|
-
// Length/Precision
|
|
68
|
-
if (type.LengthValues !== undefined) {
|
|
69
|
-
columnDef += `(${type.LengthValues})`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// NULL/NOT NULL
|
|
73
|
-
columnDef += columnInfo.NULL === false ? " NOT NULL" : " NULL";
|
|
74
|
-
|
|
75
|
-
// DEFAULT
|
|
76
|
-
if (columnInfo.DEFAULT !== undefined) {
|
|
77
|
-
let defaultValue = columnInfo.DEFAULT;
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
typeof defaultValue === "string" &&
|
|
81
|
-
defaultValue.match(/CURRENT_TIMESTAMP/i)
|
|
82
|
-
) {
|
|
83
|
-
columnDef += ` DEFAULT ${defaultValue}`;
|
|
84
|
-
} else {
|
|
85
|
-
defaultValue = `'${defaultValue}'`;
|
|
86
|
-
columnDef += ` DEFAULT ${defaultValue}`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ON UPDATE (MySQL only)
|
|
91
|
-
if (dbType === "mysql" && columnInfo.on_update) {
|
|
92
|
-
if (typeof columnInfo.on_update === "string") {
|
|
93
|
-
columnDef += ` ON UPDATE ${columnInfo.on_update}`;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// COMMENT (MySQL only)
|
|
98
|
-
if (dbType === "mysql" && columnInfo.comment) {
|
|
99
|
-
const cmnt = columnInfo.comment.replace(/'/g, "");
|
|
100
|
-
columnDef += ` COMMENT '${cmnt}'`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// AUTO_INCREMENT (MySQL) or SERIAL (PostgreSQL)
|
|
104
|
-
if (columnInfo.AUTO_INCREMENT) {
|
|
105
|
-
if (dbType === "mysql") {
|
|
106
|
-
columnDef += " AUTO_INCREMENT";
|
|
107
|
-
} else if (dbType === "postgres") {
|
|
108
|
-
columnDef = `"${columnName}" SERIAL`;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// INDEX (MySQL only)
|
|
113
|
-
if (dbType === "mysql" && columnInfo.index) {
|
|
114
|
-
columnDef += ` ${columnInfo.index}`;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
columns.push(columnDef);
|
|
118
|
-
|
|
119
|
-
// Foreign Keys
|
|
120
|
-
if (columnInfo.foreign_key) {
|
|
121
|
-
const fk = columnInfo.foreign_key;
|
|
122
|
-
if (
|
|
123
|
-
fk &&
|
|
124
|
-
typeof fk === "object" &&
|
|
125
|
-
fk.REFERENCES &&
|
|
126
|
-
fk.REFERENCES.table &&
|
|
127
|
-
fk.REFERENCES.column
|
|
128
|
-
) {
|
|
129
|
-
let foreignKeyDef = `FOREIGN KEY ("${columnName}") REFERENCES "${fk.REFERENCES.table}"("${fk.REFERENCES.column}")`;
|
|
130
|
-
|
|
131
|
-
if (fk.delete === true) {
|
|
132
|
-
foreignKeyDef += " ON DELETE CASCADE";
|
|
133
|
-
} else if (fk.delete === null) {
|
|
134
|
-
foreignKeyDef += " ON DELETE SET NULL";
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (fk.update === "CASCADE") {
|
|
138
|
-
foreignKeyDef += " ON UPDATE CASCADE";
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
foreignKeys.push(foreignKeyDef);
|
|
142
|
-
} else {
|
|
143
|
-
errors.push(`Invalid foreign key for column "${columnName}": ${JSON.stringify(fk)}`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
} else {
|
|
147
|
-
errors.push(`Invalid column definition for: ${columnName}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (errors.length > 0) {
|
|
152
|
-
throw new Error(errors.join("\n"));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const tableDefinition = [...columns, ...foreignKeys].join(", ");
|
|
156
|
-
let createTableQuery = "";
|
|
157
|
-
|
|
158
|
-
if (dbType === "mysql") {
|
|
159
|
-
createTableQuery = `CREATE TABLE IF NOT EXISTS \`${tableName}\` (${tableDefinition}) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`;
|
|
160
|
-
} else if (dbType === "postgres") {
|
|
161
|
-
createTableQuery = `CREATE TABLE IF NOT EXISTS "${tableName}" (${tableDefinition});`;
|
|
162
|
-
} else {
|
|
163
|
-
throw new Error(`Unsupported database type: ${dbType}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return createTableQuery.replace(/''/g, "'");
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
//Generate modifying and droping table query
|
|
171
|
-
async function generateAlterTableQuery(databaseName, tableName, schema, dropColumn) {
|
|
172
|
-
try {
|
|
173
|
-
if (!schema) {
|
|
174
|
-
throw new Error(`Schema for table ${tableName} is undefined or null`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const fullTableName = `\`${databaseName}\`.\`${tableName}\``;
|
|
178
|
-
|
|
179
|
-
const existingColumns = await getColumnDetails(databaseName, tableName);
|
|
180
|
-
console.log(`Fetched column details for table: ${tableName}`);
|
|
181
|
-
const existingForeignKey = await getForeignKeyDetails(databaseName, tableName);
|
|
182
|
-
console.log(`Fetched foreign key details for table: ${tableName}`);
|
|
183
|
-
|
|
184
|
-
if (!existingColumns) {
|
|
185
|
-
throw new Error(`Failed to fetch column details for table ${tableName}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
let alterStatements = [];
|
|
189
|
-
let isModifyIncludefk = [];
|
|
190
|
-
let isIncludefk = [];
|
|
191
|
-
let dropforeignkeyconstraint = [];
|
|
192
|
-
let unmatchedforeignkey = [];
|
|
193
|
-
|
|
194
|
-
for (const [columnName, columnDetails] of Object.entries(schema)) {
|
|
195
|
-
if (!columnDetails) continue;
|
|
196
|
-
|
|
197
|
-
const existingColumn = existingColumns.find(col => col.column_name === columnName);
|
|
198
|
-
|
|
199
|
-
if (existingColumn) {
|
|
200
|
-
let isSameType = existingColumn.data_type.toLowerCase() === columnDetails.type?.name.toLowerCase();
|
|
201
|
-
|
|
202
|
-
let isSameLength = false;
|
|
203
|
-
if (
|
|
204
|
-
(existingColumn.character_maximum_length > 50000 &&
|
|
205
|
-
columnDetails.type?.LengthValues === undefined) ||
|
|
206
|
-
(existingColumn.character_maximum_length === null &&
|
|
207
|
-
columnDetails.type?.LengthValues === undefined) ||
|
|
208
|
-
existingColumn.character_maximum_length === columnDetails.type?.LengthValues
|
|
209
|
-
) {
|
|
210
|
-
isSameLength = true;
|
|
211
|
-
} else if (columnDetails.type?.name === "ENUM") {
|
|
212
|
-
let length_val = columnDetails.type?.LengthValues?.replace(/,\s+/g, ",");
|
|
213
|
-
if (`enum(${length_val})` === existingColumn.column_type) {
|
|
214
|
-
isSameLength = true;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
let isSameNull =
|
|
219
|
-
(existingColumn.is_nullable === "YES" && columnDetails.NULL !== false) ||
|
|
220
|
-
(existingColumn.is_nullable === "NO" && columnDetails.NULL === false);
|
|
221
|
-
|
|
222
|
-
let isDefaultMatch = false;
|
|
223
|
-
if (isNumber(columnDetails.DEFAULT)) {
|
|
224
|
-
columnDetails.DEFAULT = columnDetails.DEFAULT.toString();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
existingColumn.default_value === `'${columnDetails.DEFAULT}'` ||
|
|
229
|
-
existingColumn.default_value === columnDetails.DEFAULT ||
|
|
230
|
-
(["NULL", null].includes(existingColumn.default_value) && columnDetails.DEFAULT === undefined) ||
|
|
231
|
-
(existingColumn.default_value === "current_timestamp()" && columnDetails.DEFAULT === "CURRENT_TIMESTAMP")
|
|
232
|
-
) {
|
|
233
|
-
isDefaultMatch = true;
|
|
234
|
-
} else if (columnDetails.DEFAULT || columnDetails.DEFAULT === 0) {
|
|
235
|
-
isDefaultMatch = existingColumn.default_value === columnDetails.DEFAULT.toString();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
let isSameComment =
|
|
239
|
-
existingColumn.column_comment === columnDetails.comment?.replace(/'/g, "") ||
|
|
240
|
-
(existingColumn.column_comment === "" && columnDetails.comment === undefined);
|
|
241
|
-
|
|
242
|
-
if (columnDetails.foreign_key) {
|
|
243
|
-
isIncludefk.push(columnName);
|
|
244
|
-
for (const keys of existingForeignKey) {
|
|
245
|
-
if (keys.COLUMN_NAME == columnName) {
|
|
246
|
-
if (
|
|
247
|
-
keys.REFERENCED_TABLE_NAME !== columnDetails.foreign_key.REFERENCES.table ||
|
|
248
|
-
keys.REFERENCED_COLUMN_NAME !== columnDetails.foreign_key.REFERENCES.column ||
|
|
249
|
-
(keys.DELETE_RULE === "CASCADE" && columnDetails.foreign_key.delete !== true) ||
|
|
250
|
-
(keys.DELETE_RULE !== "CASCADE" && columnDetails.foreign_key.delete === true)
|
|
251
|
-
) {
|
|
252
|
-
dropforeignkeyconstraint.push(keys.CONSTRAINT_NAME);
|
|
253
|
-
unmatchedforeignkey.push(keys.COLUMN_NAME);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (
|
|
260
|
-
isSameType &&
|
|
261
|
-
isSameLength &&
|
|
262
|
-
isSameNull &&
|
|
263
|
-
isDefaultMatch &&
|
|
264
|
-
isSameComment
|
|
265
|
-
) continue;
|
|
266
|
-
|
|
267
|
-
if (columnDetails.foreign_key) {
|
|
268
|
-
isModifyIncludefk.push(columnName);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
let modifyStatement = `ALTER TABLE ${fullTableName} MODIFY COLUMN \`${columnName}\` ${columnDetails.type?.name}`;
|
|
272
|
-
|
|
273
|
-
if (
|
|
274
|
-
["enum", "varchar"].includes(columnDetails.type?.name) &&
|
|
275
|
-
!columnDetails.type?.LengthValues
|
|
276
|
-
) {
|
|
277
|
-
throw new Error(`ENUM or VARCHAR column "${columnName}" needs a LengthValues definition.`);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (columnDetails.type?.LengthValues !== undefined) {
|
|
281
|
-
modifyStatement += `(${columnDetails.type.LengthValues})`;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
modifyStatement += columnDetails.NULL === false ? " NOT NULL" : " NULL";
|
|
285
|
-
|
|
286
|
-
if (columnDetails.DEFAULT || columnDetails.DEFAULT === 0) {
|
|
287
|
-
if (columnDetails.DEFAULT === "CURRENT_TIMESTAMP") {
|
|
288
|
-
modifyStatement += ` DEFAULT CURRENT_TIMESTAMP`;
|
|
289
|
-
} else if (isJsonObject(columnDetails.DEFAULT)) {
|
|
290
|
-
throw new Error("Default value is restricted for BLOB, TEXT, JSON, etc.");
|
|
291
|
-
} else {
|
|
292
|
-
modifyStatement += ` DEFAULT '${columnDetails.DEFAULT}'`;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (columnDetails.on_update) {
|
|
297
|
-
modifyStatement += ` ON UPDATE ${columnDetails.on_update}`;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (columnDetails.comment) {
|
|
301
|
-
modifyStatement += ` COMMENT '${bypassQuotes(columnDetails.comment)}'`;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (columnDetails.AUTO_INCREMENT) {
|
|
305
|
-
modifyStatement += " AUTO_INCREMENT";
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
alterStatements.push(modifyStatement);
|
|
309
|
-
} else {
|
|
310
|
-
// New column
|
|
311
|
-
let addStatement = `ALTER TABLE ${fullTableName} ADD COLUMN \`${columnName}\` ${columnDetails.type?.name}`;
|
|
312
|
-
|
|
313
|
-
if (
|
|
314
|
-
["enum", "varchar"].includes(columnDetails.type?.name) &&
|
|
315
|
-
!columnDetails.type?.LengthValues
|
|
316
|
-
) {
|
|
317
|
-
throw new Error(`ENUM or VARCHAR column "${columnName}" needs a LengthValues definition.`);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (columnDetails.type?.LengthValues !== undefined) {
|
|
321
|
-
addStatement += `(${columnDetails.type.LengthValues})`;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
addStatement += columnDetails.NULL === false ? " NOT NULL" : " NULL";
|
|
325
|
-
|
|
326
|
-
if (columnDetails.DEFAULT || columnDetails.DEFAULT === 0) {
|
|
327
|
-
if (columnDetails.DEFAULT === "CURRENT_TIMESTAMP") {
|
|
328
|
-
addStatement += ` DEFAULT CURRENT_TIMESTAMP`;
|
|
329
|
-
} else if (isJsonObject(columnDetails.DEFAULT)) {
|
|
330
|
-
throw new Error("Default value is restricted for BLOB, TEXT, JSON, etc.");
|
|
331
|
-
} else {
|
|
332
|
-
addStatement += ` DEFAULT '${columnDetails.DEFAULT}'`;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (columnDetails.on_update) {
|
|
337
|
-
addStatement += ` ON UPDATE ${columnDetails.on_update}`;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (columnDetails.comment) {
|
|
341
|
-
addStatement += ` COMMENT '${bypassQuotes(columnDetails.comment)}'`;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (columnDetails.AUTO_INCREMENT) {
|
|
345
|
-
addStatement += " AUTO_INCREMENT";
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
alterStatements.push(addStatement);
|
|
349
|
-
|
|
350
|
-
if (columnDetails.foreign_key) {
|
|
351
|
-
isIncludefk.push(columnName);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// Handle foreign keys
|
|
357
|
-
const addForeignkeyquery = [];
|
|
358
|
-
const dropForeignkeyquery = [];
|
|
359
|
-
let findnewfk = [...isIncludefk];
|
|
360
|
-
|
|
361
|
-
if (existingForeignKey.length > 0) {
|
|
362
|
-
for (const fk of existingForeignKey) {
|
|
363
|
-
if (
|
|
364
|
-
isModifyIncludefk.includes(fk.COLUMN_NAME) ||
|
|
365
|
-
!isIncludefk.includes(fk.COLUMN_NAME)
|
|
366
|
-
) {
|
|
367
|
-
if (!dropforeignkeyconstraint.includes(fk.CONSTRAINT_NAME)) {
|
|
368
|
-
dropforeignkeyconstraint.push(fk.CONSTRAINT_NAME);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
findnewfk = removefromarray(findnewfk, fk.COLUMN_NAME);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
for (const dropKey of dropforeignkeyconstraint) {
|
|
376
|
-
dropForeignkeyquery.push(`ALTER TABLE ${fullTableName} DROP FOREIGN KEY \`${dropKey}\``);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
let ibfk = 1;
|
|
380
|
-
for (const fkCol of [...findnewfk, ...isModifyIncludefk, ...unmatchedforeignkey]) {
|
|
381
|
-
const fk = schema[fkCol].foreign_key;
|
|
382
|
-
let fkStmt = `ALTER TABLE ${fullTableName} ADD CONSTRAINT \`${tableName}_ibfk${ibfk++}\` FOREIGN KEY (\`${fkCol}\`) REFERENCES \`${fk.REFERENCES.table}\`(\`${fk.REFERENCES.column}\`)`;
|
|
383
|
-
if (fk.delete === true) {
|
|
384
|
-
fkStmt += " ON DELETE CASCADE";
|
|
385
|
-
} else if (fk.delete === null) {
|
|
386
|
-
fkStmt += " ON DELETE SET NULL";
|
|
387
|
-
}
|
|
388
|
-
if (fk.on_update === null) {
|
|
389
|
-
fkStmt += " ON UPDATE SET NULL";
|
|
390
|
-
}
|
|
391
|
-
addForeignkeyquery.push(fkStmt);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (dropColumn) {
|
|
395
|
-
for (const col of existingColumns) {
|
|
396
|
-
if (!schema[col.column_name]) {
|
|
397
|
-
alterStatements.push(`ALTER TABLE ${fullTableName} DROP COLUMN \`${col.column_name}\``);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const result = [
|
|
403
|
-
...dropForeignkeyquery,
|
|
404
|
-
...alterStatements,
|
|
405
|
-
...addForeignkeyquery,
|
|
406
|
-
];
|
|
407
|
-
|
|
408
|
-
if (result.length === 0) {
|
|
409
|
-
console.log(`No changes needed for table "${tableName}".`);
|
|
410
|
-
return [];
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return result;
|
|
414
|
-
} catch (err) {
|
|
415
|
-
console.error(`Error generating alter table queries for ${tableName}:`, err.message);
|
|
416
|
-
throw err;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// Do anything with the table
|
|
421
|
-
async function createOrModifyTable(databaseName, queryText) {
|
|
422
|
-
try {
|
|
423
|
-
// Select the target database first
|
|
424
|
-
await pool.query(`USE \`${databaseName}\`;`);
|
|
425
|
-
|
|
426
|
-
await pool.query(queryText);
|
|
427
|
-
|
|
428
|
-
function getTableName(input) {
|
|
429
|
-
if (typeof input !== "string") {
|
|
430
|
-
throw new Error("Query text must be a string");
|
|
431
|
-
}
|
|
432
|
-
const words = input.trim().split(/\s+/);
|
|
433
|
-
if (words.length < 5) {
|
|
434
|
-
return [];
|
|
435
|
-
}
|
|
436
|
-
if (input.startsWith("CREATE TABLE IF NOT EXISTS") && words.length > 5) {
|
|
437
|
-
return [words[5]];
|
|
438
|
-
} else {
|
|
439
|
-
return [words[2], words[5]];
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const table_name = getTableName(queryText);
|
|
444
|
-
|
|
445
|
-
if (table_name.length > 1) {
|
|
446
|
-
return {
|
|
447
|
-
success: true,
|
|
448
|
-
message: `${table_name[1]} column of ${table_name[0]} table created or modified successfully.`,
|
|
449
|
-
querytext: queryText,
|
|
450
|
-
};
|
|
451
|
-
} else if (table_name.length === 1) {
|
|
452
|
-
return {
|
|
453
|
-
success: true,
|
|
454
|
-
message: `${table_name[0]} table created or modified successfully.`,
|
|
455
|
-
querytext: queryText,
|
|
456
|
-
};
|
|
457
|
-
} else {
|
|
458
|
-
return {
|
|
459
|
-
success: true,
|
|
460
|
-
message: `Table operation successful.`,
|
|
461
|
-
querytext: queryText,
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
} catch (err) {
|
|
465
|
-
return {
|
|
466
|
-
success: false,
|
|
467
|
-
message: err.message,
|
|
468
|
-
querytext: queryText,
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
async function createTables(databaseName, tableQueries) {
|
|
475
|
-
console.log(`Creating or Modifying Tables in Database: ${databaseName}`);
|
|
476
|
-
|
|
477
|
-
for (const query of tableQueries) {
|
|
478
|
-
console.log("Operating query is:");
|
|
479
|
-
console.log([query]);
|
|
480
|
-
console.log("...");
|
|
481
|
-
|
|
482
|
-
const result = await createOrModifyTable(databaseName, query);
|
|
483
|
-
|
|
484
|
-
if (!result.success) {
|
|
485
|
-
console.error(
|
|
486
|
-
"Error creating table:",
|
|
487
|
-
result.message,
|
|
488
|
-
"queryText:",
|
|
489
|
-
result.querytext
|
|
490
|
-
);
|
|
491
|
-
throw new Error("Error creating table");
|
|
492
|
-
} else {
|
|
493
|
-
console.log(result.message);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
async function tableOperation({ createTable, alterTable, dropTable, dropColumn, databaseName }) {
|
|
500
|
-
try {
|
|
501
|
-
let isTableModified = false;
|
|
502
|
-
let newJsonStoreFilePath = "";
|
|
503
|
-
|
|
504
|
-
const lastSavedFile = await getLastSavedFile(databaseName);
|
|
505
|
-
newJsonStoreFilePath = lastSavedFile
|
|
506
|
-
? path.join(databaseName, lastSavedFile)
|
|
507
|
-
: databaseName + path.join(__dirname, "/file.json");
|
|
508
|
-
|
|
509
|
-
const isSame = await compareJsonFiles(jsonClientfilePath, newJsonStoreFilePath);
|
|
510
|
-
if (isSame) {
|
|
511
|
-
console.log("\x1b[1m\x1b[32mThe JSON files are the same. No update needed. We are good to go...\x1b[0m");
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
console.log("The JSON files are different. Updating the database and the store file...");
|
|
516
|
-
const jsonData = await readJsonFile(jsonClientfilePath);
|
|
517
|
-
const objectTableNames = Object.keys(jsonData.tables);
|
|
518
|
-
const dbTableNames = await getTableNames(databaseName);
|
|
519
|
-
|
|
520
|
-
let queryList = [];
|
|
521
|
-
|
|
522
|
-
for (const tableName of objectTableNames) {
|
|
523
|
-
try {
|
|
524
|
-
const tableDef = jsonData.tables[tableName];
|
|
525
|
-
|
|
526
|
-
// Support LengthValue as array for enum/decimal
|
|
527
|
-
if (Array.isArray(tableDef.columns)) {
|
|
528
|
-
tableDef.columns = tableDef.columns.map((col) => {
|
|
529
|
-
if (Array.isArray(col.LengthValue)) {
|
|
530
|
-
col.LengthValue = col.LengthValue.join(",");
|
|
531
|
-
}
|
|
532
|
-
return col;
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
let query;
|
|
537
|
-
if (dbTableNames.includes(tableName.toLowerCase())) {
|
|
538
|
-
if (alterTable) {
|
|
539
|
-
query = await generateAlterTableQuery(
|
|
540
|
-
tableName.toLowerCase(),
|
|
541
|
-
tableDef,
|
|
542
|
-
dropColumn,
|
|
543
|
-
databaseName
|
|
544
|
-
);
|
|
545
|
-
console.log(`Alter query generated for table: ${tableName}`);
|
|
546
|
-
}
|
|
547
|
-
} else if (createTable) {
|
|
548
|
-
query = await generateCreateTableQuery(
|
|
549
|
-
tableName.toLowerCase(),
|
|
550
|
-
tableDef,
|
|
551
|
-
databaseName
|
|
552
|
-
);
|
|
553
|
-
console.log(`Create query generated for new table: ${tableName}`);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (query) queryList.push(query);
|
|
557
|
-
} catch (err) {
|
|
558
|
-
console.error(`Error generating query for table ${tableName}:`, err.message);
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Execute the queries
|
|
564
|
-
if (queryList.length) {
|
|
565
|
-
try {
|
|
566
|
-
await createTables(queryList.flat(), databaseName);
|
|
567
|
-
console.log("All tables created or modified successfully.");
|
|
568
|
-
isTableModified = true;
|
|
569
|
-
} catch (err) {
|
|
570
|
-
console.error("Error in creating/modifying tables:", err.message);
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
} else {
|
|
574
|
-
console.log("No table changes needed.");
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Drop unused tables
|
|
578
|
-
if (dropTable) {
|
|
579
|
-
try {
|
|
580
|
-
const tablesToDrop = dbTableNames.filter(
|
|
581
|
-
(dbTable) => !objectTableNames.includes(dbTable)
|
|
582
|
-
);
|
|
583
|
-
|
|
584
|
-
if (tablesToDrop.length > 0) {
|
|
585
|
-
await dropTables(tablesToDrop, databaseName);
|
|
586
|
-
console.log("Dropped tables:", tablesToDrop);
|
|
587
|
-
} else {
|
|
588
|
-
console.log("No tables to drop.");
|
|
589
|
-
}
|
|
590
|
-
} catch (err) {
|
|
591
|
-
console.error("Error during dropTable operation:", err.message);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Update store file
|
|
596
|
-
if (isTableModified) {
|
|
597
|
-
try {
|
|
598
|
-
const dateTime = getDateTime("_");
|
|
599
|
-
const filename = `${databaseName}/${dateTime.date}__${dateTime.time}_storeTableJSON.json`;
|
|
600
|
-
const jsonData = await readJsonFile(jsonClientfilePath);
|
|
601
|
-
await writeJsonFile(filename, jsonData);
|
|
602
|
-
console.log("Updated store file at:", filename);
|
|
603
|
-
} catch (err) {
|
|
604
|
-
console.error("Error saving updated JSON store file:", err.message);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
} catch (error) {
|
|
608
|
-
console.error("Error in tableOperation:", error.message);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
//tableOperation(true, true, true, true);
|
|
613
|
-
module.exports = { tableOperation };
|
|
614
|
-
//tableOperation(createTable, alterTable, dropTable, dropColumn);
|