import * as migrationStateManager from './MigrationStateManager' ; import { log } from './FsOps' ; import Conversion from './Conversion' ; import DBAccess from './DBAccess' ; import DBVendors from './DBVendors' ; import DBAccessQueryResult from './DBAccessQueryResult' ; import IDBAccessQueryParams from './IDBAccessQueryParams' ; import * as extraConfigProcessor from './ExtraConfigProcessor' ; /**
 * Creates foreign keys for given table.
 */ const processForeignKeyWorker = async ( conversion , tableName , rows ) : Promise < void > => { const objConstraints = Object . create ( null ) ; const originalTableName = extraConfigProcessor . getTableName ( conversion , tableName , true ) ; const logTitle = 'ForeignKeyProcessor::processForeignKeyWorker' ; rows . forEach ( ( row ) => { const currentColumnName = extraConfigProcessor . getColumnName ( conversion , originalTableName , row . COLUMN_NAME , false ) ; const currentReferencedTableName = extraConfigProcessor . getTableName ( conversion , row . REFERENCED_TABLE_NAME , false ) ; const originalReferencedTableName = extraConfigProcessor . getTableName ( conversion , row . REFERENCED_TABLE_NAME , true ) ; const currentReferencedColumnName = extraConfigProcessor . getColumnName ( conversion , originalReferencedTableName , row . REFERENCED_COLUMN_NAME , false ) ; if ( row . CONSTRAINT_NAME in objConstraints ) { objConstraints [ row . CONSTRAINT_NAME ] . column_name . push ( `"${ currentColumnName }"` ) ; objConstraints [ row . CONSTRAINT_NAME ] . referenced_column_name . push ( `"${ currentReferencedColumnName }"` ) ; return ; } objConstraints [ row . CONSTRAINT_NAME ] = Object . create ( null ) ; objConstraints [ row . CONSTRAINT_NAME ] . column_name = [ `"${ currentColumnName }"` ] ; objConstraints [ row . CONSTRAINT_NAME ] . referenced_column_name = [ `"${ currentReferencedColumnName }"` ] ; objConstraints [ row . CONSTRAINT_NAME ] . referenced_table_name = currentReferencedTableName ; objConstraints [ row . CONSTRAINT_NAME ] . update_rule = row . UPDATE_RULE ; objConstraints [ row . CONSTRAINT_NAME ] . delete_rule = row . DELETE_RULE ; } ) ; const params = { conversion : conversion , caller : logTitle , sql : '' , vendor : DBVendors . PG , processExitOnError : false , shouldReturnClient : false } ; const constraintsPromises = Object . keys ( objConstraints ) . map ( async ( attr ) => { params . sql = `ALTER TABLE "${ conversion . _schema }"."${ tableName }" 
            ADD FOREIGN KEY (${ objConstraints [ attr ] . column_name . join ( ',' ) }) 
            REFERENCES "${ conversion . _schema }"."${ objConstraints [ attr ] . referenced_table_name }" 
            (${ objConstraints [ attr ] . referenced_column_name . join ( ',' ) }) 
            ON UPDATE ${ objConstraints [ attr ] . update_rule } 
            ON DELETE ${ objConstraints [ attr ] . delete_rule };` ; await DBAccess . query ( params ) ; } ) ; await Promise . all ( constraintsPromises ) ; } ; /**
 * Starts a process of foreign keys creation.
 */ export default async ( conversion ) : Promise < void > => { const logTitle = 'ForeignKeyProcessor::default' ; const isForeignKeysProcessed = await migrationStateManager . get ( conversion , 'foreign_keys_loaded' ) ; if ( isForeignKeysProcessed ) { return ; } const params = { conversion : conversion , caller : logTitle , sql : '' , vendor : DBVendors . MYSQL , processExitOnError : false , shouldReturnClient : false } ; const fkPromises = conversion . _tablesToMigrate . map ( async ( tableName ) => { log ( conversion , `\t--[${ logTitle }] Search foreign keys for table "${ conversion . _schema }"."${ tableName }"...` ) ; params . sql = `SELECT cols.COLUMN_NAME, refs.REFERENCED_TABLE_NAME, refs.REFERENCED_COLUMN_NAME,
            cRefs.UPDATE_RULE, cRefs.DELETE_RULE, cRefs.CONSTRAINT_NAME 
            FROM INFORMATION_SCHEMA.\`COLUMNS\` AS cols 
            INNER JOIN INFORMATION_SCHEMA.\`KEY_COLUMN_USAGE\` AS refs 
            ON refs.TABLE_SCHEMA = cols.TABLE_SCHEMA 
            AND refs.REFERENCED_TABLE_SCHEMA = cols.TABLE_SCHEMA 
            AND refs.TABLE_NAME = cols.TABLE_NAME 
            AND refs.COLUMN_NAME = cols.COLUMN_NAME 
            LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS cRefs 
            ON cRefs.CONSTRAINT_SCHEMA = cols.TABLE_SCHEMA 
            AND cRefs.CONSTRAINT_NAME = refs.CONSTRAINT_NAME 
            LEFT JOIN INFORMATION_SCHEMA.\`KEY_COLUMN_USAGE\` AS links 
            ON links.TABLE_SCHEMA = cols.TABLE_SCHEMA 
            AND links.REFERENCED_TABLE_SCHEMA = cols.TABLE_SCHEMA 
            AND links.REFERENCED_TABLE_NAME = cols.TABLE_NAME 
            AND links.REFERENCED_COLUMN_NAME = cols.COLUMN_NAME 
            LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS cLinks 
            ON cLinks.CONSTRAINT_SCHEMA = cols.TABLE_SCHEMA 
            AND cLinks.CONSTRAINT_NAME = links.CONSTRAINT_NAME 
            WHERE cols.TABLE_SCHEMA = '${ conversion . _mySqlDbName }' 
            AND cols.TABLE_NAME = '${ extraConfigProcessor . getTableName ( conversion , tableName , true ) }';` ; const result = await DBAccess . query ( params ) ; if ( result . error ) { return ; } const extraRows = extraConfigProcessor . parseForeignKeys ( conversion , tableName ) ; const fullRows = ( result . data || [ ] ) . concat ( extraRows ) ; await processForeignKeyWorker ( conversion , tableName , fullRows ) ; log ( conversion , `\t--[${ logTitle }] Foreign keys for table "${ conversion . _schema }"."${ tableName }" are set...` ) ; } ) ; await Promise . all ( fkPromises ) ; } ;