nmig/src/StructureLoader.ts
2019-03-23 20:18:18 +02:00

105 lines
4.5 KiB
TypeScript

/*
* This file is a part of "NMIG" - the database migration tool.
*
* Copyright (C) 2016 - present, Anatoly Khaytovich <anatolyuss@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (please see the "LICENSE.md" file).
* If not, see <http://www.gnu.org/licenses/gpl.txt>.
*
* @author Anatoly Khaytovich <anatolyuss@gmail.com>
*/
import DBAccess from './DBAccess';
import DBAccessQueryResult from './DBAccessQueryResult';
import DBVendors from './DBVendors';
import { log } from './FsOps';
import Conversion from './Conversion';
import Table from './Table';
import { createTable } from './TableProcessor';
import prepareDataChunks from './DataChunksProcessor';
import * as migrationStateManager from './MigrationStateManager';
import * as extraConfigProcessor from './ExtraConfigProcessor';
/**
* Processes current table before data loading.
*/
async function processTableBeforeDataLoading(conversion: Conversion, tableName: string, stateLog: boolean): Promise<void> {
await createTable(conversion, tableName);
await prepareDataChunks(conversion, tableName, stateLog);
}
/**
* Retrieves the source db (MySQL) version.
*/
async function getMySqlVersion(conversion: Conversion): Promise<void> {
const dbAccess: DBAccess = new DBAccess(conversion);
const sql: string = 'SELECT VERSION() AS mysql_version;';
const result: DBAccessQueryResult = await dbAccess.query('StructureLoader::getMySqlVersion', sql, DBVendors.MYSQL, false, false);
if (result.error) {
return;
}
const arrVersion: string[] = result.data[0].mysql_version.split('.');
const majorVersion: string = arrVersion[0];
const minorVersion: string = arrVersion.slice(1).join('');
conversion._mysqlVersion = +(`${ majorVersion }.${ minorVersion }`);
}
/**
* Loads source tables and views, that need to be migrated.
*/
export default async (conversion: Conversion): Promise<Conversion> => {
await getMySqlVersion(conversion);
const dbAccess: DBAccess = new DBAccess(conversion);
const haveTablesLoaded: boolean = await migrationStateManager.get(conversion, 'tables_loaded');
let sql: string = `SHOW FULL TABLES IN \`${ conversion._mySqlDbName }\` WHERE 1 = 1`;
if (conversion._includeTables.length !== 0) {
sql += ` AND Tables_in_${ conversion._mySqlDbName } IN(${ conversion._includeTables.map((table: string) => `"${table}"`).join(',') })`;
}
if (conversion._excludeTables.length !== 0) {
sql += ` AND Tables_in_${ conversion._mySqlDbName } NOT IN(${ conversion._excludeTables.map((table: string) => `"${table}"`).join(',') })`;
}
sql += ';';
const result: DBAccessQueryResult = await dbAccess.query('StructureLoader::default', sql, DBVendors.MYSQL, true, false);
let tablesCnt: number = 0;
let viewsCnt: number = 0;
const processTablePromises: Promise<void>[] = [];
result.data.forEach((row: any) => {
let relationName: string = row[`Tables_in_${ conversion._mySqlDbName }`];
if (row.Table_type === 'BASE TABLE' && conversion._excludeTables.indexOf(relationName) === -1) {
relationName = extraConfigProcessor.getTableName(conversion, relationName, false);
conversion._tablesToMigrate.push(relationName);
conversion._dicTables[relationName] = new Table(`${ conversion._logsDirPath }/${ relationName }.log`);
processTablePromises.push(processTableBeforeDataLoading(conversion, relationName, haveTablesLoaded));
tablesCnt++;
} else if (row.Table_type === 'VIEW') {
conversion._viewsToMigrate.push(relationName);
viewsCnt++;
}
});
const message: string = `\t--[loadStructureToMigrate] Source DB structure is loaded...\n
\t--[loadStructureToMigrate] Tables to migrate: ${ tablesCnt }\n
\t--[loadStructureToMigrate] Views to migrate: ${ viewsCnt }`;
log(conversion, message);
await Promise.all(processTablePromises);
await migrationStateManager.set(conversion, 'tables_loaded');
return conversion;
}