Skip to content

Commit f1e8e09

Browse files
b-admikeSakib Hasan
authored andcommitted
refactor alterTable (#45)
* refactor alterTable * Add child helper fns * Extract common fns to base Move getAddModifyColumns and getDropColumns to base connector
1 parent 1c3446d commit f1e8e09

1 file changed

Lines changed: 115 additions & 92 deletions

File tree

lib/migration.js

Lines changed: 115 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,15 @@
88
var async = require('async');
99

1010
module.exports = function(IBMDB) {
11-
IBMDB.prototype.getAddModifyColumns = function(model, fields) {};
12-
13-
IBMDB.prototype.getDropColumns = function(model, fields) {};
14-
1511
IBMDB.prototype.showFields = function(model, cb) {
1612
var self = this;
1713
var sql = 'SELECT COLNAME AS NAME, TYPENAME AS DATATYPE, ' +
18-
'COLNO, LENGTH AS DATALENGTH, NULLS FROM SYSCAT.COLUMNS ' +
19-
'WHERE TRIM(TABNAME) LIKE \'' +
20-
self.table(model) + '\' ' +
21-
'AND TRIM(TABSCHEMA) LIKE \'' +
22-
self.schema + '\'' +
23-
' ORDER BY COLNO';
14+
'COLNO, LENGTH AS DATALENGTH, NULLS FROM SYSCAT.COLUMNS ' +
15+
'WHERE TRIM(TABNAME) LIKE \'' +
16+
self.table(model) + '\' ' +
17+
'AND TRIM(TABSCHEMA) LIKE \'' +
18+
self.schema + '\'' +
19+
' ORDER BY COLNO';
2420
this.execute(sql, function(err, fields) {
2521
if (err) {
2622
return cb(err);
@@ -33,11 +29,11 @@ module.exports = function(IBMDB) {
3329
IBMDB.prototype.showIndexes = function(model, cb) {
3430
var self = this;
3531
var sql = 'SELECT TABNAME, TABSCHEMA, INDNAME, ' +
36-
'COLNAMES, UNIQUERULE FROM SYSCAT.INDEXES ' +
37-
'WHERE TRIM(TABNAME) LIKE \'' +
38-
self.table(model) + '\' ' +
39-
'AND TRIM(TABSCHEMA) LIKE \'' +
40-
self.schema + '\'';
32+
'COLNAMES, UNIQUERULE FROM SYSCAT.INDEXES ' +
33+
'WHERE TRIM(TABNAME) LIKE \'' +
34+
self.table(model) + '\' ' +
35+
'AND TRIM(TABSCHEMA) LIKE \'' +
36+
self.schema + '\'';
4137
this.execute(sql, function(err, indexes) {
4238
if (err) {
4339
return cb(err);
@@ -47,44 +43,14 @@ module.exports = function(IBMDB) {
4743
});
4844
};
4945

50-
IBMDB.prototype.alterTable = function(model, actualFields, actualIndexes,
51-
callback, checkOnly) {
46+
IBMDB.prototype.getColumnsToAdd = function(model, actualFields) {
5247
var self = this;
53-
var m = this.getModelDefinition(model);
48+
var m = self._models[model];
5449
var propNames = Object.keys(m.properties).filter(function(name) {
5550
return !!m.properties[name];
5651
});
57-
var indexes = m.settings.indexes || {};
58-
var indexNames = Object.keys(indexes).filter(function(name) {
59-
return !!m.settings.indexes[name];
60-
});
61-
var sql = [];
62-
var tasks = [];
63-
var operations = [];
64-
var ai = {};
65-
var type = '';
6652

67-
if (actualIndexes) {
68-
actualIndexes.forEach(function(i) {
69-
var name = i.INDNAME;
70-
if (!ai[name]) {
71-
ai[name] = {
72-
info: i,
73-
columns: [],
74-
};
75-
}
76-
77-
i.COLNAMES.split(/\+\s*/).forEach(function(columnName, j) {
78-
// This is a bit of a dirty way to get around this but DB2 returns
79-
// column names as a string started with and separated by a '+'.
80-
// The code below will strip out the initial '+' then store the
81-
// actual column names.
82-
if (j > 0)
83-
ai[name].columns[j - 1] = columnName;
84-
});
85-
});
86-
}
87-
var aiNames = Object.keys(ai);
53+
var operations = [];
8854

8955
// change/add new fields
9056
propNames.forEach(function(propName) {
@@ -102,10 +68,47 @@ module.exports = function(IBMDB) {
10268
actualize(propName, found);
10369
} else {
10470
operations.push('ADD COLUMN ' + propName + ' ' +
105-
self.buildColumnDefinition(model, propName));
71+
self.buildColumnDefinition(model, propName));
10672
}
10773
});
10874

75+
function actualize(propName, oldSettings) {
76+
var newSettings = m.properties[propName];
77+
if (newSettings && changed(newSettings, oldSettings)) {
78+
// TODO: NO TESTS EXECUTE THIS CODE PATH
79+
var pName = '\'' + propName + '\'';
80+
operations.push('CHANGE COLUMN ' + pName + ' ' + pName + ' ' +
81+
self.buildColumnDefinition(model, propName));
82+
}
83+
}
84+
85+
function changed(newSettings, oldSettings) {
86+
if (oldSettings.Null === 'YES') {
87+
// Used to allow null and does not now.
88+
if (!self.isNullable(newSettings)) {
89+
return true;
90+
}
91+
}
92+
if (oldSettings.Null === 'NO') {
93+
// Did not allow null and now does.
94+
if (self.isNullable(newSettings)) {
95+
return true;
96+
}
97+
}
98+
return false;
99+
}
100+
return operations;
101+
};
102+
103+
IBMDB.prototype.getColumnsToDrop = function(model, actualFields) {
104+
var self = this;
105+
var m = this._models[model];
106+
var propNames = Object.keys(m.properties).filter(function(name) {
107+
return !!m.properties[name];
108+
});
109+
110+
var operations = [];
111+
109112
// drop columns
110113
if (actualFields) {
111114
actualFields.forEach(function(f) {
@@ -116,23 +119,52 @@ module.exports = function(IBMDB) {
116119
}
117120
});
118121
}
122+
return operations;
123+
};
119124

120-
if (operations.length) {
121-
// Add the ALTER TABLE statement to the list of tasks to perform later.
122-
sql.push('ALTER TABLE ' + self.schema + '.' +
123-
self.tableEscaped(model) + ' ' + operations.join(' ') + ';');
124-
}
125+
IBMDB.prototype.addIndexes = function(model, actualIndexes) {
126+
var ai = {};
127+
var self = this;
128+
var m = this.getModelDefinition(model);
129+
var indexes = m.settings.indexes || {};
130+
var indexNames = Object.keys(indexes).filter(function(name) {
131+
return !!m.settings.indexes[name];
132+
});
133+
var operations = [];
134+
var propNames = Object.keys(m.properties).filter(function(name) {
135+
return !!m.properties[name];
136+
});
137+
var sql = [];
138+
var type = '';
125139

126-
operations = [];
140+
if (actualIndexes) {
141+
actualIndexes.forEach(function(i) {
142+
var name = i.INDNAME;
143+
if (!ai[name]) {
144+
ai[name] = {
145+
info: i,
146+
columns: [],
147+
};
148+
}
127149

150+
i.COLNAMES.split(/\+\s*/).forEach(function(columnName, j) {
151+
// This is a bit of a dirty way to get around this but DB2 returns
152+
// column names as a string started with and separated by a '+'.
153+
// The code below will strip out the initial '+' then store the
154+
// actual column names.
155+
if (j > 0)
156+
ai[name].columns[j - 1] = columnName;
157+
});
158+
});
159+
}
160+
var aiNames = Object.keys(ai);
128161
// remove indexes
129162
aiNames.forEach(function(indexName) {
130-
if (ai[indexName].info.UNIQUERULE === 'P'
131-
|| // indexName === 'PRIMARY' ||
163+
if (ai[indexName].info.UNIQUERULE === 'P' || // indexName === 'PRIMARY' ||
132164
(m.properties[indexName] && self.id(model, indexName))) return;
133165

134166
if (indexNames.indexOf(indexName) === -1 && !m.properties[indexName] ||
135-
m.properties[indexName] && !m.properties[indexName].index) {
167+
m.properties[indexName] && !m.properties[indexName].index) {
136168
if (ai[indexName].info.UNIQUERULE === 'P') {
137169
operations.push('DROP PRIMARY KEY');
138170
} else if (ai[indexName].info.UNIQUERULE === 'U') {
@@ -148,10 +180,10 @@ module.exports = function(IBMDB) {
148180
var orderMatched = true;
149181
if (indexNames.indexOf(indexName) !== -1) {
150182
m.settings.indexes[indexName].columns.split(/,\s*/).forEach(
151-
function(columnName, i) {
152-
if (ai[indexName].columns[i] !== columnName)
153-
orderMatched = false;
154-
});
183+
function(columnName, i) {
184+
if (ai[indexName].columns[i] !== columnName)
185+
orderMatched = false;
186+
});
155187
}
156188

157189
if (!orderMatched) {
@@ -186,8 +218,8 @@ module.exports = function(IBMDB) {
186218
type = i.type;
187219
}
188220
sql.push('CREATE ' + type + ' INDEX ' + pName + ' ON ' +
189-
self.schema + '.' + self.tableEscaped(model) +
190-
'(\"' + pName + '\") ');
221+
self.schema + '.' + self.tableEscaped(model) +
222+
'(\"' + pName + '\") ');
191223
}
192224
});
193225

@@ -202,7 +234,7 @@ module.exports = function(IBMDB) {
202234
type = i.type;
203235
}
204236
var stmt = 'CREATE ' + type + 'INDEX ' + iName + ' ON ' +
205-
self.schema + '.' + self.tableEscaped(model) + '(';
237+
self.schema + '.' + self.tableEscaped(model) + '(';
206238

207239
var splitNames = i.columns.split(/,\s*/);
208240
var colNames = splitNames.join('\",\"');
@@ -212,6 +244,24 @@ module.exports = function(IBMDB) {
212244
sql.push(stmt);
213245
}
214246
});
247+
return sql;
248+
};
249+
250+
IBMDB.prototype.alterTable = function(model, actualFields, actualIndexes,
251+
callback, checkOnly) {
252+
var self = this;
253+
var sql = [];
254+
var tasks = [];
255+
256+
var operations = self.getAddModifyColumns(model, actualFields);
257+
operations = operations.concat(self.getDropColumns(model, actualFields));
258+
259+
if (operations.length) {
260+
// Add the ALTER TABLE statement to the list of tasks to perform later.
261+
sql.push('ALTER TABLE ' + self.schema + '.' +
262+
self.tableEscaped(model) + ' ' + operations.join(' ') + ';');
263+
}
264+
sql = sql.concat(self.addIndexes(model, actualIndexes));
215265

216266
sql.forEach(function(i) {
217267
tasks.push(function(cb) {
@@ -232,32 +282,5 @@ module.exports = function(IBMDB) {
232282
} else {
233283
return (callback());
234284
}
235-
236-
function actualize(propName, oldSettings) {
237-
var newSettings = m.properties[propName];
238-
if (newSettings && changed(newSettings, oldSettings)) {
239-
// TODO: NO TESTS EXECUTE THIS CODE PATH
240-
var pName = '\'' + propName + '\'';
241-
operations.push('CHANGE COLUMN ' + pName + ' ' + pName + ' ' +
242-
self.buildColumnDefinition(model, propName));
243-
}
244-
}
245-
246-
function changed(newSettings, oldSettings) {
247-
if (oldSettings.Null === 'YES') {
248-
// Used to allow null and does not now.
249-
if (!self.isNullable(newSettings)) {
250-
return true;
251-
}
252-
}
253-
if (oldSettings.Null === 'NO') {
254-
// Did not allow null and now does.
255-
if (self.isNullable(newSettings)) {
256-
return true;
257-
}
258-
}
259-
260-
return false;
261-
}
262285
};
263286
};

0 commit comments

Comments
 (0)