Merge pull request #78 from strongloop/refactor-migration

Refactor migration
This commit is contained in:
Sadman Sakib Hasan 2017-03-02 10:28:18 -08:00 committed by GitHub
commit bba29f88f2
1 changed files with 203 additions and 0 deletions

View File

@ -54,6 +54,209 @@ SQLConnector.prototype.invokeSuper = function(methodName) {
return superMethod.apply(this, args); return superMethod.apply(this, args);
}; };
/**
* Perform autoupdate for the given models
* @param {String[]} [models] A model name or an array of model names.
* If not present, apply to all models
* @param {Function} [cb] The callback function
*/
SQLConnector.prototype.autoupdate = function(models, cb) {
var self = this;
if ((!cb) && ('function' === typeof models)) {
cb = models;
models = undefined;
}
// First argument is a model name
if ('string' === typeof models) {
models = [models];
}
models = models || Object.keys(this._models);
async.each(models, function(model, done) {
if (!(model in self._models)) {
return process.nextTick(function() {
done(new Error(g.f('Model not found: %s', model)));
});
}
self.getTableStatus(model, function(err, fields, indexes, FKs) {
if (!err && fields.length) {
self.alterTable(model, fields, indexes, done);
} else {
self.createTable(model, done);
}
});
}, cb);
};
/**
* Check if the models exist
* @param {String[]} [models] A model name or an array of model names.
* If not present, apply to all models
* @param {Function} [cb] The callback function
*/
SQLConnector.prototype.isActual = function(models, cb) {
var self = this;
if ((!cb) && ('function' === typeof models)) {
cb = models;
models = undefined;
}
// First argument is a model name
if ('string' === typeof models) {
models = [models];
}
models = models || Object.keys(this._models);
var changes = [];
async.each(models, function(model, done) {
self.getTableStatus(model, function(err, fields) {
changes = changes.concat(self.getAddModifyColumns(model, fields));
changes = changes.concat(self.getDropColumns(model, fields));
done(err);
});
}, function done(err) {
if (err) {
return cb && cb(err);
}
var actual = (changes.length === 0);
cb && cb(null, actual);
});
};
SQLConnector.prototype.getAddModifyColumns = function(model, fields) {
throw new Error(g.f('{{getAddModifyColumns()}} must be implemented by the connector'));
};
SQLConnector.prototype.getDropColumns = function(model, fields) {
var sql = [];
var self = this;
sql = sql.concat(self.getColumnsToDrop(model, fields));
return sql;
};
SQLConnector.prototype.getColumnsToDrop = function(model, fields) {
throw new Error(g.f('{{getColumnsToDrop()}} must be implemented by the connector'));
};
SQLConnector.prototype.searchForPropertyInActual = function(model, propName,
actualFields) {
var self = this;
var found = false;
actualFields.forEach(function(f) {
if (f.column === self.column(model, propName)) {
found = f;
return;
}
});
return found;
};
SQLConnector.prototype.addPropertyToActual = function(model, propName) {
var self = this;
var sqlCommand = self.columnEscaped(model, propName) +
' ' + self.columnDataType(model, propName) +
(self.isNullable(self.getPropertyDefinition(model, propName)) ?
'' : ' NOT NULL');
return sqlCommand;
};
SQLConnector.prototype.columnDataType = function(model, property) {
var columnMetadata = this.columnMetadata(model, property);
var colType = columnMetadata && columnMetadata.dataType;
if (colType) {
colType = colType.toUpperCase();
}
var prop = this.getModelDefinition(model).properties[property];
if (!prop) {
return null;
}
var colLength = columnMetadata && columnMetadata.dataLength ||
prop.length || prop.limit;
if (colType && colLength) {
return colType + '(' + colLength + ')';
}
return this.buildColumnType(prop);
};
SQLConnector.prototype.buildColumnType = function(property) {
throw new Error(g.f('{{buildColumnType()}} must be implemented by the connector'));
};
SQLConnector.prototype.propertyHasNotBeenDeleted = function(model, propName) {
return !!this.getModelDefinition(model).properties[propName];
};
SQLConnector.prototype.applySqlChanges = function(model, pendingChanges, cb) {
var self = this;
if (pendingChanges.length) {
var thisQuery = 'ALTER TABLE ' + self.tableEscaped(model);
var ranOnce = false;
pendingChanges.forEach(function(change) {
if (ranOnce) {
thisQuery = thisQuery + ' ';
}
thisQuery = thisQuery + ' ' + change;
ranOnce = true;
});
self.execute(thisQuery, cb);
}
};
/**
* Alters a table
* @param {String} model The model name
* @param {Object} fields Fields of the table
* @param {Object} indexes Indexes of the table
* @param {Function} cb The callback function
*/
SQLConnector.prototype.alterTable = function(model, fields, indexes, cb) {
throw new Error(g.f('{{alterTable()}} must be implemented by the connector'));
};
/**
* Get the status of a table
* @param {String} model The model name
* @param {Function} cb The callback function
*/
SQLConnector.prototype.getTableStatus = function(model, cb) {
var fields, indexes;
var self = this;
this.showFields(model, function(err, data) {
if (err) return cb(err);
fields = data;
self.showIndexes(model, function(err, data) {
if (err) return cb(err);
indexes = data;
if (fields && indexes)
return cb(null, fields, indexes);
});
});
};
/**
* Get fields from a table
* @param {String} model The model name
* @param {Function} cb The callback function
*/
SQLConnector.prototype.showFields = function(model, cb) {
throw new Error(g.f('{{showFields()}} must be implemented by the connector'));
};
/**
* Get indexes from a table
* @param {String} model The model name
* @param {Function} cb The callback function
*/
SQLConnector.prototype.showIndexes = function(model, cb) {
throw new Error(g.f('{{showIndexes()}} must be implemented by the connector'));
};
/** /**
* Get types associated with the connector * Get types associated with the connector
* Returns {String[]} The types for the connector * Returns {String[]} The types for the connector