Merge pull request #78 from strongloop/refactor-migration
Refactor migration
This commit is contained in:
commit
bba29f88f2
203
lib/sql.js
203
lib/sql.js
|
@ -54,6 +54,209 @@ SQLConnector.prototype.invokeSuper = function(methodName) {
|
|||
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
|
||||
* Returns {String[]} The types for the connector
|
||||
|
|
Loading…
Reference in New Issue