diff --git a/components/persistor/lib/knex/db.ts b/components/persistor/lib/knex/db.ts index 2d2144b1..0fdfa259 100644 --- a/components/persistor/lib/knex/db.ts +++ b/components/persistor/lib/knex/db.ts @@ -745,9 +745,11 @@ module.exports = function (PersistObjectTemplate) { var aliasedTableName = template.__table__; tableName = this.dealias(aliasedTableName); const functionName = synchronizeIndexes.name; + let tableColumns: string[] = []; + let tableIndexes: string[] = []; while (template.__parent__) { - template = template.__parent__; + template = template.__parent__; } if (!template.__table__) { @@ -758,53 +760,15 @@ module.exports = function (PersistObjectTemplate) { var schema = this._schema; var _dbschema; - var _changes = {}; - var schemaTable = 'index_schema_history'; - var schemaField = 'schema'; - + var _changes = {}; + async function diffTable(schema, tableName) { - var loadSchema = function (tableName) { - - if (!!_dbschema) { - //@ts-ignore - return (_dbschema, tableName); - } + //Todo: can we optimize anything here?? + var tableIndexObj = await knex('pg_indexes').select(['indexname as name', knex.raw(`case when indexdef LIKE '%UNIQUE%' then 'unique' else 'index' end as type`)]).where({ tablename: tableName }); + var dbTableDef = { indexes: tableIndexObj } - return knex.schema.hasTable(schemaTable).then(function(exists) { - if (!exists) { - return knex.schema.createTable(schemaTable, function(table) { - table.increments('sequence_id').primary(); - table.text(schemaField); - table.timestamps(); - }) - } - }).then(function () { - return knex(schemaTable) - .orderBy('sequence_id', 'desc') - .limit(1); - }).then(function (record) { - var response; - if (!record[0]) { - response = {}; - } - else { - response = JSON.parse(record[0][schemaField]); - } - _dbschema = response; - return [response, template.__name__]; - }) - }; - - var loadTableDef = function(dbschema, tableName) { - if (!dbschema[tableName]) - dbschema[tableName] = {}; - return [dbschema, schema, tableName]; - }; - - var diffTable = function(dbschema, schema, tableName) { - var dbTableDef = dbschema[tableName]; var memTableDef = schema[tableName]; - var track = {add: [], change: [], delete: []}; + var track = { add: [], change: [], delete: [] }; _diff(dbTableDef, memTableDef, 'delete', false, function (_dbIdx, memIdx) { return !memIdx; }, _diff(memTableDef, dbTableDef, 'change', false, function (memIdx, dbIdx) { @@ -814,7 +778,8 @@ module.exports = function (PersistObjectTemplate) { }, track))); _changes[tableName] = _changes[tableName] || {}; - _.map(_.keys(track), function(key) { + + _.map(_.keys(track), function (key) { _changes[tableName][key] = _changes[tableName][key] || []; _changes[tableName][key].push.apply(_changes[tableName][key], track[key]); }); @@ -823,7 +788,7 @@ module.exports = function (PersistObjectTemplate) { if (!!masterTblSchema && !!masterTblSchema.indexes && masterTblSchema.indexes instanceof Array && !!shadowTblSchema) { (masterTblSchema.indexes || []).forEach(function (mstIdx) { - var shdIdx = _.findWhere(shadowTblSchema.indexes, {name: mstIdx.name}); + var shdIdx = _.findWhere(shadowTblSchema.indexes, { name: mstIdx.name }); if (addPredicate(mstIdx, shdIdx)) { diffs[opr] = diffs[opr] || []; @@ -841,34 +806,45 @@ module.exports = function (PersistObjectTemplate) { var generateChanges = function (localtemplate, _value) { return _.reduce(localtemplate.__children__, function (_curr, o) { return Promise.resolve() - .then(loadTableDef.bind(this, _dbschema, o.__name__)) - .spread(diffTable) + .then(diffTable(_dbschema, o.__name__)) .then(generateChanges.bind(this, o)); }, {}); }; - var getFilteredTarget = function(src, target) { - return _.filter(target, function(o, _filterkey) { - var currName = _.reduce(o.def.columns, function (name, col) { - return name + '_' + col; - }, 'idx_' + tableName); - return !_.find(src, function(cached) { - var cachedName = _.reduce(cached.def.columns, function (name, col) { - return name + '_' + col; - }, 'idx_' + tableName); - return (cachedName.toLowerCase() === currName.toLowerCase()) - }) - }); - }; + /** + * this function will add all the Columns to database + * @param tableName + */ + async function loadColumnNames(tableName: string) { + const columns = await knex(tableName).columnInfo(); + tableColumns = columns ? Object.keys(columns) : []; + } + + /** + * this function will all the existing indexes to tableIndexes array + * @param tableName name of the table + * + */ + async function loadPgIndexes(tableName: string) { + const indexes = await knex('pg_indexes').select(['indexname as name']).where({ tablename: tableName }); + if (!indexes) { + tableIndexes = []; + } + + for (let i = 0; i < indexes.length; i++) { + const values: string[] = Object.values(indexes[i]); + tableIndexes.push(...values); + } + } - var mergeChanges = function() { - var dbChanges = {add: [], change: [], delete: []}; - _.map(dbChanges, function(_object, key) { - _.each(_changes, function(change) { - var uniqChanges = _.uniq(change[key], function(o) { + var mergeChanges = function () { + var dbChanges = { add: [], change: [], delete: [] }; + _.map(dbChanges, function (_object, key) { + _.each(_changes, function (change) { + var uniqChanges = _.uniq(change[key], function (o) { return o.name; }); - var filtered = getFilteredTarget(dbChanges[key], uniqChanges); + var filtered = filterExistingIndexesAndNonExistingColumns(uniqChanges, key); dbChanges[key].push.apply(dbChanges[key], filtered); }) }); @@ -876,7 +852,39 @@ module.exports = function (PersistObjectTemplate) { return dbChanges; }; - var applyTableChanges = async function(dbChanges) { + /** + * + * @param items new items indexes which we want to add to database. + * @param key key could be add | delete | change + * @returns this returns only new indexes will strip out all the exisiting indexes from the result. + */ + function filterExistingIndexesAndNonExistingColumns(items, key: string) { + if (!items || !Array.isArray(items) || key !== 'add') { + return items; + } + + const filteredItems = items.filter(o => { + var currName = _.reduce(o.def.columns, function (name, col) { + return name + '_' + col; + }, 'idx_' + tableName); + return !tableIndexes.includes(currName) + } + ); + + // Todo: Need to see if we need this?? + for (let i = 0; i < filteredItems.length; i++) { + const items = filteredItems[i]; + if (items && items.def && items.def.columns) { + let columns = items.def.columns; + columns = columns.filter(column => + tableColumns.includes(column && column.id) + ); + } + } + return filteredItems; + } + + var applyTableChanges = async function (dbChanges) { function logTableChangesWarningMessage(columns, type, indexName, operation, error) { const logger = PersistObjectTemplate && PersistObjectTemplate.logger; if (logger) { @@ -906,67 +914,73 @@ module.exports = function (PersistObjectTemplate) { * @param operation * @param diffs */ - async function syncIndexesForHierarchy (operation, diffs) { + async function syncIndexesForHierarchy(operation, diffs) { for (const _key in diffs[operation]) { try { const object = diffs[operation][_key]; - var type = object.def.type; - var columns = object.def.columns; + var type = object.def?.type || object.type; + var columns = object.def?.columns; if (type !== 'unique' && type !== 'index') { throw new Error('index type can be only "unique" or "index"'); } - var name = _.reduce(object.def.columns, function (name, col) { - return name + '_' + col; - }, 'idx_' + tableName); - - name = name.toLowerCase(); if (operation === 'add') { try { + var name = _.reduce(object.def.columns, function (name, col) { + return name + '_' + col; + }, 'idx_' + tableName); + + name = name.toLowerCase(); await knex.schema.table(tableName, async function (table) { // This table function callback does not necessarily need to be // an async callback, but making the callback async/await as a guard. await table[type](columns, name); }); } - catch(error) { + catch (error) { logTableChangesWarningMessage(columns, type, name, operation, error); } } else if (operation === 'delete') { type = type.replace(/index/, 'Index'); - type = type.replace(/unique/, 'Unique'); + type = type.replace(/unique/, 'Unique') + try { await knex.schema.table(tableName, async function (table) { // This table function callback does not necessarily need to be // an async callback, but making the callback async/await as a guard. - await table['drop' + type]([], name); + await table['drop' + type]([], object.name); }); } catch (error) { - logTableChangesWarningMessage(columns, type, name, operation, error); + logTableChangesWarningMessage(columns, type, object.name, operation, error); }; } else { try { + var name = _.reduce(object.def.columns, function (name, col) { + return name + '_' + col; + }, 'idx_' + tableName); + + name = name.toLowerCase(); await knex.schema.table(tableName, async function (table) { // This table function callback does not necessarily need to be // an async callback, but making the callback async/await as a guard. await table[type](columns, name); }); - } catch(error) { + } catch (error) { logTableChangesWarningMessage(columns, type, name, operation, error); }; } } - catch(error) { + catch (error) { const logger = PersistObjectTemplate && PersistObjectTemplate.logger; if (logger) { logger.warn({ module: moduleName, function: functionName, category: 'milestone', - message: 'Unable to apply index changes for '+ tableName, + message: 'Unable to apply index changes for ' + tableName, error: error, }); } @@ -975,54 +989,20 @@ module.exports = function (PersistObjectTemplate) { } return Promise.all([ - syncIndexesForHierarchy('delete', dbChanges), - syncIndexesForHierarchy('add', dbChanges), + syncIndexesForHierarchy('delete', dbChanges), + syncIndexesForHierarchy('add', dbChanges), syncIndexesForHierarchy('change', dbChanges) ]); }; - var isSchemaChanged = function(object) { - return (object.add.length || object.change.length || object.delete.length) - }; - - var makeSchemaUpdates = function () { - var chgFound = _.reduce(_changes, function (curr, change) { - return curr || !!isSchemaChanged(change); - }, false); - - if (!chgFound) return; - - return knex(schemaTable) - .orderBy('sequence_id', 'desc') - .limit(1).then(function (record) { - var response = {}, sequence_id; - if (!record[0]) { - sequence_id = 1; - } - else { - response = JSON.parse(record[0][schemaField]); - sequence_id = ++record[0].sequence_id; - } - _.each(_changes, function (_o, chgKey) { - response[chgKey] = schema[chgKey]; - }); - - return knex(schemaTable).insert({ - sequence_id: sequence_id, - schema: JSON.stringify(response) - }); - }) - }; - return Promise.resolve() - .then(loadSchema.bind(this, tableName)) - .spread(loadTableDef) - .spread(diffTable) + .then(diffTable.bind(this, schema, template.__name__)) .then(generateChanges.bind(this, template)) .then(mergeChanges) + .then(loadColumnNames(tableName)) + .then(loadPgIndexes(tableName)) .then(applyTableChanges) - .then(makeSchemaUpdates) - .catch(function(e) { + .catch(function (e) { throw e; }) } diff --git a/components/persistor/package-lock.json b/components/persistor/package-lock.json index 003a1a0d..df18db79 100644 --- a/components/persistor/package-lock.json +++ b/components/persistor/package-lock.json @@ -1,12 +1,12 @@ { "name": "@haventech/persistor", - "version": "12.0.1", + "version": "12.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@haventech/persistor", - "version": "12.0.1", + "version": "12.1.0", "dependencies": { "aws-sdk": "2.x", "bluebird": "x", diff --git a/components/persistor/package.json b/components/persistor/package.json index 63e6acda..37d458ba 100644 --- a/components/persistor/package.json +++ b/components/persistor/package.json @@ -2,7 +2,7 @@ "name": "@haventech/persistor", "description": "A subclass of supertype that serializes to and reconstitutes from MongoDB or SQL databases", "homepage": "https://github.com/haven-life/persistor", - "version": "12.0.1", + "version": "12.1.0", "main": "dist/index.js", "types": "dist/index.d.ts", "dependencies": { diff --git a/components/persistor/test/persist_banking_pgsql.js b/components/persistor/test/persist_banking_pgsql.js index 6719a170..78f56e3c 100644 --- a/components/persistor/test/persist_banking_pgsql.js +++ b/components/persistor/test/persist_banking_pgsql.js @@ -380,7 +380,7 @@ describe('Banking from pgsql Example persist_banking_pgsql', function () { sandbox.restore(); }); - it ('opens the database Postgres', function () { + it('opens the database Postgres', function () { return Promise.resolve() .then(function () { knex = require('knex')({ @@ -402,13 +402,11 @@ describe('Banking from pgsql Example persist_banking_pgsql', function () { PersistObjectTemplate.performInjections(); // Normally done by getTemplates }).catch(function(e) {throw e;}); }); - var schemaTable = 'index_schema_history'; - it ('clears the bank', function () { + + it('clears the bank', function () { this.timeout(4000); - return knex.schema.dropTableIfExists(schemaTable) - .then(function () { - return clearCollection(Role); - }).then(function (count) { + return clearCollection(Role) + .then(function (count) { expect(count).to.equal(0); return clearCollection(Account) }).then(function (count) { @@ -465,7 +463,7 @@ describe('Banking from pgsql Example persist_banking_pgsql', function () { // }); // }); - it ('can create the data', function () { + it('can create the data', function () { // Setup customers and addresses sam = new Customer('Sam', 'M', 'Elsamman'); karen = new Customer('Karen', 'M', 'Burke'); diff --git a/components/persistor/test/persist_banking_s3.js b/components/persistor/test/persist_banking_s3.js index e738167a..69d47b3f 100644 --- a/components/persistor/test/persist_banking_s3.js +++ b/components/persistor/test/persist_banking_s3.js @@ -81,9 +81,6 @@ describe('Banking from pgsql Example persist_banking_s3', function () { PersistObjectTemplate.performInjections(); // Normally done by getTemplates this.timeout(4000); - - const schemaTable = 'index_schema_history'; - await knex.schema.dropTableIfExists(schemaTable) const count = await clearCollection(Customer); expect(count).to.equal(0); diff --git a/components/persistor/test/persist_fetch.js b/components/persistor/test/persist_fetch.js index aa0df79d..530c4f95 100644 --- a/components/persistor/test/persist_fetch.js +++ b/components/persistor/test/persist_fetch.js @@ -13,7 +13,6 @@ var knex; var schema = {}; -var schemaTable = 'index_schema_history'; var Phone, Address, Employee, empId, addressId, phoneId, Role, AddressType; var PersistObjectTemplate, ObjectTemplate; describe('persist fetch', function () { @@ -41,8 +40,7 @@ describe('persist fetch', function () { return knex.schema.dropTableIfExists('tx_role') }).then(function () { return knex.schema.dropTableIfExists('tx_address_type') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]); }) after('closes the database', function () { return knex.destroy(); @@ -196,8 +194,7 @@ describe('persist fetch', function () { return knex.schema.dropTableIfExists('tx_role') }).then(function () { return knex.schema.dropTableIfExists('tx_address_type') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]) }); it('check basic fetch without fetch spec should not return the records', function () { diff --git a/components/persistor/test/persist_fetch_children.js b/components/persistor/test/persist_fetch_children.js index ee14675b..9b89d930 100644 --- a/components/persistor/test/persist_fetch_children.js +++ b/components/persistor/test/persist_fetch_children.js @@ -12,7 +12,6 @@ var knexInit = require('knex'); var knex; var schema = {}; -var schemaTable = 'index_schema_history'; var Employee, Department, Role, roleId, EmployeeRef; var PersistObjectTemplate, ObjectTemplate; describe('persistor fetch children', function () { @@ -36,8 +35,7 @@ describe('persistor fetch children', function () { return knex.schema.dropTableIfExists('tx_department') }).then(function () { return knex.schema.dropTableIfExists('tx_employee_ref') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]) }) after('closes the database', function () { return knex.destroy(); @@ -165,8 +163,7 @@ describe('persistor fetch children', function () { return knex.schema.dropTableIfExists('tx_role') }).then(function () { return knex.schema.dropTableIfExists('tx_employee_ref') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]) }); it('load intermediate objects first and then try to load the parents ', function () { diff --git a/components/persistor/test/persist_newapi_extend.js b/components/persistor/test/persist_newapi_extend.js index 444b8d3c..f81fdaa3 100644 --- a/components/persistor/test/persist_newapi_extend.js +++ b/components/persistor/test/persist_newapi_extend.js @@ -12,13 +12,12 @@ var knexInit = require('knex'); var knex; var schema = {}; -var schemaTable = 'index_schema_history'; var Employee, Person, Manager, empId, Address; var PersistObjectTemplate, ObjectTemplate; describe('persist newapi extend', function () { // this.timeout(5000); - before('drop schema table once per test suit', function() { + before('drop schema table once per test suit', async function() { knex = knexInit({ client: 'pg', connection: { @@ -28,8 +27,7 @@ describe('persist newapi extend', function () { password: process.env.dbPassword, } }); - return Promise.all([knex.schema.dropTableIfExists('tx_person'), - knex.schema.dropTableIfExists(schemaTable)]); + return await knex.schema.dropTableIfExists('tx_person') }) after('closes the database', function () { return knex.destroy(); @@ -117,10 +115,8 @@ describe('persist newapi extend', function () { } }); - afterEach('remove tables and after each test', function() { - return Promise.all([ - knex.schema.dropTableIfExists('tx_person'), - knex.schema.dropTableIfExists(schemaTable)]); + afterEach('remove tables and after each test', async function() { + return await knex.schema.dropTableIfExists('tx_person') }); it('persistorFetchById without fetch spec should not return the records', function () { diff --git a/components/persistor/test/persist_newapi_tests.js b/components/persistor/test/persist_newapi_tests.js index 64681daf..2ecaab62 100644 --- a/components/persistor/test/persist_newapi_tests.js +++ b/components/persistor/test/persist_newapi_tests.js @@ -12,7 +12,6 @@ var knexInit = require('knex'); var knex; var schema = {}; -var schemaTable = 'index_schema_history'; var Phone, Address, Employee, empId, addressId, phoneId, Role; var PersistObjectTemplate, ObjectTemplate; @@ -39,8 +38,7 @@ describe('persist newapi tests', function () { return knex.schema.dropTableIfExists('tx_department') }).then(function () { return knex.schema.dropTableIfExists('tx_role') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]) }) after('closes the database', function () { return knex.destroy(); @@ -178,8 +176,7 @@ describe('persist newapi tests', function () { return knex.schema.dropTableIfExists('tx_department') }).then(function () { return knex.schema.dropTableIfExists('tx_role') - }), - knex.schema.dropTableIfExists(schemaTable)]); + })]) }); it('persistorFetchById without fetch spec should not return the records', function () { diff --git a/components/persistor/test/persist_parent_subset.js b/components/persistor/test/persist_parent_subset.js index b758f9a2..5cf0c76a 100644 --- a/components/persistor/test/persist_parent_subset.js +++ b/components/persistor/test/persist_parent_subset.js @@ -15,8 +15,6 @@ var knexInit = require('knex'); var knex; var schema = {}; -var schemaTable = 'index_schema_history'; - describe('persist parent subset', function () { before('arrange', function (done) { @@ -44,8 +42,7 @@ describe('persist parent subset', function () { }), knex.schema.dropTableIfExists('tx_employee_parentchild_subset').then(function () { return knex.schema.dropTableIfExists('tx_employee_parentchild_subset'); - }), - knex.schema.dropTableIfExists(schemaTable) + }) ]).should.notify(done); }); after('closes the database', function () { diff --git a/components/persistor/test/persist_polymorphic.js b/components/persistor/test/persist_polymorphic.js index a12f3919..e910586c 100644 --- a/components/persistor/test/persist_polymorphic.js +++ b/components/persistor/test/persist_polymorphic.js @@ -485,7 +485,6 @@ var schema = { var knexInit = require('knex'); var knex; -var schemaTable = 'index_schema_history'; describe('type mapping tests for parent/child relations', function () { before('arrange', function (done) { knex = knexInit({ @@ -516,7 +515,6 @@ describe('type mapping tests for parent/child relations', function () { knex.schema.dropTableIfExists('NewTableWithComments1'), knex.schema.dropTableIfExists('ExistingTableWithComments'), knex.schema.dropTableIfExists('ExistingTableWithAField'), - knex.schema.dropTableIfExists(schemaTable) ]).should.notify(done); }) after('closes the database', function () { diff --git a/components/persistor/test/persist_schema_indexdefchanges.js b/components/persistor/test/persist_schema_indexdefchanges.js index 3aa0ddeb..a5232bf1 100644 --- a/components/persistor/test/persist_schema_indexdefchanges.js +++ b/components/persistor/test/persist_schema_indexdefchanges.js @@ -9,8 +9,8 @@ chai.use(chaiAsPromised); var Promise = require('bluebird'); var ObjectTemplate = require('@haventech/supertype').default; var PersistObjectTemplate = require('../dist/index.js')(ObjectTemplate, null, ObjectTemplate); - - +const sinon = require('sinon'); +let spyLoggerWarn; var Address = PersistObjectTemplate.create('Address', { id: { type: Number }, init: function(id) { @@ -105,7 +105,7 @@ var ExtendParent = Parent.extend('ExtendParent', { var schema = { Employee: { - documentOf: 'pg/employee', + documentOf: 'pg/Employee', parents: { address: { id: 'address_id', @@ -207,7 +207,6 @@ var schema = { } var knexInit = require('knex'); var knex; -var schemaTable = 'index_schema_history'; describe('index synchronization checks', function () { var checkKeyExistsInSchema; var getIndexes; @@ -223,27 +222,13 @@ describe('index synchronization checks', function () { } }); - checkKeyExistsInSchema = function(key) { - return knex(schemaTable) - .select('schema') - .orderBy('sequence_id', 'desc') - .limit(1) - .then(function (records) { - if (!records[0]) return false; - var pattern = new RegExp(key); - return !!records[0].schema.match(pattern); - }) + checkKeyExistsInSchema = async function(key) { + const result = await knex('pg_indexes').select(['indexname as name']).where({ tablename: key }); + return result.length > 0 ? true : false; }; getIndexes = function(key) { - return knex(schemaTable) - .select('schema') - .orderBy('sequence_id', 'desc') - .limit(1) - .then(function (records) { - if (!records[0]) return []; - return JSON.parse(records[0].schema)[key].indexes; - }); + return knex('pg_indexes').select(['indexname as name']).where({ tablename: key }); }; (function () { @@ -251,6 +236,7 @@ describe('index synchronization checks', function () { PersistObjectTemplate.setSchema(schema); PersistObjectTemplate.performInjections(); // Normally done by getTemplates })(); + spyLoggerWarn = sinon.spy( PersistObjectTemplate.logger, 'warn'); return Promise.all([ knex.schema.dropTableIfExists('notificationCheck'), @@ -263,7 +249,6 @@ describe('index synchronization checks', function () { PersistObjectTemplate.dropKnexTable(IndexSyncTable), PersistObjectTemplate.dropKnexTable(MultipleIndexTable), PersistObjectTemplate.dropKnexTable(Parent), - knex(schemaTable).del(), knex.schema.dropTableIfExists('IndexSyncTable') ]).should.notify(done); }); @@ -271,6 +256,10 @@ describe('index synchronization checks', function () { return knex.destroy(); }); + afterEach(() => { + spyLoggerWarn.resetHistory(); + }) + it('synchronize the table without defining the indexes and make sure that the process does not make any entries to the schema table', function () { //sync table @@ -280,7 +269,11 @@ describe('index synchronization checks', function () { }); it('synchronize the index definition and check if the index exists on the table by dropping the index', function () { - return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable).should.eventually.have.property('command').that.match(/INSERT/); + // we don't return anything now when we call synchronizeKnexTableFromTemplate so checking db if we have index present + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable).then(function () { + return getIndexes('IndexSyncTable').should.eventually.have.length(1); + }) + }); it('calling synchronizeKnexTableFromTemplate without any changes to the schema definitions..', function () { @@ -303,6 +296,24 @@ describe('index synchronization checks', function () { }); it('add index and sync', function () { + schema.IndexSyncTable.indexes = [ + { + name: 'Fst_Index', + def: { + columns: ['name'], + type: 'index' + } + } + ]; + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable, null, true).then(async function () { + // searching `pg_indexes` if index present or not. + const result = await knex('pg_indexes').select(['indexname as name']).where({ tablename: 'IndexSyncTable' }); + expect(result[0]).to.be.eql({ name: 'idx_indexsynctable_name' }) + return getIndexes('IndexSyncTable').should.eventually.have.length(1); + }); + }); + + it('should have no warn logs if adding same index again', function () { schema.IndexSyncTable.indexes = [ { name: 'Fst_Index', @@ -313,6 +324,8 @@ describe('index synchronization checks', function () { } ]; return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable, null, true).then(function () { + //checking if warn logs is called or not + spyLoggerWarn.called.should.be.eql(false); return getIndexes('IndexSyncTable').should.eventually.have.length(1); }); }); @@ -421,4 +434,78 @@ describe('index synchronization checks', function () { return getIndexes('Employee').should.eventually.have.length(3); }); }); + + it('should add a warn log when we create invalid index where column doesnt exist', function () { + schema.IndexSyncTable.indexes = [ + { + name: 'Fst_Index', + def: { + columns: ['name'], + type: 'index' + } + }, + { + name: 'Scd_Index', + def: { + columns: ['randomColumn'], // invalid column + type: 'index' + } + } + ]; + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable, null, true).then(function () { + spyLoggerWarn.called.should.be.eql(true); + // checking the logger args with data + expect(spyLoggerWarn.firstCall.args[0].data).to.include({ + type: 'index', + operation: 'add', + indexName: 'idx_indexsynctable_randomcolumn', + }) + return getIndexes('IndexSyncTable').should.eventually.have.length(1); + }) + }); + + it('should not update the index if type is not valid and should throw error in logs', function () { + schema.IndexSyncTable.indexes = [ + { + name: 'Fst_Index_New1', + def: { + columns: ['name'], + type: 'unique' + } + }, + { + name: 'Scd_Index', + def: { + columns: ['id'], + type: 'indesx' + } + } + + ]; + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable, null, true).then(function () { + spyLoggerWarn.called.should.be.eql(true); + return getIndexes('IndexSyncTable').should.eventually.have.length(1); + }) + }); + + it('should be deleting column "name" as we update the schema and no indexes should be present in db ', function () { + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable).then(async function () { + await getIndexes('IndexSyncTable').should.eventually.have.length(1); + + // dropping column "name" from schema + IndexSyncTable = PersistObjectTemplate.create('IndexSyncTable', { + id: {type: Number} + }); + schema.IndexSyncTable.indexes = []; + + PersistObjectTemplate._verifySchema(); + return PersistObjectTemplate.synchronizeKnexTableFromTemplate(IndexSyncTable, null, true).then(async function () { + //no indexes should be present in pg_indexes; + const result = await knex('pg_indexes').select(['indexname as name']).where({ tablename: 'IndexSyncTable' }); + expect(result).to.be.eql([]); + return getIndexes('IndexSyncTable').should.eventually.have.length(0); + }) + }); + }); + }); \ No newline at end of file diff --git a/components/persistor/test/persist_schema_updates.js b/components/persistor/test/persist_schema_updates.js index 5a686bfd..521f2cd3 100644 --- a/components/persistor/test/persist_schema_updates.js +++ b/components/persistor/test/persist_schema_updates.js @@ -87,7 +87,7 @@ var ExtendParent = Parent.extend('ExtendParent', { var schema = { Employee: { - documentOf: 'pg/employee' + documentOf: 'pg/Employee' }, Manager: { documentOf: 'pg/Manager', @@ -155,7 +155,6 @@ var schema = { var knexInit = require('knex'); var knex; -var schemaTable = 'index_schema_history'; describe('schema update checks', function () { before('arrange', function (done) { @@ -190,13 +189,14 @@ describe('schema update checks', function () { knex.schema.dropTableIfExists('CreateNewType'), knex.schema.dropTableIfExists('newTableWithoutTableDef'), knex.schema.dropTableIfExists('IndexSyncTable').then(function() { - knex.schema.createTableIfNotExists('IndexSyncTable', function (table) { + knex.schema.hasTable('IndexSyncTable').then(function(exists) { + if(exists) return; + return knex.createTable('IndexSyncTable', function (table) { table.double('id'); table.text('name') }) - }), - knex.schema.dropTableIfExists(schemaTable) - + }) + }), ]).should.notify(done); }); after('closes the database', function () { @@ -300,13 +300,11 @@ describe('schema update checks', function () { PersistObjectTemplate._verifySchema(); await PersistObjectTemplate.synchronizeKnexTableFromTemplate(newTablePrimIndex); - const records = await knex(schemaTable).select('schema').orderBy('sequence_id', 'desc').limit(1); - const result = records[0].schema; - - expect(result).contains('NewTablePrimIndex'); + const records = await knex.schema.hasTable('NewTablePrimIndex'); + expect(records).equal(true); }); - it('add a new table definition to the schema and try to synchronize', function () { + it('add a new table definition to the schema and try to synchronize', async function () { schema.newTable = {}; schema.newTable.documentOf = 'pg/NewTable'; var newTable = PersistObjectTemplate.create('newTable', { @@ -319,16 +317,9 @@ describe('schema update checks', function () { }) schema.newTable.indexes = JSON.parse('[{"name": "single_index","def": {"columns": ["id", "name"],"type": "unique"}}]'); PersistObjectTemplate._verifySchema(); - return PersistObjectTemplate.synchronizeKnexTableFromTemplate(newTable, null, true).then(function () { - return knex(schemaTable) - .select('schema') - .orderBy('sequence_id', 'desc') - .limit(1) - .then(function (records) { - return Promise.resolve(records[0].schema); - }) - }).should.eventually.contain('NewTable'); - + await PersistObjectTemplate.synchronizeKnexTableFromTemplate(newTable, null, true) + const records = await knex.schema.hasTable('NewTable'); + expect(records).equal(true); }); diff --git a/components/persistor/test/persist_transaction.js b/components/persistor/test/persist_transaction.js index 242d065e..3cb2ba25 100644 --- a/components/persistor/test/persist_transaction.js +++ b/components/persistor/test/persist_transaction.js @@ -12,8 +12,6 @@ var Promise = require('bluebird'); var knexInit = require('knex'); var knex; var schema = {}; -var schemaTable = 'index_schema_history'; - describe('persist transaction', function () { before('arrange', function (done) { @@ -48,7 +46,6 @@ describe('persist transaction', function () { return knex.schema.dropTableIfExists('tx_persistdelete_employee'); }), knex.schema.dropTableIfExists('tx_deletewot_employee'), - knex.schema.dropTableIfExists(schemaTable) ]).should.notify(done); }); after('closes the database', function () { diff --git a/components/persistor/test/supertype/one-to-manychecks.ts b/components/persistor/test/supertype/one-to-manychecks.ts index 51dc7bd2..dd0a08f8 100644 --- a/components/persistor/test/supertype/one-to-manychecks.ts +++ b/components/persistor/test/supertype/one-to-manychecks.ts @@ -62,7 +62,6 @@ describe('Banking from pgsql Example one-to-manychecks typescript', function () function cleanDB() { return Promise.all([ - knex.schema.dropTableIfExists('index_schema_history'), knex.schema.dropTableIfExists('employee'), knex.schema.dropTableIfExists('responsibility')]); } diff --git a/components/persistor/test/supertype/persist_banking_pgsql.ts b/components/persistor/test/supertype/persist_banking_pgsql.ts index 1396e1da..6d521546 100644 --- a/components/persistor/test/supertype/persist_banking_pgsql.ts +++ b/components/persistor/test/supertype/persist_banking_pgsql.ts @@ -100,10 +100,6 @@ var schema = { } } - - -var schemaTable = 'index_schema_history'; - describe('typescript tests: Banking from pgsql Example persist_banking_pgsql', function () { var knex;