From e0e7f0d92a31bcc30b904dffea367f460a7f5724 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 13 Dec 2019 12:50:20 -0500 Subject: [PATCH] test: add test for string auto-generation --- lib/migration.js | 81 ++++++++++++++++++++----------- test/postgresql.migration.test.js | 71 ++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 29 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 07596e0f..f98bec63 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -297,26 +297,31 @@ function mixinMigration(PostgreSQL) { const modelDef = this.getModelDefinition(model); const prop = modelDef.properties[propName]; let result = self.columnDataType(model, propName); + // checks if dataType is set to uuid - let postgreType = modelDef.properties[propName]; - if(postgreType.postgresql && postgreType.postgresql.dataType){ - postgreType = postgreType.postgresql.dataType.toUpperCase(); + let postgDefaultFn; + let postgType; + const postgSettings = prop.postgresql; + if (postgSettings && postgSettings.dataType) { + postgType = postgSettings.dataType.toUpperCase(); } if (prop.generated) { if (result === 'INTEGER') { return 'SERIAL'; - } - else if (postgreType === 'UUID') { - result = result + ' NOT NULL' + ' DEFAULT uuid_generate_v4()'; - return result; + } else if (postgType === 'UUID') { + if (postgSettings && postgSettings.defaultFn && postgSettings.extension) { + // if user provides their own extension and function + postgDefaultFn = postgSettings.defaultFn; + return result + ' NOT NULL' + ' DEFAULT ' + postgDefaultFn; + } + return result + ' NOT NULL' + ' DEFAULT uuid_generate_v4()'; } else { console.log(chalk.red('>>> WARNING: ') + - `auto-generattion is not supported for type "${chalk.yellow(prop.type)}". Please add your own function to the table "${chalk.yellow(model)}".` - ); + `auto-generattion is not supported for type "${chalk.yellow(prop.type)}". \ + Please add your own function to the table "${chalk.yellow(model)}".`); } } - if (!self.isNullable(prop)) result = result + ' NOT NULL'; result += self.columnDbDefault(model, propName); return result; @@ -330,34 +335,53 @@ function mixinMigration(PostgreSQL) { PostgreSQL.prototype.createTable = function(model, cb) { const self = this; const name = self.tableEscaped(model); + const modelDef = this.getModelDefinition(model); + + // collects all extenstions need to be created + let createExtensions; + Object.keys(this.getModelDefinition(model).properties).forEach(function(propName) { + const prop = modelDef.properties[propName]; + + // checks if dataType is set to uuid + const postgSettings = prop.postgresql; + if (postgSettings && postgSettings.dataType && postgSettings.dataType === 'UUID' + && postgSettings.defaultFn && postgSettings.extension) { + createExtensions += 'CREATE EXTENSION IF NOT EXISTS "' + postgSettings.extension + '";'; + } + }); + // default extension + if (!createExtensions) { + createExtensions = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'; + } // Please note IF NOT EXISTS is introduced in postgresql v9.3 self.execute( - 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";' + + createExtensions + 'CREATE SCHEMA ' + self.escapeName(self.schema(model)), - function(err) { - if (err && err.code !== '42P06') { - return cb && cb(err); - } - self.execute('CREATE TABLE ' + name + ' (\n ' + - self.propertiesSQL(model) + '\n)', - function(err, info) { - if (err) { - return cb(err, info); + function(err) { + if (err && err.code !== '42P06') { + return cb && cb(err); } - self.addIndexes(model, undefined, function(err) { + self.execute('CREATE TABLE ' + name + ' (\n ' + + self.propertiesSQL(model) + '\n)', + function(err, info) { if (err) { - return cb(err); + return cb(err, info); } - const fkSQL = self.getForeignKeySQL(model, - self.getModelDefinition(model).settings.foreignKeys); - self.addForeignKeys(model, fkSQL, function(err, result) { - cb(err); + self.addIndexes(model, undefined, function(err) { + if (err) { + return cb(err); + } + const fkSQL = self.getForeignKeySQL(model, + self.getModelDefinition(model).settings.foreignKeys); + self.addForeignKeys(model, fkSQL, function(err, result) { + cb(err); + }); }); }); - }); - }); + }, + ); }; PostgreSQL.prototype.buildIndex = function(model, property) { @@ -664,6 +688,7 @@ function mixinMigration(PostgreSQL) { case 'CHARACTER': case 'CHAR': case 'TEXT': + case 'UUID': return 'String'; case 'BYTEA': diff --git a/test/postgresql.migration.test.js b/test/postgresql.migration.test.js index 4c432cd1..fa9ff0da 100644 --- a/test/postgresql.migration.test.js +++ b/test/postgresql.migration.test.js @@ -14,7 +14,7 @@ describe('migrations', function() { before(setup); it('should run migration', function(done) { - db.automigrate('UserDataWithIndexes', done); + db.automigrate(['UserDataWithIndexes', 'OrderData', 'DefaultUuid'], done); }); it('UserDataWithIndexes should have correct indexes', function(done) { @@ -73,6 +73,42 @@ describe('migrations', function() { done(); }); }); + + it('OrderData should have correct prop type uuid with custom generation function', function(done) { + checkColumns('OrderData', function(err, cols) { + assert.deepEqual(cols, { + ordercode: + {column_name: 'ordercode', + column_default: 'uuid_generate_v1()', + data_type: 'uuid'}, + ordername: + {column_name: 'ordername', + column_default: null, + data_type: 'text'}, + id: + {column_name: 'id', + column_default: 'nextval(\'orderdata_id_seq\'::regclass)', + data_type: 'integer'}, + }); + done(); + }); + }); + + it('DefaultUuid should have correct id type uuid and default function v4', function(done) { + checkColumns('DefaultUuid', function(err, cols) { + assert.deepEqual(cols, { + defaultcode: + {column_name: 'defaultcode', + column_default: 'uuid_generate_v4()', + data_type: 'uuid'}, + id: + {column_name: 'id', + column_default: 'nextval(\'defaultuuid_id_seq\'::regclass)', + data_type: 'integer'}, + }); + done(); + }); + }); }); function setup(done) { @@ -118,6 +154,23 @@ function setup(done) { }, }, }); + const OrderData = db.define('OrderData', { + ordercode: {type: 'String', required: true, generated: true, useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + defaultFn: 'uuid_generate_v1()', + extension: 'uuid-ossp', + }}, + ordername: {type: 'String'}, + }); + + const DefaultUuid = db.define('DefaultUuid', { + defaultCode: {type: 'String', required: true, generated: true, useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + defaultFn: 'uuid_generate_v1()', // lack extension + }}, + }); done(); } @@ -161,3 +214,19 @@ function table(model) { function query(sql, cb) { db.adapter.query(sql, cb); } + +function checkColumns(table, cb) { + const tableName = table.toLowerCase(); + query('SELECT column_name, column_default, data_type FROM information_schema.columns \ + WHERE(table_schema, table_name) = (\'public\', \'' + tableName + '\');', + function(err, data) { + const cols = {}; + if (!err) { + data.forEach(function(index) { + cols[index.column_name] = index; + delete index.name; + }); + } + cb(err, cols); + }); +}