Skip to content

Commit 62dc458

Browse files
author
Sadman Sakib Hasan
authored
Merge pull request #219 from strongloop/refactor-postgresql-migration
Refactor postgresql migration
2 parents ff2dff0 + d6b1504 commit 62dc458

File tree

1 file changed

+35
-195
lines changed

1 file changed

+35
-195
lines changed

lib/migration.js

Lines changed: 35 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -11,136 +11,46 @@ var async = require('async');
1111
module.exports = mixinMigration;
1212

1313
function mixinMigration(PostgreSQL) {
14-
/*!
15-
* Discover the properties from a table
16-
* @param {String} model The model name
17-
* @param {Function} cb The callback function
18-
*/
19-
PostgreSQL.prototype.getTableStatus = function(model, cb) {
20-
var fields;
21-
var indexes;
22-
23-
function done(err) {
24-
if (fields && indexes) {
25-
cb(err, fields, indexes);
26-
}
27-
}
28-
29-
function decoratedTableDataCallback(err, data) {
14+
PostgreSQL.prototype.showFields = function(model, cb) {
15+
var sql = 'SELECT column_name AS "column", data_type AS "type", ' +
16+
'is_nullable AS "nullable", character_maximum_length as "length"' // , data_default AS "Default"'
17+
+ ' FROM "information_schema"."columns" WHERE table_name=\'' +
18+
this.table(model) + '\'';
19+
this.execute(sql, function(err, fields) {
3020
if (err) {
31-
console.error(err);
32-
}
33-
if (!err) {
34-
data.forEach(function(field) {
21+
return cb(err);
22+
} else {
23+
fields.forEach(function(field) {
3524
field.type = mapPostgreSQLDatatypes(field.type, field.length);
3625
});
26+
cb(err, fields);
3727
}
38-
fields = data;
39-
done(err);
40-
}
41-
42-
function decoratedIndexDataCallback(err, data) {
43-
var indexHash = {};
44-
45-
if (err) {
46-
console.log(err);
47-
}
48-
49-
indexes = data;
50-
done(err);
51-
}
52-
53-
this.execute('SELECT column_name AS "column", data_type AS "type", ' +
54-
'is_nullable AS "nullable", character_maximum_length as "length"' // , data_default AS "Default"'
55-
+ ' FROM "information_schema"."columns" WHERE table_name=\'' +
56-
this.table(model) + '\'', decoratedTableDataCallback);
57-
58-
this.execute(
59-
'SELECT t.relname AS "table", i.relname AS "name", ' +
60-
'am.amname AS "type", ix.indisprimary AS "primary", ' +
61-
'ix.indisunique AS "unique", ' +
62-
'ARRAY(SELECT pg_get_indexdef(ix.indexrelid, k + 1, true) ' +
63-
' FROM generate_subscripts(ix.indkey, 1) AS k ' +
64-
' ORDER BY k ) AS "keys", ' +
65-
'ARRAY(SELECT ' +
66-
' CASE ix.indoption[k] & 1 WHEN 1 THEN \'DESC\' ELSE \'ASC\' END ' +
67-
' FROM generate_subscripts(ix.indoption, 1) AS k ' +
68-
' ORDER BY k ' +
69-
') AS "order" ' +
70-
'FROM pg_class t, pg_class i, pg_index ix, pg_am am ' +
71-
'WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND ' +
72-
'i.relam = am.oid AND ' +
73-
't.relkind=\'r\' AND t.relname=\'' +
74-
this.table(model) + '\'', decoratedIndexDataCallback);
75-
};
76-
77-
/**
78-
* Perform autoupdate for the given models
79-
* @param {String[]} [models] A model name or an array of model names. If not present, apply to all models
80-
* @callback {Function} [callback] The callback function
81-
* @param {String|Error} err The error string or object
82-
*/
83-
PostgreSQL.prototype.autoupdate = function(models, cb) {
84-
var self = this;
85-
if ((!cb) && ('function' === typeof models)) {
86-
cb = models;
87-
models = undefined;
88-
}
89-
// First argument is a model name
90-
if ('string' === typeof models) {
91-
models = [models];
92-
}
93-
94-
models = models || Object.keys(this._models);
95-
96-
async.each(models, function(model, done) {
97-
if (!(model in self._models)) {
98-
return process.nextTick(function() {
99-
done(new Error(g.f('Model not found: %s' + model)));
100-
});
101-
}
102-
self.getTableStatus(model, function(err, fields, indexes) {
103-
if (!err && fields.length) {
104-
self.alterTable(model, fields, indexes, done);
105-
} else {
106-
self.createTable(model, done);
107-
}
108-
});
109-
}, cb);
28+
});
11029
};
11130

112-
/*!
113-
* Check if the models exist
114-
* @param {String[]} [models] A model name or an array of model names. If not present, apply to all models
115-
* @param {Function} [cb] The callback function
116-
*/
117-
PostgreSQL.prototype.isActual = function(models, cb) {
118-
var self = this;
119-
120-
if ((!cb) && ('function' === typeof models)) {
121-
cb = models;
122-
models = undefined;
123-
}
124-
// First argument is a model name
125-
if ('string' === typeof models) {
126-
models = [models];
127-
}
128-
129-
models = models || Object.keys(this._models);
130-
131-
var changes = [];
132-
async.each(models, function(model, done) {
133-
self.getTableStatus(model, function(err, fields) {
134-
changes = changes.concat(self.getAddModifyColumns(model, fields));
135-
changes = changes.concat(self.getDropColumns(model, fields));
136-
done(err);
137-
});
138-
}, function done(err) {
31+
PostgreSQL.prototype.showIndexes = function(model, cb) {
32+
var sql = 'SELECT t.relname AS "table", i.relname AS "name", ' +
33+
'am.amname AS "type", ix.indisprimary AS "primary", ' +
34+
'ix.indisunique AS "unique", ' +
35+
'ARRAY(SELECT pg_get_indexdef(ix.indexrelid, k + 1, true) ' +
36+
' FROM generate_subscripts(ix.indkey, 1) AS k ' +
37+
' ORDER BY k ) AS "keys", ' +
38+
'ARRAY(SELECT ' +
39+
' CASE ix.indoption[k] & 1 WHEN 1 THEN \'DESC\' ELSE \'ASC\' END ' +
40+
' FROM generate_subscripts(ix.indoption, 1) AS k ' +
41+
' ORDER BY k ' +
42+
') AS "order" ' +
43+
'FROM pg_class t, pg_class i, pg_index ix, pg_am am ' +
44+
'WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND ' +
45+
'i.relam = am.oid AND ' +
46+
't.relkind=\'r\' AND t.relname=\'' +
47+
this.table(model) + '\'';
48+
this.execute(sql, function(err, indexes) {
13949
if (err) {
140-
return cb && cb(err);
50+
return cb(err);
51+
} else {
52+
cb(err, indexes);
14153
}
142-
var actual = (changes.length === 0);
143-
cb && cb(null, actual);
14454
});
14555
};
14656

@@ -205,13 +115,6 @@ function mixinMigration(PostgreSQL) {
205115
return sql;
206116
};
207117

208-
PostgreSQL.prototype.getDropColumns = function(model, actualFields) {
209-
var sql = [];
210-
var self = this;
211-
sql = sql.concat(self.getColumnsToDrop(model, actualFields));
212-
return sql;
213-
};
214-
215118
PostgreSQL.prototype.getColumnsToAdd = function(model, actualFields) {
216119
var self = this;
217120
var m = self._models[model];
@@ -231,28 +134,6 @@ function mixinMigration(PostgreSQL) {
231134
return sql;
232135
};
233136

234-
PostgreSQL.prototype.addPropertyToActual = function(model, propName) {
235-
var self = this;
236-
var prop = this.getModelDefinition(model).properties[propName];
237-
var sqlCommand = self.columnEscaped(model, propName)
238-
+ ' ' + self.columnDataType(model, propName) +
239-
(self.isNullable(prop) ? '' : ' NOT NULL') +
240-
self.columnDbDefault(model, propName);
241-
return sqlCommand;
242-
};
243-
244-
PostgreSQL.prototype.searchForPropertyInActual = function(model, propName, actualFields) {
245-
var self = this;
246-
var found = false;
247-
actualFields.forEach(function(f) {
248-
if (f.column === self.column(model, propName)) {
249-
found = f;
250-
return;
251-
}
252-
});
253-
return found;
254-
};
255-
256137
PostgreSQL.prototype.getPropertiesToModify = function(model, actualFields) {
257138
var self = this;
258139
var sql = [];
@@ -345,23 +226,6 @@ function mixinMigration(PostgreSQL) {
345226
}
346227
};
347228

348-
PostgreSQL.prototype.applySqlChanges = function(model, pendingChanges, cb) {
349-
var self = this;
350-
if (pendingChanges.length) {
351-
var thisQuery = 'ALTER TABLE ' + self.tableEscaped(model);
352-
var ranOnce = false;
353-
pendingChanges.forEach(function(change) {
354-
if (ranOnce) {
355-
thisQuery = thisQuery + ' ';
356-
}
357-
thisQuery = thisQuery + ' ' + change;
358-
ranOnce = true;
359-
});
360-
// thisQuery = thisQuery + ';';
361-
self.execute(thisQuery, cb);
362-
}
363-
};
364-
365229
/*!
366230
* Build a list of columns for the given model
367231
* @param {String} model The model name
@@ -517,29 +381,9 @@ function mixinMigration(PostgreSQL) {
517381
return colDefault ? (' DEFAULT ' + colDefault) : '';
518382
};
519383

520-
/*!
521-
* Find the column type for a given model property
522-
*
523-
* @param {String} model The model name
524-
* @param {String} property The property name
525-
* @returns {String} The column type
526-
*/
527-
PostgreSQL.prototype.columnDataType = function(model, property) {
528-
var columnMetadata = this.columnMetadata(model, property);
529-
var colType = columnMetadata && columnMetadata.dataType;
530-
if (colType) {
531-
colType = colType.toUpperCase();
532-
}
533-
var prop = this.getModelDefinition(model).properties[property];
534-
if (!prop) {
535-
return null;
536-
}
537-
var colLength = columnMetadata && columnMetadata.dataLength || prop.length;
538-
if (colType) {
539-
return colType + (colLength ? '(' + colLength + ')' : '');
540-
}
541-
542-
switch (prop.type.name) {
384+
PostgreSQL.prototype.buildColumnType = function buildColumnType(propertyDefinition) {
385+
var p = propertyDefinition;
386+
switch (p.type.name) {
543387
default:
544388
case 'String':
545389
case 'JSON':
@@ -641,10 +485,6 @@ function mixinMigration(PostgreSQL) {
641485
}
642486
}
643487

644-
PostgreSQL.prototype.propertyHasNotBeenDeleted = function(model, propName) {
645-
return !!this.getModelDefinition(model).properties[propName];
646-
};
647-
648488
PostgreSQL.prototype.addIndexes = function(model, actualIndexes, cb) {
649489
var self = this;
650490
var m = self._models[model];

0 commit comments

Comments
 (0)