From d6b15047b050aaf5b63e8db4d8ea90b44f1caa1c Mon Sep 17 00:00:00 2001 From: ssh24 Date: Thu, 23 Feb 2017 13:59:05 -0500 Subject: [PATCH] Refactor migration methods Extract getTableStatus & autoupdate Extract isActual function Extract getDropColumns into base connector Extract addPropertyToActual to base connector Extract searchForPropertyInActual to base Extract propertyHasNotBeenDeleted to base Extract applySqlChanges to base Extract columnDataType to base connector Use mapPostgreSQLDatatypes in showFields --- lib/migration.js | 230 ++++++++--------------------------------------- 1 file changed, 35 insertions(+), 195 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index c1dee3c3..ad03de44 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -11,136 +11,46 @@ var async = require('async'); module.exports = mixinMigration; function mixinMigration(PostgreSQL) { - /*! - * Discover the properties from a table - * @param {String} model The model name - * @param {Function} cb The callback function - */ - PostgreSQL.prototype.getTableStatus = function(model, cb) { - var fields; - var indexes; - - function done(err) { - if (fields && indexes) { - cb(err, fields, indexes); - } - } - - function decoratedTableDataCallback(err, data) { + PostgreSQL.prototype.showFields = function(model, cb) { + var sql = 'SELECT column_name AS "column", data_type AS "type", ' + + 'is_nullable AS "nullable", character_maximum_length as "length"' // , data_default AS "Default"' + + ' FROM "information_schema"."columns" WHERE table_name=\'' + + this.table(model) + '\''; + this.execute(sql, function(err, fields) { if (err) { - console.error(err); - } - if (!err) { - data.forEach(function(field) { + return cb(err); + } else { + fields.forEach(function(field) { field.type = mapPostgreSQLDatatypes(field.type, field.length); }); + cb(err, fields); } - fields = data; - done(err); - } - - function decoratedIndexDataCallback(err, data) { - var indexHash = {}; - - if (err) { - console.log(err); - } - - indexes = data; - done(err); - } - - this.execute('SELECT column_name AS "column", data_type AS "type", ' + - 'is_nullable AS "nullable", character_maximum_length as "length"' // , data_default AS "Default"' - + ' FROM "information_schema"."columns" WHERE table_name=\'' + - this.table(model) + '\'', decoratedTableDataCallback); - - this.execute( - 'SELECT t.relname AS "table", i.relname AS "name", ' + - 'am.amname AS "type", ix.indisprimary AS "primary", ' + - 'ix.indisunique AS "unique", ' + - 'ARRAY(SELECT pg_get_indexdef(ix.indexrelid, k + 1, true) ' + - ' FROM generate_subscripts(ix.indkey, 1) AS k ' + - ' ORDER BY k ) AS "keys", ' + - 'ARRAY(SELECT ' + - ' CASE ix.indoption[k] & 1 WHEN 1 THEN \'DESC\' ELSE \'ASC\' END ' + - ' FROM generate_subscripts(ix.indoption, 1) AS k ' + - ' ORDER BY k ' + - ') AS "order" ' + - 'FROM pg_class t, pg_class i, pg_index ix, pg_am am ' + - 'WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND ' + - 'i.relam = am.oid AND ' + - 't.relkind=\'r\' AND t.relname=\'' + - this.table(model) + '\'', decoratedIndexDataCallback); - }; - - /** - * 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 - * @callback {Function} [callback] The callback function - * @param {String|Error} err The error string or object - */ - PostgreSQL.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) { - 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 - */ - PostgreSQL.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) { + PostgreSQL.prototype.showIndexes = function(model, cb) { + var sql = 'SELECT t.relname AS "table", i.relname AS "name", ' + + 'am.amname AS "type", ix.indisprimary AS "primary", ' + + 'ix.indisunique AS "unique", ' + + 'ARRAY(SELECT pg_get_indexdef(ix.indexrelid, k + 1, true) ' + + ' FROM generate_subscripts(ix.indkey, 1) AS k ' + + ' ORDER BY k ) AS "keys", ' + + 'ARRAY(SELECT ' + + ' CASE ix.indoption[k] & 1 WHEN 1 THEN \'DESC\' ELSE \'ASC\' END ' + + ' FROM generate_subscripts(ix.indoption, 1) AS k ' + + ' ORDER BY k ' + + ') AS "order" ' + + 'FROM pg_class t, pg_class i, pg_index ix, pg_am am ' + + 'WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND ' + + 'i.relam = am.oid AND ' + + 't.relkind=\'r\' AND t.relname=\'' + + this.table(model) + '\''; + this.execute(sql, function(err, indexes) { if (err) { - return cb && cb(err); + return cb(err); + } else { + cb(err, indexes); } - var actual = (changes.length === 0); - cb && cb(null, actual); }); }; @@ -205,13 +115,6 @@ function mixinMigration(PostgreSQL) { return sql; }; - PostgreSQL.prototype.getDropColumns = function(model, actualFields) { - var sql = []; - var self = this; - sql = sql.concat(self.getColumnsToDrop(model, actualFields)); - return sql; - }; - PostgreSQL.prototype.getColumnsToAdd = function(model, actualFields) { var self = this; var m = self._models[model]; @@ -231,28 +134,6 @@ function mixinMigration(PostgreSQL) { return sql; }; - PostgreSQL.prototype.addPropertyToActual = function(model, propName) { - var self = this; - var prop = this.getModelDefinition(model).properties[propName]; - var sqlCommand = self.columnEscaped(model, propName) - + ' ' + self.columnDataType(model, propName) + - (self.isNullable(prop) ? '' : ' NOT NULL') + - self.columnDbDefault(model, propName); - return sqlCommand; - }; - - PostgreSQL.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; - }; - PostgreSQL.prototype.getPropertiesToModify = function(model, actualFields) { var self = this; var sql = []; @@ -345,23 +226,6 @@ function mixinMigration(PostgreSQL) { } }; - PostgreSQL.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; - }); - // thisQuery = thisQuery + ';'; - self.execute(thisQuery, cb); - } - }; - /*! * Build a list of columns for the given model * @param {String} model The model name @@ -517,29 +381,9 @@ function mixinMigration(PostgreSQL) { return colDefault ? (' DEFAULT ' + colDefault) : ''; }; - /*! - * Find the column type for a given model property - * - * @param {String} model The model name - * @param {String} property The property name - * @returns {String} The column type - */ - PostgreSQL.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; - if (colType) { - return colType + (colLength ? '(' + colLength + ')' : ''); - } - - switch (prop.type.name) { + PostgreSQL.prototype.buildColumnType = function buildColumnType(propertyDefinition) { + var p = propertyDefinition; + switch (p.type.name) { default: case 'String': case 'JSON': @@ -641,10 +485,6 @@ function mixinMigration(PostgreSQL) { } } - PostgreSQL.prototype.propertyHasNotBeenDeleted = function(model, propName) { - return !!this.getModelDefinition(model).properties[propName]; - }; - PostgreSQL.prototype.addIndexes = function(model, actualIndexes, cb) { var self = this; var m = self._models[model];