extract-mysql-schema 0.1.0 → 0.3.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/index.js +281 -67
- package/package.json +4 -1
- package/run.js +34 -2
package/index.js
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const SequelizeAdapter = require("sequelize");
|
|
3
|
+
const orderBy = require("lodash.orderby");
|
|
4
|
+
|
|
5
|
+
const spaceTabs = function(list) {
|
|
6
|
+
const cols=[];
|
|
7
|
+
let lines = [];
|
|
8
|
+
list.forEach((line)=>{
|
|
9
|
+
let line_cols = line.split('\t');
|
|
10
|
+
for(let i=0;i<line_cols.length;i++) {
|
|
11
|
+
let col = line_cols[i].trim();
|
|
12
|
+
cols[i]=cols[i]||0;
|
|
13
|
+
if(col.length>cols[i])
|
|
14
|
+
cols[i]=col.length;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
list.forEach((line)=>{
|
|
19
|
+
let line_cols = line.split('\t');
|
|
20
|
+
for(let i=0;i<line_cols.length-1;i++) {
|
|
21
|
+
line_cols[i] = line_cols[i].trim().padEnd(cols[i]+1);//+'('+(cols[i]+1)+')';
|
|
22
|
+
}
|
|
23
|
+
lines.push(line_cols.join(''));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
|
|
3
29
|
|
|
4
30
|
const getAdapter = async function (connection) {
|
|
5
31
|
let adapter = new SequelizeAdapter(connection.database, connection.user, connection.password, {
|
|
@@ -15,57 +41,65 @@ const getAdapter = async function (connection) {
|
|
|
15
41
|
return adapter;
|
|
16
42
|
}
|
|
17
43
|
|
|
18
|
-
const
|
|
19
|
-
Object.keys(obj).reduce((acc, k) => {
|
|
20
|
-
acc[k.toLowerCase()] = obj[k];
|
|
21
|
-
return acc;
|
|
22
|
-
}, {});
|
|
23
|
-
|
|
24
|
-
const extractSchemas = async function (connection,options) {
|
|
44
|
+
const extractSchemas = async function (connection, options) {
|
|
25
45
|
const schemaName = connection.database;
|
|
26
|
-
options = options || {
|
|
46
|
+
options = options || {};
|
|
27
47
|
|
|
28
48
|
let adapter = await getAdapter(connection);
|
|
29
49
|
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
50
|
+
let queryProcedures = await adapter.query(`
|
|
51
|
+
SELECT * FROM INFORMATION_SCHEMA.ROUTINES where ROUTINE_SCHEMA = '${schemaName}'
|
|
52
|
+
`);
|
|
53
|
+
queryProcedures=queryProcedures[0];
|
|
54
|
+
|
|
55
|
+
let queryParameters = await adapter.query(`
|
|
56
|
+
SELECT p.* FROM INFORMATION_SCHEMA.PARAMETERS as p join INFORMATION_SCHEMA.ROUTINES as r on p.SPECIFIC_NAME=r.SPECIFIC_NAME
|
|
57
|
+
WHERE ROUTINE_SCHEMA='${schemaName}'
|
|
58
|
+
ORDER BY p.SPECIFIC_NAME,p.ORDINAL_POSITION
|
|
59
|
+
`);
|
|
60
|
+
queryParameters=queryParameters[0];
|
|
42
61
|
|
|
43
|
-
let
|
|
62
|
+
let queryFkey = await adapter.query(`
|
|
44
63
|
SELECT iif.*, iifc.FOR_COL_NAME, iifc.REF_COL_NAME
|
|
45
64
|
FROM INFORMATION_SCHEMA.INNODB_FOREIGN as iif
|
|
46
65
|
JOIN INFORMATION_SCHEMA.INNODB_FOREIGN_COLS as iifc on iifc.ID=iif.ID
|
|
47
|
-
WHERE iif.ID
|
|
66
|
+
WHERE iif.ID LIKE '${schemaName}/%'
|
|
48
67
|
`);
|
|
49
|
-
|
|
68
|
+
queryFkey=queryFkey[0];
|
|
50
69
|
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
let queryIndexes = await adapter.query(`
|
|
71
|
+
select T2.TABLE_SCHEMA,T2.TABLE_NAME,I.NAME as INDEX_NAME,F.NAME AS FIELD_NAME,F.POS,
|
|
72
|
+
CASE WHEN I.TYPE=2 OR I.TYPE=3 THEN 'YES' ELSE 'NO' END AS IS_UNIQUE,
|
|
73
|
+
CASE WHEN I.TYPE=3 THEN 'YES' ELSE 'NO' END AS IS_PRIMARY,
|
|
74
|
+
CASE WHEN I.TYPE=0 THEN 'YES' ELSE 'NO' END AS IS_FK
|
|
75
|
+
from INFORMATION_SCHEMA.INNODB_INDEXES I
|
|
76
|
+
JOIN INFORMATION_SCHEMA.INNODB_FIELDS F on F.INDEX_ID=I.INDEX_ID
|
|
77
|
+
JOIN INFORMATION_SCHEMA.INNODB_TABLES T1 ON T1.TABLE_ID=I.TABLE_ID
|
|
78
|
+
LEFT JOIN INFORMATION_SCHEMA.TABLES T2 ON T1.NAME=CONCAT(T2.TABLE_SCHEMA,'/',T2.TABLE_NAME)
|
|
79
|
+
WHERE T2.TABLE_SCHEMA = '${schemaName}'
|
|
80
|
+
ORDER BY T2.TABLE_SCHEMA,T2.TABLE_NAME,I.NAME,F.POS
|
|
56
81
|
`);
|
|
57
|
-
|
|
82
|
+
queryIndexes=queryIndexes[0];
|
|
83
|
+
|
|
84
|
+
let queryColumns = await adapter.query(`
|
|
85
|
+
SELECT T.TABLE_TYPE,C.*
|
|
86
|
+
FROM INFORMATION_SCHEMA.COLUMNS C
|
|
87
|
+
LEFT JOIN INFORMATION_SCHEMA.TABLES T ON T.TABLE_SCHEMA=C.TABLE_SCHEMA AND T.TABLE_NAME=C.TABLE_NAME
|
|
88
|
+
where C.TABLE_SCHEMA ='${schemaName}'
|
|
89
|
+
ORDER BY C.TABLE_NAME,C.ORDINAL_POSITION
|
|
90
|
+
`);
|
|
91
|
+
queryColumns = queryColumns[0];
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
await adapter.close();
|
|
60
94
|
|
|
61
95
|
const foreign = {};
|
|
62
|
-
for(let i=0;i<
|
|
63
|
-
const tableName =
|
|
64
|
-
const keyName =
|
|
65
|
-
foreign[tableName+"_"+
|
|
96
|
+
for(let i=0;i<queryFkey.length;i++) {
|
|
97
|
+
const tableName = queryFkey[i]['FOR_NAME'].substring(schemaName.length+1);
|
|
98
|
+
const keyName = queryFkey[i]['ID'].substring(schemaName.length+1);
|
|
99
|
+
foreign[tableName+"_"+queryFkey[i]['FOR_COL_NAME']] = {
|
|
66
100
|
"schemaName": schemaName,
|
|
67
|
-
"tableName":
|
|
68
|
-
"columnName":
|
|
101
|
+
"tableName": queryFkey[i]['REF_NAME'].substring(schemaName.length+1),
|
|
102
|
+
"columnName": queryFkey[i]['FOR_COL_NAME'],
|
|
69
103
|
"onUpdate": "CASCADE",
|
|
70
104
|
"onDelete": "RESTRICT",
|
|
71
105
|
"name": keyName
|
|
@@ -73,60 +107,240 @@ const extractSchemas = async function (connection,options) {
|
|
|
73
107
|
}
|
|
74
108
|
|
|
75
109
|
let schema = {};
|
|
110
|
+
let wrappers = {};
|
|
76
111
|
let tables = [];
|
|
77
|
-
|
|
78
|
-
|
|
112
|
+
let views = [];
|
|
113
|
+
let hasParent = [];
|
|
114
|
+
for (let i = 0; i < queryColumns.length; i++) {
|
|
115
|
+
let name = queryColumns[i]['COLUMN_NAME'];
|
|
79
116
|
|
|
80
|
-
let tableName =
|
|
117
|
+
let tableName = queryColumns[i]['TABLE_NAME'];
|
|
81
118
|
let table = [];
|
|
82
|
-
|
|
83
|
-
|
|
119
|
+
let definition = [];
|
|
120
|
+
let wrapper = {};
|
|
121
|
+
if (schema[tableName]) {
|
|
122
|
+
table = schema[tableName];
|
|
123
|
+
wrapper = wrappers[tableName];
|
|
124
|
+
definition = wrapper.definition;
|
|
125
|
+
} else {
|
|
84
126
|
schema[tableName] = table;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
127
|
+
if(queryColumns[i]['TABLE']==="VIEW"){
|
|
128
|
+
wrapper = {
|
|
129
|
+
name: tableName,
|
|
130
|
+
schemaName: schemaName,
|
|
131
|
+
kind: "view",
|
|
132
|
+
columns: table,
|
|
133
|
+
definition,
|
|
134
|
+
informationSchemaValue: {
|
|
135
|
+
table_type: 'VIEW',
|
|
136
|
+
table_catalog: schemaName,
|
|
137
|
+
table_name: tableName,
|
|
138
|
+
table_schema: schemaName
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
wrappers[tableName] = wrapper;
|
|
142
|
+
views.push(wrapper);
|
|
143
|
+
} else {
|
|
144
|
+
wrapper = {
|
|
145
|
+
name: tableName,
|
|
146
|
+
schemaName: schemaName,
|
|
147
|
+
kind: "table",
|
|
148
|
+
columns: table,
|
|
149
|
+
definition,
|
|
150
|
+
informationSchemaValue: {
|
|
151
|
+
is_insertable_into: 'YES',
|
|
152
|
+
table_type: 'BASE',
|
|
153
|
+
table_catalog: schemaName,
|
|
154
|
+
table_name: tableName,
|
|
155
|
+
table_schema: schemaName
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
wrappers[tableName] = wrapper;
|
|
159
|
+
tables.push(wrapper);
|
|
96
160
|
}
|
|
97
|
-
tables.push(wrapper);
|
|
98
161
|
}
|
|
99
162
|
|
|
100
163
|
let column = {
|
|
101
164
|
name: name,
|
|
102
|
-
ordinalPosition:
|
|
103
|
-
sqltype:
|
|
104
|
-
maxLength:
|
|
105
|
-
isPrimaryKey:
|
|
106
|
-
isNullable:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
165
|
+
ordinalPosition: queryColumns[i]['ORDINAL_POSITION'],
|
|
166
|
+
sqltype: queryColumns[i]['COLUMN_TYPE'],
|
|
167
|
+
maxLength: queryColumns[i]['CHARACTER_MAXIMUM_LENGTH'],
|
|
168
|
+
isPrimaryKey: queryColumns[i]['COLUMN_KEY'] === 'PRI',
|
|
169
|
+
isNullable: queryColumns[i]['IS_NULLABLE'] === 'YES',
|
|
170
|
+
isAutoNumber: queryColumns[i]['EXTRA'] === 'auto_increment',
|
|
171
|
+
generated: queryColumns[i]['EXTRA'].indexOf('DEFAULT_GENERATED') >= 0 ? (queryColumns[i]['EXTRA'].indexOf('on update') > 0 ? "ALWAYS" : "BY DEFAULT") : "NEVER",
|
|
172
|
+
isUpdatable: queryColumns[i]['EXTRA'].indexOf('DEFAULT_GENERATED') < 0,
|
|
173
|
+
type: queryColumns[i]['DATA_TYPE'],
|
|
174
|
+
defaultValue: queryColumns[i]['COLUMN_DEFAULT'] || "",
|
|
111
175
|
references:[]
|
|
112
176
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
177
|
+
let extra = queryColumns[i]['EXTRA']||"";
|
|
178
|
+
extra=extra.replace(/DEFAULT_GENERATED\w?/g,'').replace(/auto_increment\w?/g,'');
|
|
179
|
+
let def = column.defaultValue?(column.defaultValue):"";
|
|
180
|
+
if(def!=="CURRENT_TIMESTAMP" && def) {
|
|
181
|
+
if(def.indexOf('(')>0) def=`(${def})`;
|
|
182
|
+
else if(column.type.indexOf('char')>=0 || column.type.indexOf('text')>=0) def=`'${def}'`;
|
|
116
183
|
}
|
|
184
|
+
if(def) def=`DEFAULT ${def}`;
|
|
185
|
+
definition.push(`${name}\t${column.sqltype}\t${column.isAutoNumber?" auto_increment":""}${def}\t${column.isNullable?"NULL":"NOT NULL"}${column.isPrimaryKey?" PRIMARY KEY":""}${extra}`);
|
|
186
|
+
|
|
117
187
|
if(foreign[tableName+"_"+name]!==undefined) {
|
|
118
188
|
column.references.push(foreign[tableName+"_"+name]);
|
|
189
|
+
if(hasParent.indexOf(tableName)<0) {
|
|
190
|
+
hasParent.push(tableName);
|
|
191
|
+
}
|
|
119
192
|
}
|
|
120
193
|
|
|
121
194
|
column = Object.fromEntries(Object.entries(column).filter(([_, v]) => v != null));
|
|
122
195
|
table.push(column);
|
|
123
196
|
}
|
|
124
197
|
|
|
198
|
+
Object.keys(wrappers).forEach((name)=>{
|
|
199
|
+
let wrapper = wrappers[name];
|
|
200
|
+
let definition = spaceTabs(wrapper.definition).join('\n ,');
|
|
201
|
+
definition = `CREATE TABLE IF NOT EXISTS ${name}\n(\n ${definition}\n);`;
|
|
202
|
+
|
|
203
|
+
let definitions = [];
|
|
204
|
+
definitions.push(definition);
|
|
205
|
+
|
|
206
|
+
let indexes = queryIndexes.filter((idx)=>idx['TABLE_NAME']===name);
|
|
207
|
+
indexes.forEach((idx)=>{
|
|
208
|
+
let isConstraint = idx['IS_UNIQUE']==='YES' || idx['IS_PRIMARY']==='YES' || idx['IS_FK']==='YES';
|
|
209
|
+
|
|
210
|
+
if(isConstraint) {
|
|
211
|
+
if(idx['IS_PRIMARY']==='YES') return;
|
|
212
|
+
else if(idx['IS_UNIQUE']==='YES') {
|
|
213
|
+
definitions.push(`
|
|
214
|
+
alter table ${idx['TABLE_NAME']}
|
|
215
|
+
add constraint ${idx['INDEX_NAME']}
|
|
216
|
+
unique (${idx['FIELD_NAME']});
|
|
217
|
+
`)
|
|
218
|
+
} else {
|
|
219
|
+
let ref = foreign[name+"_"+idx['FIELD_NAME']];
|
|
220
|
+
//console.log("HERE",name+"_"+idx['FIELD_NAME'],ref);
|
|
221
|
+
if(ref===undefined) return;
|
|
222
|
+
|
|
223
|
+
definitions.push(`
|
|
224
|
+
alter table ${idx['TABLE_NAME']}
|
|
225
|
+
add constraint ${idx['INDEX_NAME']}
|
|
226
|
+
foreign key (${idx['FIELD_NAME']}) references ${ref['tableName']} (${ref['columnName']});
|
|
227
|
+
`)
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
definitions.push(`
|
|
231
|
+
create index ${idx['INDEX_NAME']}
|
|
232
|
+
on ${idx['TABLE_NAME']} (${idx['FIELD_NAME']});
|
|
233
|
+
`)
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
wrapper.definition = definitions.join('\n');
|
|
238
|
+
// if(name==="application") console.log(wrapper.definition);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
let noparent = [];
|
|
242
|
+
for (let i = 0; i < tables.length; i++) {
|
|
243
|
+
if(hasParent.indexOf(tables[i].name)<0) {
|
|
244
|
+
noparent.push(tables[i].name);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
noparent.sort();
|
|
248
|
+
|
|
249
|
+
let byCounts = {};
|
|
250
|
+
for (let i = 0; i < hasParent.length; i++) {
|
|
251
|
+
let tableName = hasParent[i];
|
|
252
|
+
let table = schema[hasParent[i]];
|
|
253
|
+
for (let j = 0; j < table.length; j++) {
|
|
254
|
+
var column = table[j];
|
|
255
|
+
var references = column.references;
|
|
256
|
+
if(column.references.length==0) continue;
|
|
257
|
+
|
|
258
|
+
for (let k = 0; k < references.length; k++) {
|
|
259
|
+
var reference = references[k];
|
|
260
|
+
if(byCounts[reference.tableName]===undefined) byCounts[reference.tableName]={name:reference.tableName,count:0,children:[]};
|
|
261
|
+
byCounts[reference.tableName].count++;
|
|
262
|
+
byCounts[reference.tableName].children.push(tableName);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
byCounts = orderBy(byCounts,['count']).reverse();
|
|
267
|
+
let tableOrder = noparent;
|
|
268
|
+
for(let i=0;i<byCounts.length;i++){
|
|
269
|
+
if(tableOrder.indexOf(byCounts[i].name)<0)
|
|
270
|
+
tableOrder.push(byCounts[i].name);
|
|
271
|
+
|
|
272
|
+
let children = byCounts[i].children;
|
|
273
|
+
for(let j=0;j<children.length;j++){
|
|
274
|
+
let child=children[j];
|
|
275
|
+
if(tableOrder.indexOf(child)<0 && byCounts.indexOf(child)<0) {
|
|
276
|
+
tableOrder.push(child);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const procedures = [];
|
|
282
|
+
for(let i=0;i<queryProcedures.length;i++) {
|
|
283
|
+
const row = JSON.parse(JSON.stringify(queryProcedures[i]));
|
|
284
|
+
const name = row["SPECIFIC_NAME"];
|
|
285
|
+
let definition = row["ROUTINE_DEFINITION"];
|
|
286
|
+
const params = [];
|
|
287
|
+
let paramsDefinition = [];
|
|
288
|
+
|
|
289
|
+
for(let j=0;j<queryParameters.length;j++){
|
|
290
|
+
let paramISV = queryParameters[j];
|
|
291
|
+
if(paramISV["SPECIFIC_NAME"]!==name) continue;
|
|
292
|
+
let param = {
|
|
293
|
+
name: paramISV["PARAMETER_NAME"],
|
|
294
|
+
ordinalPosition: paramISV["ORDINAL_POSITION"],
|
|
295
|
+
sqltype: paramISV['DTD_IDENTIFIER'],
|
|
296
|
+
maxLength: paramISV['CHARACTER_MAXIMUM_LENGTH'],
|
|
297
|
+
type: paramISV['DATA_TYPE'],
|
|
298
|
+
mode: paramISV['PARAMETER_MODE']
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
paramsDefinition.push(`${param.mode} ${param.name} ${param.sqltype}`);
|
|
302
|
+
|
|
303
|
+
if(options.procedureISV) {
|
|
304
|
+
param.informationSchemaValue=paramISV;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
params.push(param);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
paramsDefinition = paramsDefinition.join('\n\t,');
|
|
311
|
+
|
|
312
|
+
definition = `
|
|
313
|
+
DELIMITER //
|
|
314
|
+
DROP PROCEDURE IF EXISTS ${name};
|
|
315
|
+
CREATE PROCEDURE ${name}(
|
|
316
|
+
\t ${paramsDefinition}
|
|
317
|
+
)
|
|
318
|
+
${definition}
|
|
319
|
+
//
|
|
320
|
+
DELIMITER;
|
|
321
|
+
`;
|
|
322
|
+
|
|
323
|
+
let routine = {
|
|
324
|
+
name,
|
|
325
|
+
schemaName: schemaName,
|
|
326
|
+
kind: "procedure",
|
|
327
|
+
definition,
|
|
328
|
+
params
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
if(options.procedureISV) {
|
|
332
|
+
routine.informationSchemaValue=row;
|
|
333
|
+
}
|
|
334
|
+
procedures.push(routine);
|
|
335
|
+
}
|
|
336
|
+
|
|
125
337
|
let result = {};
|
|
126
338
|
result[schemaName] = {
|
|
127
339
|
name: schemaName,
|
|
128
|
-
tables
|
|
129
|
-
|
|
340
|
+
tables,
|
|
341
|
+
tableOrder,
|
|
342
|
+
views,
|
|
343
|
+
procedures
|
|
130
344
|
}
|
|
131
345
|
return result;
|
|
132
346
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extract-mysql-schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": "./run.js",
|
|
@@ -20,5 +20,8 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"mysql2": "^3.6.3",
|
|
22
22
|
"sequelize": "^6.34.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"lodash.orderby": "^4.6.0"
|
|
23
26
|
}
|
|
24
27
|
}
|
package/run.js
CHANGED
|
@@ -5,6 +5,34 @@ const { extractSchemas } = require('./index.js');
|
|
|
5
5
|
async function main(options) {
|
|
6
6
|
const config = require(path.join(process.cwd(),options.configFile));
|
|
7
7
|
const result = await extractSchemas(config.connection,options);
|
|
8
|
+
|
|
9
|
+
if(options.writeSql){
|
|
10
|
+
if(result[config.connection.database].tables.length>0) {
|
|
11
|
+
// write table sql
|
|
12
|
+
const tablesPath=path.join(process.cwd(),"tables")
|
|
13
|
+
if (!fs.existsSync(tablesPath)){
|
|
14
|
+
fs.mkdirSync(tablesPath);
|
|
15
|
+
}
|
|
16
|
+
result[config.connection.database].tables.forEach(table => {
|
|
17
|
+
if(options.verbose) console.log("writing",path.join(tablesPath,table.name+".sql"));
|
|
18
|
+
fs.writeFileSync(path.join(tablesPath,table.name+".sql"), table.definition ,"utf8")
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if(result[config.connection.database].procedures.length>0) {
|
|
23
|
+
// write routines
|
|
24
|
+
const proceduresPath=path.join(process.cwd(),"procedures")
|
|
25
|
+
if (!fs.existsSync(proceduresPath)){
|
|
26
|
+
fs.mkdirSync(proceduresPath);
|
|
27
|
+
}
|
|
28
|
+
result[config.connection.database].procedures.forEach(proc => {
|
|
29
|
+
if(options.verbose) console.log("writing",path.join(proceduresPath,proc.name+".sql"));
|
|
30
|
+
fs.writeFileSync(path.join(proceduresPath,proc.name+".sql"), proc.definition ,"utf8")
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
8
36
|
if(options.outputFile) {
|
|
9
37
|
fs.writeFileSync(path.join(process.cwd(),options.outputFile), JSON.stringify(result,null,2) ,"utf8")
|
|
10
38
|
} else console.log(JSON.stringify(result,null,2));
|
|
@@ -13,8 +41,10 @@ async function main(options) {
|
|
|
13
41
|
let options = {
|
|
14
42
|
configFile:"",
|
|
15
43
|
outputFile:"",
|
|
16
|
-
columnISV:
|
|
17
|
-
tableISV:false
|
|
44
|
+
columnISV:true,
|
|
45
|
+
tableISV:false,
|
|
46
|
+
procedureISV:false,
|
|
47
|
+
writeSql:false
|
|
18
48
|
}
|
|
19
49
|
|
|
20
50
|
if (process.argv.length === 2) {
|
|
@@ -26,6 +56,8 @@ let argv = process.argv;
|
|
|
26
56
|
for(let i=2;i<argv.length;i++) {
|
|
27
57
|
if(argv[i]==="--columnISV") options.columnISV=true;
|
|
28
58
|
else if(argv[i]==="--tableISV") options.tableISV=true;
|
|
59
|
+
else if(argv[i]==="--procedureISV") options.procedureISV=true;
|
|
60
|
+
else if(argv[i]==="--writeSql") options.writeSql=true;
|
|
29
61
|
else
|
|
30
62
|
if(argv[i].substring(0,2)==="--") {
|
|
31
63
|
let name = argv[i].substring(2);
|