# Copyright (c) 2015, 2020, Oracle and/or its affiliates. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2.0, # as published by the Free Software Foundation. # # This program is also distributed with certain software (including # but not limited to OpenSSL) that is licensed under separate terms, as # designated in a particular file or component or in included license # documentation. The authors of MySQL hereby grant you an additional # permission to link the program and your derivative works with the # separately licensed software that they have included with MySQL. # 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, version 2.0, for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os class ImportScript: def __init__(self): self.error_log_name = 'import_errors.log' @staticmethod def create(target_os): if target_os == 'windows': return ImportScriptWindows() elif target_os == 'linux': return ImportScriptLinux() elif target_os == 'darwin': return ImportScriptDarwin() else: return None def generate_import_script(self, connection_args, path_to_file, schema_name): pass def get_script_ext(self): pass def get_import_cmd(self, table, path_to_file): pass class ImportScriptWindows(ImportScript): def get_import_cmd(self, table, path_to_file): return "LOAD DATA INFILE '%s_#####_import/%s' INTO TABLE %s FIELDS TERMINATED BY ',' ENCLOSED BY '';" % (table['target_schema'], path_to_file, table['target_table']) def get_script_ext(self): return 'cmd' def generate_import_script(self, connection_args, path_to_file, schema_name): output = ['@ECHO OFF'] output.append('echo Started load data. Please wait.') output.append('SET MYPATH=%%~dp0') output.append('IF EXIST %%%%MYPATH%%%%%s del /F %%%%MYPATH%%%%%s' % (self.error_log_name, self.error_log_name)) output.append("SET command=mysql.exe -h127.0.0.1 -P%s -u%s -p -s -N information_schema -e \"SELECT Variable_Value FROM GLOBAL_VARIABLES WHERE Variable_Name = 'datadir'\" 2^>^> %%%%MYPATH%%%%%s" % (connection_args['target_port'], connection_args['target_user'], self.error_log_name)) output.append('FOR /F "tokens=* USEBACKQ" %%%%F IN ^(^`%%command%%^`^) DO ^(') output.append(' SET DADADIR=%%%%F') output.append('^)') output.append('if %%ERRORLEVEL%% GEQ 1 ^(') output.append(' echo Script has failed. See the log file for details.') output.append(' exit /b 1') output.append('^)') output.append('pushd %%DADADIR%%') output.append('mkdir %s_#####_import' % schema_name) output.append('xcopy %%%%MYPATH%%%%*.csv %s_#####_import\* 2^>^> %%%%MYPATH%%%%%s' % (schema_name, self.error_log_name)) output.append('if %%ERRORLEVEL%% GEQ 1 ^(') output.append(' echo Script has failed. See the log file for details.') output.append(' exit /b 1') output.append('^)') output.append('xcopy %%%%MYPATH%%%%*.sql %s_#####_import\* 2^>^> %%%%MYPATH%%%%%s' % (schema_name, self.error_log_name)) output.append('if %%ERRORLEVEL%% GEQ 1 ^(') output.append(' echo Script has failed. See the log file for details.') output.append(' exit /b 1') output.append('^)') output.append('mysql.exe -h127.0.0.1 -P%s -u%s -p ^< %s_#####_import\%s 2^>^> %%%%MYPATH%%%%%s' % (connection_args['target_port'], connection_args['target_user'], schema_name, path_to_file, self.error_log_name)) output.append('if %%ERRORLEVEL%% GEQ 1 ^(') output.append(' echo Script has failed. See the log file for details.') output.append(' exit /b 1') output.append('^)') output.append('rmdir %s_#####_import /s /q' % schema_name) output.append('echo Finished load data') output.append('popd') output.append('pause') return output class ImportScriptLinux(ImportScript): def get_import_cmd(self, table, path_to_file): return "LOAD DATA INFILE '%s_#####_import/%s' INTO TABLE %s FIELDS TERMINATED BY ',' ENCLOSED BY '';" % (table['target_schema'], path_to_file, table['target_table']) def get_script_ext(self): return 'sh' def generate_import_script(self, connection_args, path_to_file, schema_name): output = ['#!/bin/bash'] output.append('MYPATH=\`pwd\`') output.append('if [ -f \$MYPATH/%s ] ; then' % self.error_log_name) output.append(' rm \$MYPATH/%s' % self.error_log_name) output.append('fi') output.append("TARGET_DIR=\`MYSQL_PWD=$arg_target_password mysql -h127.0.0.1 -P%s -u%s -s -N information_schema -e 'SELECT Variable_Value FROM GLOBAL_VARIABLES WHERE Variable_Name = \\\"datadir\\\"'\` 2>> \$MYPATH/%s" % (connection_args['target_port'], connection_args['target_user'], self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('pushd \$TARGET_DIR') output.append('mkdir %s_#####_import' % schema_name) output.append('cp \$MYPATH/*.csv %s_#####_import/ 2>> \$MYPATH/%s' % (schema_name, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('cp \$MYPATH/*.sql %s_#####_import/ 2>> \$MYPATH/%s' % (schema_name, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('echo Started load data. Please wait.') output.append('MYSQL_PWD=$arg_target_password mysql -h127.0.0.1 -P%s -u%s < %s_#####_import/%s 2>> \$MYPATH/%s' % (connection_args['target_port'], connection_args['target_user'], schema_name, path_to_file, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('echo Finished load data') output.append('rm -rf %s_#####_import' % schema_name) output.append('popd') #output.append('read -p Press [Enter] key to continue...') return output class ImportScriptDarwin(ImportScript): def get_import_cmd(self, table, path_to_file): return "LOAD DATA INFILE '%s_#####_import/%s' INTO TABLE %s FIELDS TERMINATED BY ',' ENCLOSED BY '';" % (table['target_schema'], path_to_file, table['target_table']) def get_script_ext(self): return 'sh' def generate_import_script(self, connection_args, path_to_file, schema_name): output = ['#!/bin/bash'] output.append('MYPATH=\`pwd\`') output.append('if [ -f \$MYPATH/%s ] ; then' % self.error_log_name) output.append(' rm \$MYPATH/%s' % self.error_log_name) output.append('fi') output.append("TARGET_DIR=\`MYSQL_PWD=$arg_target_password mysql -h127.0.0.1 -P%s -u%s -s -N information_schema -e 'SELECT Variable_Value FROM GLOBAL_VARIABLES WHERE Variable_Name = \\\"datadir\\\"'\` 2>> \$MYPATH/%s" % (connection_args['target_port'], connection_args['target_user'], self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('pushd \$TARGET_DIR') output.append('mkdir %s_#####_import' % schema_name) output.append('cp \$MYPATH/*.csv %s_#####_import/ 2>> \$MYPATH/%s' % (schema_name, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('cp \$MYPATH/*.sql %s_#####_import/ 2>> \$MYPATH/%s' % (schema_name, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('echo Started load data. Please wait.') output.append('MYSQL_PWD=$arg_target_password mysql -h127.0.0.1 -P%s -u%s < %s_#####_import/%s 2>> \$MYPATH/%s' % (connection_args['target_port'], connection_args['target_user'], schema_name, path_to_file, self.error_log_name)) output.append('if [ \$? -ne 0 ];then') output.append(' echo Script has failed. See the log file for details.') output.append(' exit 1') output.append('fi') output.append('echo Finished load data') output.append('rm -rf %s_#####_import' % schema_name) output.append('popd') #output.append('read -p Press [Enter] key to continue...') return output class SourceRDBMS: def __init__(self, source_os): self.source_os = source_os @staticmethod def create(source_rdbms, source_os): if source_rdbms == 'mssql': return SourceRDBMSMssql(source_os) elif source_rdbms == 'mysql': return SourceRDBMSMysql(source_os) elif source_rdbms == 'postgresql': return SourceRDBMSPostgresql(source_os) elif source_rdbms == 'sqlanywhere': return SourceRDBMSSqlAnywhere(source_os) else: return None def get_copy_table_cmd(self, table):pass class SourceRDBMSMssql(SourceRDBMS): def get_copy_table_cmd(self, table, connection_args): return 'bcp "SELECT %(select_expression)s FROM %(unquoted_source_schema)s.%(unquoted_source_table)s" queryout %(source_table)s.csv -c -t, -T -S .\%(source_instance)s -U %(source_user)s -P %%arg_source_passwords' % dict(list(table.items()) + list(connection_args.items())) class SourceRDBMSMysql(SourceRDBMS): def get_copy_table_cmd(self, table, connection_args): if self.source_os == 'windows': return 'mysqldump.exe --login-path=wb_migration_source -t --tab=. %(source_schema)s %(source_table)s --fields-terminated-by=,' % dict(list(table.items()) + list(connection_args.items())) else: return 'MYSQL_PWD=$arg_source_password mysqldump -h127.0.0.1 -P%(source_port)s -u%(source_user)s -t --tab=/tmp %(source_schema)s %(source_table)s --fields-terminated-by=\',\'' % dict(list(table.items()) + list(connection_args.items())) def get_cfg_editor_cmd(self, connection_args): if self.source_os == 'windows': return 'mysql_config_editor.exe set --login-path=wb_migration_source -h127.0.0.1 -P%(source_port)s -u%(source_user)s -p' % connection_args class SourceRDBMSPostgresql(SourceRDBMS): def get_copy_table_cmd(self, table, connection_args): return 'psql -U %(source_user)s -d %(source_schema)s -c "COPY %(source_table)s TO stdout DELIMITER \',\';" > %(source_table)s.csv' % dict(list(table.items()) + list(connection_args.items())) class SourceRDBMSSqlAnywhere(SourceRDBMS): def get_copy_table_cmd(self, table, connection_args): if self.source_os == 'windows': return """dbisql.exe -c "DBN=%(source_schema)s;UID=%(source_user)s;PWD=%arg_source_password%" "SELECT * FROM %(source_table)s; OUTPUT TO '%(source_table)s.csv' FORMAT TEXT DELIMITED BY ',' QUOTE '';""" % dict(list(table.items()) + list(connection_args.items())) else: return """dbisql -c "DBN=%(source_schema)s;UID=%(source_user)s;PWD=$arg_source_password" "SELECT * FROM %(source_table)s; OUTPUT TO '%(source_table)s.csv' FORMAT TEXT DELIMITED BY ',' QUOTE '';""" % dict(list(table.items()) + list(connection_args.items())) class DataCopyScript: def __init__(self): self.error_log_name = 'bulk_copy_errors.log' @staticmethod def create(source_os): if source_os == 'windows': return DataCopyScriptWindows() elif source_os == 'linux': return DataCopyScriptLinux() elif source_os == 'darwin': return DataCopyScriptDarwin() else: return None def generate(self, tables, script_path, source_rdbms):pass class DataCopyScriptWindows(DataCopyScript): def generate(self, tables, connection_args, script_path, source_rdbms, import_script): progress = 0 total_progress = (3 + len(tables)) source_schema = tables[0]['source_schema'] target_schema = tables[0]['target_schema'] dir_name = 'dump_%s' % source_schema log_file = '%s.log' % dir_name import_file_name = 'import_%s.%s' % (source_schema, import_script.get_script_ext()) import_sql_file_name = 'import_%s.sql' % source_schema with open(script_path, 'w+') as f: f.write('@ECHO OFF\r\n') f.write('SET MYPATH=%~dp0\r\n') f.write('IF EXIST %%MYPATH%%%s del /F %%MYPATH%%%s\r\n' % (self.error_log_name, self.error_log_name)) if isinstance(source_rdbms, SourceRDBMSMysql): f.write('mysql_config_editor.exe remove --login-path=wb_migration_source 2>> "%%MYPATH%%%s"\r\n' % self.error_log_name) f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') f.write('%s 2>> "%%MYPATH%%%s"\r\n' % (source_rdbms.get_cfg_editor_cmd(connection_args), self.error_log_name)) f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') f.write("SET command=mysql.exe -h127.0.0.1 -P%s -u%s -p -s -N information_schema -e \"SELECT Variable_Value FROM GLOBAL_VARIABLES WHERE Variable_Name = 'datadir'\" 2>> \"%%MYPATH%%%s\"\r\n" % (connection_args['source_port'], connection_args['source_user'], self.error_log_name)) f.write('FOR /F "tokens=* USEBACKQ" %%F IN (`%command%`) DO (\r\n') f.write(' SET DADADIR=%%F\r\n') f.write(')\r\n') f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') else: f.write("set arg_source_password=\"\"\r\n") f.write('SET DADADIR=%TEMP%\\\r\n') if not isinstance(import_script, ImportScriptWindows): f.write("set arg_target_password=\"\"\r\n") f.write('pushd %DADADIR%\r\n') f.write('echo [%d %%%%] Creating directory %s\r\n' % (progress, dir_name)) f.write('mkdir %s\r\n' % dir_name) f.write('pushd %s\r\n' % dir_name) progress = progress + 1 f.write('copy NUL %s\r\n' % import_sql_file_name) f.write('echo %s >> %s\r\n' % ('SET SESSION UNIQUE_CHECKS=0;', import_sql_file_name)) f.write('echo %s >> %s\r\n' % ('SET SESSION FOREIGN_KEY_CHECKS=0;', import_sql_file_name)) f.write('echo %s >> %s\r\n' % ('use %s;' % target_schema, import_sql_file_name)) f.write('echo [%d %%%%] Start dumping tables\r\n' % (progress * 100 / total_progress)) for table in tables: f.write('%s 2>> "%%MYPATH%%%s"\r\n' % (source_rdbms.get_copy_table_cmd(table, connection_args), self.error_log_name)) f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') if isinstance(source_rdbms, SourceRDBMSMysql): f.write('rename %s.txt %s.csv\r\n' % (table['source_table'], table['source_table'])) f.write('del %s.sql\r\n' % table['source_table']) f.write('echo %s >> %s\r\n' % (import_script.get_import_cmd(table, '%s.csv' % (table['source_table'])), import_sql_file_name)) progress = progress + 1 f.write('echo [%d %%%%] Dumped table %s\r\n' % (progress * 100 / total_progress, table['source_table'])) f.write('copy NUL %s\r\n' % import_file_name) import_file_lines = import_script.generate_import_script(connection_args, import_sql_file_name, target_schema) for line in import_file_lines: f.write('(echo %s) >> %s\r\n' % (line, import_file_name)) progress = progress + 1 f.write('echo [%d %%%%] Generated import script %s\r\n' % (progress * 100 / total_progress, import_file_name)) f.write('popd\r\n') f.write('set TEMPDIR=%%DADADIR%%%s\r\n' % dir_name) f.write('echo Set fso = CreateObject("Scripting.FileSystemObject") > _zipIt.vbs\r\n') f.write('echo InputFolder = fso.GetAbsolutePathName(WScript.Arguments.Item(0)) >> _zipIt.vbs\r\n') f.write('echo ZipFile = fso.GetAbsolutePathName(WScript.Arguments.Item(1)) >> _zipIt.vbs\r\n') f.write('echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar) >> _zipIt.vbs\r\n') f.write('echo Set objShell = CreateObject("Shell.Application") >> _zipIt.vbs\r\n') f.write('echo Set source = objShell.NameSpace(InputFolder).Items >> _zipIt.vbs\r\n') f.write('echo objShell.NameSpace(ZipFile).CopyHere(source) >> _zipIt.vbs\r\n') f.write('echo Do Until objShell.NameSpace( ZipFile ).Items.Count ^= objShell.NameSpace( InputFolder ).Items.Count >> _zipIt.vbs\r\n') f.write('echo wScript.Sleep 200 >> _zipIt.vbs\r\n') f.write('echo Loop >> _zipIt.vbs\r\n') f.write('CScript _zipIt.vbs "%%TEMPDIR%%" "%%DADADIR%%%s.zip" 2>> "%%MYPATH%%%s"\r\n' % (dir_name, self.error_log_name)) f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') progress = progress + 1 f.write('echo [%d %%%%] Zipped all files to %s.zip file\r\n' % (progress * 100 / total_progress, dir_name)) f.write('xcopy %s.zip %%MYPATH%% 2>> "%%MYPATH%%%s"\r\n' % (dir_name, self.error_log_name)) f.write('if %ERRORLEVEL% GEQ 1 (\r\n') f.write(' echo Script has failed. See the log file for details.\r\n') f.write(' exit /b 1\r\n') f.write(')\r\n') f.write('del %s.zip\r\n' % dir_name) f.write('del _zipIt.vbs\r\n') f.write('del /F /Q %s\*.*\r\n' % dir_name) f.write('rmdir %s\r\n' % dir_name) f.write('popd\r\n') f.write('echo Now you can copy %%MYPATH%%%s.zip file to the target server and run the import script.\r\n' % dir_name) f.write('pause\r\n') class DataCopyScriptLinux(DataCopyScript): def generate(self, tables, connection_args, script_path, source_rdbms, import_script): progress = 0 total_progress = (3 + len(tables)) source_schema = tables[0]['source_schema'] target_schema = tables[0]['target_schema'] dir_name = 'dump_%s' % source_schema log_file = '%s.log' % dir_name import_file_name = 'import_%s.%s' % (source_schema, import_script.get_script_ext()) import_sql_file_name = 'import_%s.sql' % source_schema with open(script_path, 'w+') as f: os.chmod(script_path, 0o700) f.write('#!/bin/bash\n\n') f.write('MYPATH=`pwd`\n') f.write("arg_source_password=\"\"\n") f.write("arg_target_password=\"\"\n") f.write(""" if [ -z "$arg_source_password" ] && [ -z "$arg_target_password" ] ; then echo WARNING: Both source and target RDBMSes passwords are empty. You should edit this file to set them. exit 1 fi """) f.write('if [ -f $MYPATH/%s ] ; then\n' % self.error_log_name) f.write(' rm $MYPATH/%s\n' % self.error_log_name) f.write('fi\n') for table in tables: f.write('if [ -f /tmp/%s.txt ];\n' % table['source_table']) f.write('then\n') f.write(' rm /tmp/%s.txt 2> /dev/null\n' % table['source_table']) f.write(' if [ $? -ne 0 ];then\n') f.write(' echo "File /tmp/%s.txt already exists. You should remove file before running this script."\n' % table['source_table']) f.write(' exit 1\n') f.write(' fi\n') f.write('fi\n') f.write('pushd /tmp\n') f.write('echo [%d %%] Creating directory %s\n' % (progress, dir_name)) f.write('mkdir %s\n' % dir_name) f.write('pushd %s\n' % dir_name) progress = progress + 1 f.write('echo "%s" > %s\n' % ('SET SESSION UNIQUE_CHECKS=0;', import_sql_file_name)) f.write('echo "%s" >> %s\n' % ('SET SESSION FOREIGN_KEY_CHECKS=0;', import_sql_file_name)) f.write('echo "%s" >> %s\n' % ('use %s;' % target_schema, import_sql_file_name)) f.write('echo [%d %%] Start dumping tables\n' % (progress * 100 / total_progress)) for table in tables: f.write('%s 2>> $MYPATH/%s\n' % (source_rdbms.get_copy_table_cmd(table, connection_args), self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') if isinstance(source_rdbms, SourceRDBMSMysql): f.write('cp /tmp/%s.txt %s.csv\n' % (table['source_table'], table['source_table'])) f.write('if [ -f /tmp/%s.sql ];\n' % table['source_table']) f.write('then\n') f.write(' rm /tmp/%s.sql\n' % table['source_table']) f.write('fi\n') f.write('echo "%s" >> %s\n' % (import_script.get_import_cmd(table, '%s.csv' % (table['source_table'])), import_sql_file_name)) progress = progress + 1 f.write('echo [%d %%] Dumped table %s\n' % (progress * 100 / total_progress, table['source_table'])) f.write('touch %s\n' % import_file_name) if isinstance(import_script, ImportScriptDarwin) or isinstance(import_script, ImportScriptLinux): f.write('chmod +x %s\n' % import_file_name) import_file_lines = import_script.generate_import_script(connection_args, import_sql_file_name, target_schema) for line in import_file_lines: f.write('echo "%s" >> %s\n' % (line, import_file_name)) progress = progress + 1 f.write('echo [%d %%] Generated import script %s\n' % (progress * 100 / total_progress, import_file_name)) f.write('popd\n') f.write('zip -r %s.zip %s 2>> $MYPATH/%s\n' % (dir_name, dir_name, self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') progress = progress + 1 f.write('echo [%d %%] Zipped all files to %s.zip file\n' % (progress * 100 / total_progress, dir_name)) f.write('rm -rf %s\n' % dir_name) f.write('cp %s.zip $MYPATH 2>> $MYPATH/%s\n' % (dir_name, self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') f.write('popd\n') f.write('echo Now you can copy $MYPATH/%s.zip file to the target server, unzip it and run the import script.\n' % dir_name) f.write('read -p "Press [Enter] key to continue..."') class DataCopyScriptDarwin(DataCopyScript): def generate(self, tables, connection_args, script_path, source_rdbms, import_script): progress = 0 total_progress = (3 + len(tables)) source_schema = tables[0]['source_schema'] target_schema = tables[0]['target_schema'] dir_name = 'dump_%s' % source_schema log_file = '%s.log' % dir_name import_file_name = 'import_%s.%s' % (source_schema, import_script.get_script_ext()) import_sql_file_name = 'import_%s.sql' % source_schema with open(script_path, 'w+') as f: os.chmod(script_path, 0o700) f.write('#!/bin/bash\n\n') f.write('MYPATH=`pwd`\n') f.write("arg_source_password=\"\"\n") f.write("arg_target_password=\"\"\n") f.write(""" if [ -z "$arg_source_password" ] && [ -z "$arg_target_password" ] ; then echo WARNING: Both source and target RDBMSes passwords are empty. You should edit this file to set them. exit 1 fi """) f.write('if [ -f $MYPATH/%s ] ; then\n' % self.error_log_name) f.write(' rm $MYPATH/%s\n' % self.error_log_name) f.write('fi\n') for table in tables: f.write('if [ -f /tmp/%s.txt ];\n' % table['source_table']) f.write('then\n') f.write(' rm /tmp/%s.txt 2> /dev/null\n' % table['source_table']) f.write(' if [ $? -ne 0 ];then\n') f.write(' echo "File /tmp/%s.txt already exists. You should remove file before running this script."\n' % table['source_table']) f.write(' exit 1\n') f.write(' fi\n') f.write('fi\n') f.write('pushd /tmp\n') f.write('echo [%d %%] Creating directory %s\n' % (progress, dir_name)) f.write('mkdir %s\n' % dir_name) f.write('pushd %s\n' % dir_name) progress = progress + 1 f.write('echo "%s" > %s\n' % ('SET SESSION UNIQUE_CHECKS=0;', import_sql_file_name)) f.write('echo "%s" >> %s\n' % ('SET SESSION FOREIGN_KEY_CHECKS=0;', import_sql_file_name)) f.write('echo "%s" >> %s\n' % ('use %s;' % target_schema, import_sql_file_name)) f.write('echo [%d %%] Start dumping tables\n' % (progress * 100 / total_progress)) for table in tables: f.write('%s 2>> $MYPATH/%s\n' % (source_rdbms.get_copy_table_cmd(table, connection_args), self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') if isinstance(source_rdbms, SourceRDBMSMysql): f.write('cp /tmp/%s.txt %s.csv\n' % (table['source_table'], table['source_table'])) f.write('if [ -f /tmp/%s.sql ];\n' % table['source_table']) f.write('then\n') f.write(' rm /tmp/%s.sql\n' % table['source_table']) f.write('fi\n') f.write('echo "%s" >> %s\n' % (import_script.get_import_cmd(table, '%s.csv' % (table['source_table'])), import_sql_file_name)) progress = progress + 1 f.write('echo [%d %%] Dumped table %s\n' % (progress * 100 / total_progress, table['source_table'])) f.write('touch %s\n' % import_file_name) if isinstance(import_script, ImportScriptDarwin) or isinstance(import_script, ImportScriptLinux): f.write('chmod +x %s\n' % import_file_name) import_file_lines = import_script.generate_import_script(connection_args, import_sql_file_name, target_schema) for line in import_file_lines: f.write('echo "%s" >> %s\n' % (line, import_file_name)) progress = progress + 1 f.write('echo [%d %%] Generated import script %s\n' % (progress * 100 / total_progress, import_file_name)) f.write('popd\n') f.write('zip -r %s.zip %s 2>> $MYPATH/%s\n' % (dir_name, dir_name, self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') progress = progress + 1 f.write('echo [%d %%] Zipped all files to %s.zip file\n' % (progress * 100 / total_progress, dir_name)) f.write('rm -rf %s\n' % dir_name) f.write('cp %s.zip $MYPATH 2>> $MYPATH/%s\n' % (dir_name, self.error_log_name)) f.write('if [ $? -ne 0 ];then\n') f.write(' echo Script has failed. See the log file for details.\n') f.write(' exit 1\n') f.write('fi\n') f.write('popd\n') f.write('echo Now you can copy $MYPATH/%s.zip file to the target server, unzip it and run the import script.\n' % dir_name) f.write('read -p "Press [Enter] key to continue..."') class DataCopyFactory: def __init__(self, source_os, target_os, source_rdbms): self.source_rdbms = SourceRDBMS.create(source_rdbms, source_os) self.datacopy_script = DataCopyScript.create(source_os) self.import_script = ImportScript.create(target_os) def _unquoteIdentifier(self, identifier): if not '.' in identifier: return identifier[1:-1] else: return identifier[identifier.index('.') + 2:-1] def unquoteIdentifiers(self, tables): for table in tables: table['unquoted_source_schema'] = table['source_schema'] table['unquoted_source_table'] = table['source_table'] table['source_schema'] = self._unquoteIdentifier(table['source_schema']) table['target_schema'] = self._unquoteIdentifier(table['target_schema']) table['source_table'] = self._unquoteIdentifier(table['source_table']) table['target_table'] = self._unquoteIdentifier(table['target_table']) def generate(self, tables, connection_args, script_path): self.unquoteIdentifiers(tables) self.datacopy_script.generate(tables, connection_args, script_path, self.source_rdbms, self.import_script)