mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
1401 lines
49 KiB
ObjectPascal
1401 lines
49 KiB
ObjectPascal
unit exportsql;
|
|
|
|
|
|
// -------------------------------------
|
|
// Export Tables
|
|
// -------------------------------------
|
|
|
|
|
|
interface
|
|
|
|
uses
|
|
Threading,
|
|
Windows,
|
|
Messages,
|
|
SysUtils,
|
|
Classes,
|
|
Graphics,
|
|
Controls,
|
|
Forms,
|
|
Dialogs,
|
|
StdCtrls,
|
|
ExtCtrls,
|
|
CheckLst,
|
|
Buttons,
|
|
comctrls,
|
|
Registry,
|
|
ToolWin,
|
|
DB,
|
|
SynEdit,
|
|
SynMemo,
|
|
ZDataSet;
|
|
|
|
type
|
|
TExportSQLForm = class(TForm)
|
|
btnExport: TButton;
|
|
btnCancel: TButton;
|
|
dialogSave: TSaveDialog;
|
|
barProgress: TProgressBar;
|
|
lblProgress: TLabel;
|
|
pageControl1: TPageControl;
|
|
TabSheet1: TTabSheet;
|
|
TabSheet2: TTabSheet;
|
|
lblSelectDbTables: TLabel;
|
|
checkListTables: TCheckListBox;
|
|
comboSelectDatabase: TComboBox;
|
|
toolbarSelectTools: TToolBar;
|
|
ToolButton1: TToolButton;
|
|
ToolButton2: TToolButton;
|
|
groupOutput: TGroupBox;
|
|
btnFileBrowse: TBitBtn;
|
|
editFileName: TEdit;
|
|
radioOtherDatabase: TRadioButton;
|
|
radioFile: TRadioButton;
|
|
comboOtherDatabase: TComboBox;
|
|
radioOtherHost: TRadioButton;
|
|
comboOtherHost: TComboBox;
|
|
comboOtherHostDatabase: TComboBox;
|
|
groupExampleSql: TGroupBox;
|
|
SynMemoExampleSQL: TSynMemo;
|
|
groupOptions: TGroupBox;
|
|
lblTargetCompat: TLabel;
|
|
cbxStructure: TCheckBox;
|
|
cbxDatabase: TCheckBox;
|
|
comboDatabase: TComboBox;
|
|
cbxTables: TCheckBox;
|
|
comboTables: TComboBox;
|
|
cbxData: TCheckBox;
|
|
comboData: TComboBox;
|
|
comboTargetCompat: TComboBox;
|
|
procedure comboTargetCompatChange(Sender: TObject);
|
|
procedure comboOtherHostSelect(Sender: TObject);
|
|
procedure comboDataChange(Sender: TObject);
|
|
procedure comboTablesChange(Sender: TObject);
|
|
procedure comboDatabaseChange(Sender: TObject);
|
|
procedure cbxTablesClick(Sender: TObject);
|
|
procedure cbxDatabaseClick(Sender: TObject);
|
|
procedure btnCancelClick(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure comboSelectDatabaseChange(Sender: TObject);
|
|
procedure CheckListToggle(Sender: TObject);
|
|
procedure btnFileBrowseClick(Sender: TObject);
|
|
procedure btnExportClick(Sender: TObject);
|
|
procedure radioOtherDatabaseClick(Sender: TObject);
|
|
procedure radioFileClick(Sender: TObject);
|
|
procedure fillcombo_anotherdb(Sender: TObject);
|
|
procedure generateExampleSQL;
|
|
procedure validateRadioControls(Sender: TObject);
|
|
procedure validateControls(Sender: TObject);
|
|
procedure cbxStructureClick(Sender: TObject);
|
|
procedure radioOtherHostClick(Sender: TObject);
|
|
procedure cbxDataClick(Sender: TObject);
|
|
procedure checkListTablesKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
procedure SaveSettings;
|
|
private
|
|
{ Private declarations }
|
|
public
|
|
{ Public declarations }
|
|
end;
|
|
|
|
function ExportTablesWindow (AOwner : TComponent; Flags : String = '') : Boolean;
|
|
|
|
{$I const.inc}
|
|
|
|
implementation
|
|
|
|
uses
|
|
Main,
|
|
Childwin,
|
|
Helpers,
|
|
Synchronization,
|
|
Communication;
|
|
|
|
{$R *.DFM}
|
|
|
|
const
|
|
// Order of items in combo box: comboDatabase
|
|
DB_DROP_CREATE = 0;
|
|
DB_CREATE = 1;
|
|
DB_CREATE_IGNORE = 2;
|
|
// Order of items in combo box: comboTables
|
|
TAB_DROP_CREATE = 0;
|
|
TAB_CREATE = 1;
|
|
TAB_CREATE_IGNORE = 2;
|
|
// Order of items in combo box: comboData
|
|
DATA_TRUNCATE_INSERT = 0;
|
|
DATA_INSERT = 1;
|
|
DATA_INSERT_IGNORE = 2;
|
|
DATA_REPLACE_INTO = 3;
|
|
// Order of radiobutton group "Output"
|
|
OUTPUT_FILE = 1;
|
|
OUTPUT_DB = 2;
|
|
OUTPUT_HOST = 3;
|
|
|
|
// Default output compatibility
|
|
SQL_VERSION_DEFAULT = SQL_VERSION_ANSI;
|
|
|
|
var
|
|
appHandles: array of THandle;
|
|
cancelDialog: TForm = nil;
|
|
remote_version: integer;
|
|
remote_max_allowed_packet : Int64;
|
|
target_versions : TStringList;
|
|
|
|
function ExportTablesWindow (AOwner : TComponent; Flags : String = '') : Boolean;
|
|
var
|
|
f : TExportSQLForm;
|
|
begin
|
|
f := TExportSQLForm.Create(AOwner);
|
|
// todo: pass params if needed
|
|
Result := (f.ShowModal = mrOK);
|
|
FreeAndNil (f);
|
|
end;
|
|
|
|
procedure TExportSQLForm.btnCancelClick(Sender: TObject);
|
|
begin
|
|
close;
|
|
end;
|
|
|
|
procedure TExportSQLForm.FormShow(Sender: TObject);
|
|
var
|
|
tn : TTreeNode;
|
|
i, OutputTo : Integer;
|
|
dbtree_db : String;
|
|
list: TWindowDataArray;
|
|
begin
|
|
barProgress.Position := 0;
|
|
lblProgress.Caption := '';
|
|
PageControl1.ActivePageIndex := 0;
|
|
SynMemoExampleSQL.Highlighter := Mainform.ChildWin.SynSQLSyn1;
|
|
SynMemoExampleSQL.Font := Mainform.ChildWin.SynMemoQuery.Font;
|
|
|
|
// read dbs and Tables from treeview
|
|
comboSelectDatabase.Items.Clear;
|
|
Caption := Mainform.ChildWin.MysqlConn.Description + ' - Export Tables...';
|
|
for i:=0 to Mainform.ChildWin.DBTree.Items.Count-1 do
|
|
begin
|
|
tn := Mainform.ChildWin.DBTree.Items[i];
|
|
if tn.Level = 1 then
|
|
comboSelectDatabase.Items.Add(tn.Text);
|
|
end;
|
|
|
|
if Mainform.ChildWin.DBRightClickSelectedItem <> nil then
|
|
begin
|
|
case Mainform.ChildWin.DBRightClickSelectedItem.Level of
|
|
1 : dbtree_db := Mainform.ChildWin.DBRightClickSelectedItem.Text;
|
|
2 : dbtree_db := Mainform.ChildWin.DBRightClickSelectedItem.Parent.Text;
|
|
3 : dbtree_db := Mainform.ChildWin.DBRightClickSelectedItem.Parent.Parent.Text;
|
|
end;
|
|
end;
|
|
|
|
for i:=0 to comboSelectDatabase.Items.Count-1 do
|
|
begin
|
|
if ((dbtree_db = '') and (comboSelectDatabase.Items[i] = Mainform.ChildWin.ActualDatabase))
|
|
or ((dbtree_db <> '') and (comboSelectDatabase.Items[i] = dbtree_db)) then
|
|
begin
|
|
comboSelectDatabase.ItemIndex := i;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
if comboSelectDatabase.ItemIndex = -1 then
|
|
comboSelectDatabase.ItemIndex := 0;
|
|
|
|
comboSelectDatabaseChange(self);
|
|
|
|
// Initialize and fill list with target versions
|
|
target_versions := TStringList.Create;
|
|
with target_versions do
|
|
begin
|
|
Add( IntToStr( SQL_VERSION_ANSI ) + '=Standard ANSI SQL' );
|
|
Add( '32300=MySQL 3.23' );
|
|
Add( '40000=MySQL 4.0' );
|
|
Add( '40100=MySQL 4.1' );
|
|
Add( '50000=MySQL 5.0' );
|
|
Add( '50100=MySQL 5.1' );
|
|
Add( IntToStr( Mainform.ChildWin.mysql_version ) + '=Same as source server (MySQL '+Mainform.ChildWin.GetVar('SELECT VERSION()') +')' );
|
|
end;
|
|
|
|
// Add all target versions to combobox and set default option
|
|
comboTargetCompat.Items.Clear;
|
|
for i := 0 to target_versions.Count - 1 do
|
|
begin
|
|
comboTargetCompat.Items.Add( target_versions.ValueFromIndex[i] );
|
|
if( target_versions.Names[i] = IntToStr( SQL_VERSION_DEFAULT ) ) then
|
|
begin
|
|
comboTargetCompat.ItemIndex := i;
|
|
end;
|
|
end;
|
|
|
|
// Read options
|
|
with TRegistry.Create do
|
|
if OpenKey(REGPATH, true) then begin
|
|
// WithUseDB, UseBackticks, CompleteInserts: deprecated (hardcoded true now)
|
|
if Valueexists('ExportStructure') then cbxStructure.Checked := ReadBool('ExportStructure');
|
|
if Valueexists('WithCreateDatabase') then cbxDatabase.Checked := ReadBool('WithCreateDatabase');
|
|
if Valueexists('WithCreateTable') then cbxTables.Checked := ReadBool('WithCreateTable');
|
|
if Valueexists('ExportData') then cbxData.Checked := ReadBool('ExportData');
|
|
if Valueexists('CreateDatabaseHow') then comboDatabase.ItemIndex := ReadInteger('CreateDatabaseHow');
|
|
if Valueexists('CreateTablesHow') then comboTables.ItemIndex := ReadInteger('CreateTablesHow')
|
|
else if Valueexists('WithDropTable') and ReadBool('WithDropTable') then comboTables.ItemIndex := TAB_DROP_CREATE;
|
|
if Valueexists('CreateDataHow') then comboData.ItemIndex := ReadInteger('CreateDataHow');
|
|
if Valueexists('Compatibility') then comboTargetCompat.ItemIndex := ReadInteger('Compatibility');
|
|
if Valueexists('exportfilename') then editFileName.Text := ReadString('exportfilename');
|
|
if Valueexists('ExportSQL_OutputTo') then
|
|
begin
|
|
OutputTo := ReadInteger('ExportSQL_OutputTo');
|
|
|
|
{***
|
|
@note ansgarbecker, 2007-02-24
|
|
If OutputTo is now OUTPUT_HOST and there are no other windows
|
|
to export to, reset OutputTo to OUTPUT_FILE to avoid the error-popup
|
|
"You need at least 2 windows...", which should not be fired in
|
|
FormShow rather than only when the user has really clicked that
|
|
radiobutton.
|
|
As a benefit, the OUTPUT_FILE won't be saved to registry here
|
|
so the OUTPUT_HOST is still enabled in registry and will be used
|
|
the next time if we have more than 1 window
|
|
@see bug #1666054
|
|
}
|
|
// Check if all the heidisql windows are still alive.
|
|
CheckForCrashedWindows;
|
|
// Fetch list of heidisql windows.
|
|
list := GetWindowList;
|
|
if Length(list) < 2 then
|
|
OutputTo := OUTPUT_FILE;
|
|
|
|
case OutputTo of
|
|
OUTPUT_FILE : radioFile.Checked := true;
|
|
OUTPUT_DB : radioOtherDatabase.Checked := true;
|
|
OUTPUT_HOST : radioOtherHost.Checked := true;
|
|
end;
|
|
end;
|
|
if ValueExists('ExportSQL_WindowWidth') then Width := ReadInteger('ExportSQL_WindowWidth');
|
|
if ValueExists('ExportSQL_WindowHeight') then Height := ReadInteger('ExportSQL_WindowHeight');
|
|
end;
|
|
|
|
if EditFileName.Text = '' then
|
|
EditFileName.Text := ExtractFilePath(paramstr(0)) + 'export.sql';
|
|
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
|
|
procedure TExportSQLForm.comboDatabaseChange(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.comboDataChange(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.comboOtherHostSelect(Sender: TObject);
|
|
var
|
|
data: TDataSet;
|
|
j: integer;
|
|
versions : TStringList;
|
|
begin
|
|
// Get both databases and version right when the radio
|
|
// is clicked, so we can switch to the 'file' radio
|
|
// immediately when something goes wrong.
|
|
try
|
|
data := RemoteExecQuery(
|
|
appHandles[comboOtherHost.ItemIndex],
|
|
'SHOW DATABASES',
|
|
'Fetching remote list of databases...'
|
|
);
|
|
comboOtherHostDatabase.Clear;
|
|
for j:=0 to data.RecordCount - 1 do begin
|
|
comboOtherHostDatabase.Items.Add(data.FieldByName('Database').AsString);
|
|
data.Next;
|
|
end;
|
|
data.Free;
|
|
|
|
data := RemoteExecQuery(
|
|
appHandles[comboOtherHost.ItemIndex],
|
|
'SELECT VERSION()',
|
|
'Probing for remote version...'
|
|
);
|
|
versions := explode('.', data.Fields[0].AsString);
|
|
remote_version := MakeInt(versions[0]) * 10000 + MakeInt(versions[1]) * 100 + MakeInt(versions[2]);
|
|
data.Free;
|
|
|
|
// Fetch the max_allowed_packet variable to be sure not to
|
|
// overload the server when using "Extended Insert"
|
|
data := RemoteExecQuery(
|
|
appHandles[comboOtherHost.ItemIndex],
|
|
'SHOW VARIABLES LIKE "max_allowed_packet"',
|
|
'Checking for maximum allowed SQL-packet size on server '+comboOtherHost.Text+'...'
|
|
);
|
|
remote_max_allowed_packet := MakeInt( data.FieldByName('Value').AsString );
|
|
data.Free;
|
|
except
|
|
on E: Exception do begin
|
|
ShowMessage(E.Message);
|
|
radioFile.Checked := true;
|
|
E.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TExportSQLForm.comboSelectDatabaseChange(Sender: TObject);
|
|
var
|
|
i,j : Integer;
|
|
dbtree_table : String;
|
|
begin
|
|
// read tables from db
|
|
checkListTables.Items.Clear;
|
|
|
|
// Fetch tables from DB
|
|
// todo: skip views or add complete support for views.
|
|
checkListTables.Items := Mainform.ChildWin.GetCol( 'SHOW TABLES FROM ' + MainForm.mask(comboSelectDatabase.Text) );
|
|
|
|
// select all/some:
|
|
for i:=0 to checkListTables.Items.Count-1 do
|
|
begin
|
|
if Mainform.ChildWin.DBRightClickSelectedItem <> nil then
|
|
begin
|
|
case Mainform.ChildWin.DBRightClickSelectedItem.Level of
|
|
2 : dbtree_table := Mainform.ChildWin.DBRightClickSelectedItem.Text;
|
|
3 : dbtree_table := Mainform.ChildWin.DBRightClickSelectedItem.Parent.Text;
|
|
end;
|
|
case Mainform.ChildWin.DBRightClickSelectedItem.Level of
|
|
1 : checkListTables.checked[i] := true;
|
|
2,3 : checkListTables.checked[i] := dbtree_table = checkListTables.Items[i];
|
|
end;
|
|
end
|
|
else if Mainform.ChildWin.ActualDatabase = comboSelectDatabase.Text then
|
|
for j:=0 to Mainform.ChildWin.ListTables.Items.Count-1 do
|
|
begin
|
|
if checkListTables.Items[i] = Mainform.ChildWin.ListTables.Items[j].Caption then
|
|
begin
|
|
checkListTables.checked[i] := Mainform.ChildWin.ListTables.Items[j].Selected;
|
|
break;
|
|
end;
|
|
end
|
|
else
|
|
checkListTables.checked[i] := true;
|
|
end;
|
|
Mainform.ChildWin.DBRightClickSelectedItem := nil;
|
|
|
|
// write items for "Another Databases":
|
|
fillcombo_anotherdb(self);
|
|
end;
|
|
|
|
|
|
procedure TExportSQLForm.comboTablesChange(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.comboTargetCompatChange(Sender: TObject);
|
|
begin
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.CheckListToggle(Sender: TObject);
|
|
begin
|
|
// check all or none
|
|
ToggleCheckListBox(checkListTables, ((Sender as TControl).Tag = 1));
|
|
end;
|
|
|
|
|
|
|
|
procedure TExportSQLForm.btnFileBrowseClick(Sender: TObject);
|
|
begin
|
|
dialogSave.Filename := comboSelectDatabase.Text;
|
|
if dialogSave.Execute then
|
|
if dialogSave.Filename <> '' then
|
|
EditFileName.Text := dialogSave.Filename;
|
|
end;
|
|
|
|
|
|
procedure TExportSQLForm.btnExportClick(Sender: TObject);
|
|
var
|
|
f : TFileStream;
|
|
i,j,k,m : Integer;
|
|
exportdb,exporttables : boolean;
|
|
exportdata : boolean;
|
|
dropquery,createquery,insertquery,
|
|
columnnames : String;
|
|
keylist : Array of TMyKey;
|
|
keystr,DB2export : String;
|
|
which : Integer;
|
|
tofile,todb,tohost : boolean;
|
|
tcount,tablecounter : Integer;
|
|
win2export : THandle;
|
|
StrProgress : String;
|
|
value : String;
|
|
Escaped,fullvalue : PChar;
|
|
extended_insert : Boolean;
|
|
max_allowed_packet : Int64;
|
|
thesevalues : String;
|
|
valuescount, limit : Integer;
|
|
donext : Boolean;
|
|
PBuffer : PChar;
|
|
sql, current_characterset : String;
|
|
target_version, loopnumber: Integer;
|
|
ansi : Boolean;
|
|
RecordCount_all, RecordCount_one, RecordNo_all,
|
|
offset : Int64;
|
|
sql_select : String;
|
|
cwin : TMDIChild;
|
|
query : TDataSet;
|
|
begin
|
|
// export!
|
|
pageControl1.ActivePageIndex := 0;
|
|
Screen.Cursor := crHourGlass;
|
|
|
|
// Initialize default-variables
|
|
target_version := SQL_VERSION_DEFAULT;
|
|
max_allowed_packet := 1024*1024;
|
|
|
|
// export what?
|
|
exportdb := cbxDatabase.Enabled and cbxDatabase.Checked;
|
|
exporttables := cbxTables.Enabled and cbxTables.Checked;
|
|
exportdata := cbxData.Checked;
|
|
|
|
// to where?
|
|
tofile := radioFile.Checked;
|
|
todb := radioOtherDatabase.Checked;
|
|
tohost := radioOtherHost.Checked;
|
|
|
|
// for easy use of methods in childwin
|
|
cwin := Mainform.ChildWin;
|
|
|
|
{***
|
|
@note ansgarbecker
|
|
For "export to file" set max_allowed_packet to the default-value
|
|
in mysql-server to be safe on most servers.
|
|
For "export to another db" set max_allowed_packet to the value set on current host
|
|
For "export to other host" set max_allowed_packet to the value set on remote host
|
|
@see http://dev.mysql.com/doc/refman/5.0/en/packet-too-large.html
|
|
}
|
|
|
|
// Export to .sql-file on disk
|
|
if tofile then begin
|
|
// Extract name part of selected target version
|
|
target_version := StrToIntDef( target_versions.Names[ comboTargetCompat.ItemIndex ], SQL_VERSION_DEFAULT );
|
|
try
|
|
f := TFileStream.Create(EditFileName.Text, fmCreate);
|
|
except
|
|
messagedlg('File "'+EditFileName.Text+'" could not be opened!' + crlf + 'Maybe in use by another application?', mterror, [mbOK], 0);
|
|
f.free;
|
|
Screen.Cursor := crDefault;
|
|
abort;
|
|
end;
|
|
wfs(f, '# ' + APPNAME + ' Dump ');
|
|
wfs(f, '#');
|
|
DB2export := comboSelectDatabase.Text;
|
|
end;
|
|
|
|
// Export to other database in the same window
|
|
if todb then begin
|
|
target_version := cwin.mysql_version;
|
|
max_allowed_packet := MakeInt( cwin.GetVar( 'SHOW VARIABLES LIKE ''max_allowed_packet''', 1 ) );
|
|
DB2export := comboOtherDatabase.Text;
|
|
end;
|
|
|
|
// Export to other window/host
|
|
if tohost then begin
|
|
target_version := remote_version;
|
|
max_allowed_packet := remote_max_allowed_packet;
|
|
win2export := appHandles[comboOtherHost.ItemIndex];
|
|
if cbxDatabase.Checked then
|
|
begin
|
|
// Use original DB-name from source-server
|
|
DB2export := comboSelectDatabase.Text;
|
|
end
|
|
else
|
|
// Use existing DB-name on target-server
|
|
DB2export := comboOtherHostDatabase.Items[comboOtherHostDatabase.ItemIndex];
|
|
end;
|
|
|
|
// MySQL has supported extended insert since 3.23.
|
|
extended_insert := not (target_version = SQL_VERSION_ANSI);
|
|
|
|
try
|
|
// Be sure to read everything from the correct database
|
|
cwin.ExecUseQuery( comboSelectDatabase.Text );
|
|
|
|
{***
|
|
Ouput useful header information only when exporting to file
|
|
}
|
|
if tofile then
|
|
begin
|
|
wfs(f, '# --------------------------------------------------------');
|
|
wfs(f, '# Host: ' + cwin.MysqlConn.Connection.HostName );
|
|
wfs(f, '# Database: ' + DB2export );
|
|
wfs(f, '# Server version: ' + cwin.GetVar( 'SELECT VERSION()' ) );
|
|
wfs(f, '# Server OS: ' + cwin.GetVar( 'SHOW VARIABLES LIKE "version_compile_os"', 1 ) );
|
|
wfs(f, '# Target-Compatibility: ' + comboTargetCompat.Text );
|
|
if extended_insert then
|
|
begin
|
|
wfs(f, '# max_allowed_packet: ' + inttostr(max_allowed_packet) );
|
|
end;
|
|
wfs(f, '# ' + APPNAME + ' version: ' + appversion );
|
|
wfs(f, '# --------------------------------------------------------');
|
|
wfs(f);
|
|
end;
|
|
|
|
{***
|
|
Some actions which are only needed if we're not in OtherDatabase-mode:
|
|
Set character set, create and use database.
|
|
}
|
|
if tofile or tohost then
|
|
begin
|
|
{***
|
|
Set characterset to current one
|
|
}
|
|
if cwin.mysql_version > 40100 then
|
|
current_characterset := cwin.GetVar( 'SHOW VARIABLES LIKE "character_set_connection"', 1 )
|
|
else if cwin.mysql_version > 40000 then
|
|
// todo: test this, add charolation --> charset conversion table from 4.0 to 4.1+
|
|
current_characterset := cwin.GetVar( 'SHOW VARIABLES LIKE "character_set"', 1 )
|
|
else
|
|
// todo: test this
|
|
current_characterset := 'binary';
|
|
|
|
if current_characterset <> '' then
|
|
begin
|
|
sql := '/*!40100 SET CHARACTER SET ' + current_characterset + ';*/';
|
|
sql := fixSQL( sql, target_version );
|
|
if tofile then
|
|
wfs(f, sql)
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql );
|
|
end;
|
|
|
|
// Switch to correct SQL_MODE so MySQL doesn't reject ANSI SQL
|
|
if target_version = SQL_VERSION_ANSI then
|
|
begin
|
|
sql := '/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=''ANSI'' ;*/';
|
|
if tofile then
|
|
wfs(f, sql)
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql );
|
|
end;
|
|
|
|
if exportdb then
|
|
begin
|
|
{***
|
|
DROP statement for database
|
|
}
|
|
if tofile then
|
|
begin
|
|
wfs(f);
|
|
wfs(f);
|
|
wfs(f, '#');
|
|
wfs(f, '# Database structure for database ''' + DB2export + '''');
|
|
wfs(f, '#');
|
|
wfs(f);
|
|
end;
|
|
if comboDatabase.ItemIndex = DB_DROP_CREATE then
|
|
begin
|
|
sql := 'DROP DATABASE IF EXISTS ' + maskSql(target_version, DB2export) + ';';
|
|
if tofile then
|
|
wfs(f, sql)
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql );
|
|
end;
|
|
|
|
{***
|
|
CREATE statement for database plus database-switching
|
|
}
|
|
if cwin.mysql_version < 50002 then
|
|
begin
|
|
sql := 'CREATE DATABASE ';
|
|
if comboDatabase.ItemIndex = DB_CREATE_IGNORE then
|
|
begin
|
|
sql := sql + '/*!32312 IF NOT EXISTS*/ ';
|
|
end;
|
|
sql := sql + maskSql(target_version, DB2export) + ';';
|
|
end
|
|
else
|
|
begin
|
|
sql := cwin.GetVar( 'SHOW CREATE DATABASE ' + mainform.mask(DB2export), 1 );
|
|
sql := fixNewlines(sql) + ';';
|
|
if target_version = SQL_VERSION_ANSI then
|
|
sql := StringReplace(sql, '`', '"', [rfReplaceAll]);
|
|
if comboDatabase.ItemIndex = DB_CREATE_IGNORE then
|
|
begin
|
|
Insert('/*!32312 IF NOT EXISTS*/ ', sql, Pos('DATABASE', sql) + 9);
|
|
end;
|
|
end;
|
|
sql := fixSQL( sql, target_version);
|
|
if tofile then
|
|
wfs(f, sql )
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql );
|
|
if exporttables then
|
|
begin
|
|
sql := 'USE ' + maskSql(target_version, DB2export) + ';';
|
|
if tofile then
|
|
begin
|
|
wfs(f);
|
|
wfs(f, sql);
|
|
end
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// How many tables?
|
|
tcount := 0;
|
|
for i:=0 to checkListTables.Items.Count-1 do if checkListTables.checked[i] then inc(tcount);
|
|
barProgress.Max := 0;
|
|
if exporttables then
|
|
barProgress.Max := tcount;
|
|
if exportdata then
|
|
barProgress.Max := barProgress.Max + tcount;
|
|
|
|
checkListTables.ItemIndex := -1;
|
|
tablecounter := 0;
|
|
|
|
for i:=0 to checkListTables.Items.Count-1 do if checkListTables.checked[i] then
|
|
begin
|
|
inc(tablecounter);
|
|
if checkListTables.ItemIndex > -1 then
|
|
checkListTables.Checked[checkListTables.ItemIndex] := false;
|
|
checkListTables.ItemIndex := i;
|
|
StrProgress := 'Table ' + inttostr(tablecounter) + '/' + inttostr(tcount) + ': ' + checkListTables.Items[i];
|
|
lblProgress.caption := StrProgress;
|
|
|
|
if exporttables then
|
|
begin
|
|
dropquery := '';
|
|
if comboTables.ItemIndex = TAB_DROP_CREATE then begin
|
|
if tofile then
|
|
dropquery := 'DROP TABLE IF EXISTS ' + maskSql(target_version, checkListTables.Items[i])
|
|
else
|
|
dropquery := 'DROP TABLE IF EXISTS ' + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]);
|
|
end;
|
|
|
|
createquery := '';
|
|
if tofile then begin
|
|
createquery := '#' + crlf;
|
|
createquery := createquery + '# Table structure for table ''' + checkListTables.Items[i] + '''' + crlf;
|
|
createquery := createquery + '#' + crlf + crlf;
|
|
end;
|
|
|
|
{***
|
|
Let the server generate the CREATE TABLE statement if the version allows that
|
|
}
|
|
if cwin.mysql_version >= 32320 then
|
|
begin
|
|
Query := cwin.GetResults('SHOW CREATE TABLE ' + mainform.mask(checkListTables.Items[i]));
|
|
sql := Query.Fields[1].AsString;
|
|
sql := fixNewlines(sql);
|
|
// Skip VIEWS. Not foolproof, but good enough until more support for information_schema (fallback to? regexp?) is added.
|
|
// todo: implement working support for views.
|
|
if (Pos(' TABLE `', sql) = 0) and (Pos(' VIEW `', sql) > 0) then continue;
|
|
if Pos('DEFAULT CHARSET', sql) > 0 then begin
|
|
Insert('/*!40100 ', sql, Pos('DEFAULT CHARSET', sql));
|
|
sql := sql + '*/';
|
|
end;
|
|
if target_version = SQL_VERSION_ANSI then
|
|
begin
|
|
sql := StringReplace(sql, '`', '"', [rfReplaceAll]);
|
|
j := max(pos('TYPE=', sql), pos('ENGINE=', sql));
|
|
// Delphi's Pos() lacks a start-at parameter. Admittedly very ugly hack to achieve said effect.
|
|
k := 0;
|
|
while k <= j do k := k + 1 + Pos(' ', Copy(sql, k + 1, Length(sql)));
|
|
Delete(sql, j, k - j);
|
|
end;
|
|
{***
|
|
@note ansgarbecker
|
|
The ENGINE and TYPE options specify the storage engine for the table.
|
|
ENGINE was added in MySQL 4.0.18 (for 4.0) and 4.1.2 (for 4.1).
|
|
It is the preferred option name as of those versions, and TYPE has
|
|
become deprecated. TYPE is supported throughout the 4.x series, but
|
|
likely will be removed in the future.
|
|
@see http://dev.mysql.com/doc/refman/4.1/en/create-table.html
|
|
}
|
|
if target_version < 40000 then
|
|
begin
|
|
sql := stringreplace(sql, 'ENGINE=', 'TYPE=', [rfReplaceAll]);
|
|
end
|
|
else if target_version >= 51000 then
|
|
begin
|
|
sql := stringreplace(sql, 'TYPE=', 'ENGINE=', [rfReplaceAll]);
|
|
end;
|
|
sql := fixSQL( sql, target_version );
|
|
end
|
|
{***
|
|
Generate CREATE TABLE statement by hand on old servers
|
|
}
|
|
else if cwin.mysql_version < 32320 then begin
|
|
Query := cwin.GetResults( 'SHOW COLUMNS FROM ' + mainform.mask(checkListTables.Items[i]));
|
|
if tofile then
|
|
sql := 'CREATE TABLE IF NOT EXISTS ' + maskSql(target_version, checkListTables.Items[i]) + ' (' + crlf
|
|
else
|
|
sql := sql + 'CREATE TABLE IF NOT EXISTS ' + maskSql(target_version, DB2Export) + '.' + cwin.mask(checkListTables.Items[i]) + ' (' + crlf;
|
|
for j := 1 to Query.Fieldcount do
|
|
begin
|
|
sql := sql + ' ' + maskSql(target_version, Query.Fields[0].AsString) + ' ' + Query.Fields[1].AsString;
|
|
if Query.Fields[2].AsString <> 'YES' then
|
|
sql := sql + ' NOT NULL';
|
|
if Query.Fields[4].AsString <> '' then
|
|
sql := sql + ' DEFAULT ''' + Query.Fields[4].AsString + '''';
|
|
if Query.Fields[5].AsString <> '' then
|
|
sql := sql + ' ' + Query.Fields[5].AsString;
|
|
if j < Query.Fieldcount then
|
|
sql := sql + ',' + crlf;
|
|
end;
|
|
|
|
// Keys:
|
|
Query := cwin.GetResults( 'SHOW KEYS FROM ' + cwin.mask(checkListTables.Items[i]));
|
|
setLength(keylist, 0);
|
|
keystr := '';
|
|
if Query.RecordCount > 0 then
|
|
keystr := ',';
|
|
|
|
for j := 1 to Query.RecordCount do
|
|
begin
|
|
which := -1;
|
|
|
|
for k:=0 to length(keylist)-1 do
|
|
begin
|
|
if keylist[k].Name = Query.Fields[2].AsString then // keyname exists!
|
|
which := k;
|
|
end;
|
|
if which = -1 then
|
|
begin
|
|
setlength(keylist, length(keylist)+1);
|
|
which := high(keylist);
|
|
keylist[which].Columns := TStringList.Create;
|
|
with keylist[which] do // set properties for new key
|
|
begin
|
|
Name := Query.Fields[2].AsString;
|
|
if Query.Fields[2].AsString = 'PRIMARY' then
|
|
_type := 'PRIMARY'
|
|
else if Query.FieldCount >= 10 then if Query.Fields[9].AsString = 'FULLTEXT' then
|
|
_type := 'FULLTEXT'
|
|
else if Query.Fields[1].AsString = '1' then
|
|
_type := ''
|
|
else if Query.Fields[1].AsString = '0' then
|
|
_type := 'UNIQUE';
|
|
end;
|
|
end;
|
|
keylist[which].Columns.add(maskSql(target_version, Query.Fields[4].AsString)); // add column(s)
|
|
Query.Next;
|
|
end;
|
|
for k:=0 to high(keylist) do
|
|
begin
|
|
if k > 0 then
|
|
keystr := keystr + ',';
|
|
if keylist[k].Name = 'PRIMARY' then
|
|
keystr := keystr + crlf + ' PRIMARY KEY ('
|
|
else
|
|
keystr := keystr + crlf + ' ' + keylist[k]._type + ' KEY ' + maskSql(target_version, keylist[k].Name) + ' (';
|
|
keystr := keystr + implodestr(',', keylist[k].Columns) + ')';
|
|
end;
|
|
sql := sql + keystr + crlf + ')';
|
|
end; // mysql_version < 32320
|
|
|
|
if comboTables.ItemIndex = TAB_CREATE_IGNORE then
|
|
begin
|
|
Insert('/*!32312 IF NOT EXISTS*/ ', sql, Pos('TABLE', sql) + 6);
|
|
end;
|
|
|
|
createquery := createquery + sql;
|
|
|
|
// Output CREATE TABLE to file
|
|
if tofile then begin
|
|
createquery := createquery + ';' + crlf;
|
|
if dropquery <> '' then dropquery := dropquery + ';' + crlf;
|
|
wfs(f);
|
|
wfs(f);
|
|
if dropquery <> '' then wfs(f, dropquery);
|
|
wfs(f, createquery);
|
|
end
|
|
|
|
// Run CREATE TABLE on another Database
|
|
else if todb then begin
|
|
cwin.ExecUseQuery( DB2export );
|
|
if comboTables.ItemIndex = TAB_DROP_CREATE then
|
|
cwin.ExecUpdateQuery( dropquery );
|
|
cwin.ExecUpdateQuery( createquery );
|
|
cwin.ExecUseQuery( comboSelectDatabase.Text );
|
|
end
|
|
|
|
// Run CREATE TABLE on another host
|
|
else if tohost then begin
|
|
RemoteExecUseNonQuery(win2export, cwin.mysql_version, DB2Export);
|
|
if comboTables.ItemIndex = TAB_DROP_CREATE then
|
|
RemoteExecNonQuery(win2export, dropquery);
|
|
RemoteExecNonQuery(win2export, createquery);
|
|
end;
|
|
|
|
barProgress.StepIt;
|
|
end;
|
|
|
|
{***
|
|
Export data
|
|
}
|
|
if exportdata then
|
|
begin
|
|
// Set to mysql-readable char:
|
|
DecimalSeparator := '.';
|
|
columnnames := ' (';
|
|
Query := cwin.GetResults( 'SHOW FIELDS FROM ' + mainform.mask(checkListTables.Items[i]));
|
|
for k:=1 to Query.RecordCount do
|
|
begin
|
|
if k>1 then
|
|
columnnames := columnnames + ', ';
|
|
columnnames := columnnames + maskSql(target_version, Query.Fields[0].AsString);
|
|
Query.Next;
|
|
end;
|
|
columnnames := columnnames+')';
|
|
|
|
if tofile then
|
|
begin
|
|
wfs(f);
|
|
wfs(f);
|
|
wfs(f, '#');
|
|
wfs(f, '# Dumping data for table ''' + checkListTables.Items[i] + '''');
|
|
wfs(f, '#');
|
|
wfs(f);
|
|
end;
|
|
|
|
if comboData.ItemIndex = DATA_TRUNCATE_INSERT then
|
|
begin
|
|
if tofile then
|
|
begin
|
|
wfs(f, 'TRUNCATE TABLE ' + maskSql(target_version, checkListTables.Items[i]) + ';');
|
|
end
|
|
else if todb then
|
|
begin
|
|
cwin.ExecUpdateQuery('TRUNCATE TABLE ' + cwin.mask(DB2Export) + '.' + checkListTables.Items[i]);
|
|
end
|
|
else if tohost then
|
|
begin
|
|
RemoteExecNonQuery(win2export, 'TRUNCATE TABLE ' + maskSql(target_version, DB2Export) + '.' + checkListTables.Items[i]);
|
|
end;
|
|
end;
|
|
|
|
{***
|
|
Detect average row size and limit the number of rows fetched at
|
|
once if more than ~ 5 MB of data
|
|
Be sure to do this step before the table is locked!
|
|
}
|
|
RecordCount_all := MakeInt( cwin.GetVar( 'SELECT COUNT(*) FROM ' + cwin.mask(checkListTables.Items[i]) ) );
|
|
limit := cwin.GetCalculatedLimit( checkListTables.Items[i] );
|
|
|
|
if tofile then
|
|
begin
|
|
wfs(f, fixSQL( '/*!40000 ALTER TABLE '+ maskSql(target_version, checkListTables.Items[i]) +' DISABLE KEYS;*/', target_version) );
|
|
wfs(f, 'LOCK TABLES '+ maskSql(target_version, checkListTables.Items[i]) +' WRITE;' );
|
|
end
|
|
else if todb then
|
|
begin
|
|
cwin.ExecUseQuery(DB2Export);
|
|
if target_version > 40000 then
|
|
cwin.ExecUpdateQuery( 'ALTER TABLE ' + cwin.mask(checkListTables.Items[i])+' DISABLE KEYS' );
|
|
{***
|
|
@note ansgarbecker, 2007-02-18:
|
|
Normally we would have to apply a WRITE-LOCK to the target-table.
|
|
Unfortunately the server invokes a "Table xyz was not locked"-error
|
|
on the source-table if we do that:
|
|
cwin.ExecQuery( 'LOCK TABLES ' + cwin.mask(DB2Export) + '.' + cwin.mask(checkListTables.Items[i])+' WRITE' );
|
|
Even when applying a WRITE- or READ-LOCK also to the source-table,
|
|
the INSERTs seem to be not executed.
|
|
So the best solution for now seems to be to not LOCK the target-table,
|
|
running the risk that the table is edited by other concurrent users
|
|
}
|
|
cwin.ExecUseQuery(comboSelectDatabase.Text);
|
|
end
|
|
else if tohost then
|
|
begin
|
|
if target_version > 40000 then
|
|
RemoteExecNonQuery(win2export, 'ALTER TABLE ' + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]) + ' DISABLE KEYS');
|
|
RemoteExecNonQuery(win2export, 'LOCK TABLES ' + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]) + ' WRITE');
|
|
end;
|
|
|
|
offset := 0;
|
|
loopnumber := 0;
|
|
RecordNo_all := 0;
|
|
|
|
// Loop as long as (offset+limit) have not reached (recordcount)
|
|
while true do
|
|
begin
|
|
inc( loopnumber );
|
|
debug('loopnumber: '+formatnumber(loopnumber));
|
|
|
|
// Check if end of data has been reached
|
|
if ( (offset) >= RecordCount_all) or ( (limit = -1) and (loopnumber > 1) ) then
|
|
begin
|
|
break;
|
|
end;
|
|
|
|
sql_select := 'SELECT * FROM ' + cwin.mask(comboSelectDatabase.Text) + '.' + cwin.mask(checkListTables.Items[i]);
|
|
if limit > -1 then
|
|
begin
|
|
sql_select := sql_select + ' LIMIT ' + IntToStr( offset ) + ', ' + IntToStr( limit );
|
|
offset := offset + limit;
|
|
end;
|
|
|
|
// Execute SELECT
|
|
Query := cwin.GetResults( sql_select );
|
|
|
|
insertquery := '';
|
|
valuescount := 0;
|
|
j := 0;
|
|
donext := true;
|
|
RecordCount_one := Query.RecordCount;
|
|
while not Query.Eof do
|
|
begin
|
|
inc(j);
|
|
inc(RecordNo_all);
|
|
lblProgress.caption := StrProgress + ' (Record ' + FormatNumber(RecordNo_all) + ')';
|
|
if j mod 100 = 0 then
|
|
lblProgress.Repaint;
|
|
if insertquery = '' then
|
|
begin
|
|
case comboData.ItemIndex of
|
|
DATA_TRUNCATE_INSERT: insertquery := 'INSERT INTO ';
|
|
DATA_INSERT: insertquery := 'INSERT INTO ';
|
|
DATA_INSERT_IGNORE: insertquery := 'INSERT IGNORE INTO ';
|
|
DATA_REPLACE_INTO: insertquery := 'REPLACE INTO ';
|
|
end;
|
|
if tofile then
|
|
insertquery := insertquery + maskSql(target_version, checkListTables.Items[i])
|
|
else
|
|
insertquery := insertquery + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]);
|
|
insertquery := insertquery + columnnames;
|
|
insertquery := insertquery + ' VALUES' + crlf + #9;
|
|
end;
|
|
thesevalues := '(';
|
|
|
|
for k := 0 to Query.fieldcount-1 do
|
|
begin
|
|
if Query.Fields[k].IsNull then
|
|
value := 'NULL'
|
|
else
|
|
case Query.Fields[k].DataType of
|
|
ftInteger, ftSmallint, ftWord:
|
|
value := Query.Fields[k].AsString;
|
|
ftBoolean:
|
|
value := esc( Bool2Str( Query.Fields[k].AsBoolean ) );
|
|
else
|
|
value := escapeAuto( Query.Fields[k].AsString, current_characterset, target_version );
|
|
end;
|
|
thesevalues := thesevalues + value;
|
|
if k < Query.Fieldcount-1 then
|
|
thesevalues := thesevalues + ',';
|
|
end;
|
|
thesevalues := thesevalues + ')';
|
|
if extended_insert then
|
|
begin
|
|
if (valuescount > 1)
|
|
and (length(insertquery)+length(thesevalues)+2 >= max_allowed_packet)
|
|
then
|
|
begin
|
|
// Rewind one record and throw thesevalues away
|
|
donext := false;
|
|
dec(j);
|
|
delete( insertquery, length(insertquery)-3, 4 );
|
|
end
|
|
else if j = RecordCount_one then
|
|
begin
|
|
insertquery := insertquery + thesevalues;
|
|
end
|
|
else
|
|
begin
|
|
inc(valuescount);
|
|
insertquery := insertquery + thesevalues + ',' + crlf + #9;
|
|
Query.Next;
|
|
continue;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
insertquery := insertquery + thesevalues;
|
|
end;
|
|
if tofile then
|
|
wfs(f, insertquery + ';')
|
|
else if todb then
|
|
cwin.ExecUpdateQuery(insertquery)
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, insertquery);
|
|
if donext then
|
|
Query.Next;
|
|
donext := true;
|
|
insertquery := '';
|
|
end;
|
|
Query.Close;
|
|
end;
|
|
// Set back to local setting:
|
|
setLocales;
|
|
|
|
if tofile then
|
|
begin
|
|
wfs(f, 'UNLOCK TABLES;' );
|
|
wfs(f, fixSQL( '/*!40000 ALTER TABLE '+maskSql(target_version, checkListTables.Items[i])+' ENABLE KEYS;*/', target_version) );
|
|
end
|
|
else if todb then
|
|
begin
|
|
if target_version > 40000 then
|
|
cwin.ExecUpdateQuery( 'ALTER TABLE ' + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]) + ' ENABLE KEYS' );
|
|
end
|
|
else if tohost then
|
|
begin
|
|
RemoteExecNonQuery(win2export, 'UNLOCK TABLES');
|
|
if target_version > 40000 then
|
|
RemoteExecNonQuery(win2export, 'ALTER TABLE ' + maskSql(target_version, DB2Export) + '.' + maskSql(target_version, checkListTables.Items[i]) + ' ENABLE KEYS');
|
|
end;
|
|
barProgress.StepIt;
|
|
end;
|
|
end;
|
|
|
|
// Restore old value for SQL_MODE
|
|
if (tofile or tohost) and (target_version = SQL_VERSION_ANSI) then
|
|
begin
|
|
sql := '/*!40101 SET SQL_MODE=@OLD_SQL_MODE ;*/';
|
|
if tofile then
|
|
wfs(f, sql)
|
|
else if tohost then
|
|
RemoteExecNonQuery(win2export, sql );
|
|
end;
|
|
|
|
if cwin.ActualDatabase <> '' then
|
|
begin
|
|
cwin.ExecUseQuery( cwin.ActualDatabase );
|
|
end;
|
|
FINALLY
|
|
if tofile then
|
|
f.Free;
|
|
Screen.Cursor := crDefault;
|
|
END;
|
|
|
|
SaveSettings;
|
|
close;
|
|
end;
|
|
|
|
procedure TExportSQLForm.radioOtherDatabaseClick(Sender: TObject);
|
|
begin
|
|
if comboSelectDatabase.Items.Count <= 1 then begin
|
|
MessageDLG('There must be more than one database to enable this option.', mtError, [mbOK], 0);
|
|
radioFile.OnClick(self);
|
|
abort;
|
|
end;
|
|
validateRadioControls(Sender);
|
|
validateControls(Sender);
|
|
generateExampleSql;
|
|
end;
|
|
|
|
procedure TExportSQLForm.radioFileClick(Sender: TObject);
|
|
begin
|
|
validateRadioControls(Sender);
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.fillcombo_anotherdb(Sender: TObject);
|
|
begin
|
|
comboOtherDatabase.Items := comboSelectDatabase.Items;
|
|
comboOtherDatabase.Items.delete(comboSelectDatabase.ItemIndex);
|
|
if comboOtherDatabase.ItemIndex = -1 then
|
|
comboOtherDatabase.ItemIndex := 0;
|
|
end;
|
|
|
|
procedure TExportSQLForm.generateExampleSQL;
|
|
const
|
|
STR_DROP_DB = 'DROP DATABASE <db>;' + CRLF;
|
|
STR_CREATE_DB = 'CREATE DATABASE <db>;' + CRLF;
|
|
STR_CREATE_DB_IGNORE = 'CREATE DATABASE IF NOT EXISTS <db>;' + CRLF;
|
|
STR_DROP_TABLE = 'DROP TABLE <table>;' + CRLF;
|
|
STR_CREATE_TABLE = 'CREATE TABLE <table> <definition>;' + CRLF;
|
|
STR_CREATE_TABLE_IGNORE = 'CREATE TABLE IF NOT EXISTS <table> <definition>;' + CRLF;
|
|
STR_TRUNCATE_TABLE = 'TRUNCATE TABLE <table>;' + CRLF;
|
|
STR_INSERT = 'INSERT INTO <table> (<columns>) VALUES (<values>)';
|
|
STR_INSERT_IGNORE = 'INSERT IGNORE INTO <table> (<columns>) VALUES (<values>)';
|
|
STR_REPLACE_INTO = 'REPLACE INTO <table> (<columns>) VALUES (<values>)';
|
|
STR_END_INSERT_REG = ';' + CRLF + '(...)' + CRLF;
|
|
STR_END_INSERT_EXT = ', (<values>)...;' + CRLF;
|
|
var
|
|
s: string;
|
|
procedure add(str: string); overload;
|
|
begin
|
|
s := s + str;
|
|
end;
|
|
procedure add(str1: string; str2: string); overload;
|
|
begin
|
|
s := s + str1 + str2;
|
|
end;
|
|
begin
|
|
s := '';
|
|
if cbxStructure.Enabled and cbxStructure.Checked then begin
|
|
if cbxDatabase.Enabled and cbxDatabase.Checked then begin
|
|
case comboDatabase.ItemIndex of
|
|
DB_DROP_CREATE: add(STR_DROP_DB, STR_CREATE_DB);
|
|
DB_CREATE: add(STR_CREATE_DB);
|
|
DB_CREATE_IGNORE: add(STR_CREATE_DB_IGNORE);
|
|
end;
|
|
add( CRLF );
|
|
end;
|
|
if cbxTables.Enabled and cbxTables.Checked then begin
|
|
case comboTables.ItemIndex of
|
|
TAB_DROP_CREATE: add(STR_DROP_TABLE, STR_CREATE_TABLE);
|
|
TAB_CREATE: add(STR_CREATE_TABLE);
|
|
TAB_CREATE_IGNORE: add(STR_CREATE_TABLE_IGNORE);
|
|
end;
|
|
add( CRLF );
|
|
end;
|
|
end;
|
|
if cbxData.Enabled and cbxData.Checked then begin
|
|
case comboData.ItemIndex of
|
|
DATA_TRUNCATE_INSERT: add(STR_TRUNCATE_TABLE, STR_INSERT);
|
|
DATA_INSERT: add(STR_INSERT);
|
|
DATA_INSERT_IGNORE: add(STR_INSERT_IGNORE);
|
|
DATA_REPLACE_INTO: add(STR_REPLACE_INTO);
|
|
end;
|
|
if comboTargetCompat.ItemIndex > 0 then add(STR_END_INSERT_EXT)
|
|
else add(STR_END_INSERT_REG);
|
|
end;
|
|
s := TrimRight(s);
|
|
SynMemoExampleSql.Text := s;
|
|
end;
|
|
|
|
procedure TExportSQLForm.validateRadioControls(Sender: TObject);
|
|
begin
|
|
if radioFile.Checked then begin
|
|
EditFileName.Enabled := true;
|
|
EditFileName.Color := clWindow;
|
|
btnFileBrowse.Enabled := true;
|
|
EditFileName.SetFocus;
|
|
end else begin
|
|
EditFileName.Enabled := false;
|
|
EditFileName.Color := clBtnFace;
|
|
btnFileBrowse.Enabled := false;
|
|
end;
|
|
|
|
if radioOtherDatabase.Checked then begin
|
|
comboOtherDatabase.Enabled := true;
|
|
comboOtherDatabase.Color := clWindow;
|
|
if comboOtherDatabase.CanFocus then comboOtherDatabase.SetFocus;
|
|
end else begin
|
|
comboOtherDatabase.Enabled := false;
|
|
comboOtherDatabase.Color := clBtnFace;
|
|
end;
|
|
|
|
if radioOtherHost.Checked then begin
|
|
comboOtherHost.Enabled := true;
|
|
comboOtherHost.Color := clWindow;
|
|
comboOtherHostDatabase.Enabled := not (cbxStructure.Checked and cbxDatabase.Checked);
|
|
comboOtherHostDatabase.Color := clWindow;
|
|
if comboOtherHost.CanFocus then comboOtherHost.SetFocus;
|
|
end else begin
|
|
comboOtherHost.Enabled := false;
|
|
comboOtherHost.Color := clBtnFace;
|
|
comboOtherHostDatabase.Enabled := false;
|
|
comboOtherHostDatabase.Color := clBtnFace;
|
|
end;
|
|
|
|
// Disable target selection if exporting to known session.
|
|
comboTargetCompat.Enabled := radioFile.Checked;
|
|
end;
|
|
|
|
procedure TExportSQLForm.validateControls(Sender: TObject);
|
|
begin
|
|
cbxDatabase.Enabled := cbxStructure.Checked and ( radioFile.Checked or radioOtherHost.Checked );
|
|
comboDatabase.Enabled := cbxStructure.Checked and ( radioFile.Checked or radioOtherHost.Checked ) and cbxDatabase.Checked;
|
|
comboOtherHostDatabase.Enabled := not cbxDatabase.Checked;
|
|
|
|
cbxTables.Enabled := cbxStructure.Checked;
|
|
comboTables.Enabled := cbxStructure.Checked and cbxTables.Checked;
|
|
|
|
comboData.Enabled := cbxData.Checked;
|
|
|
|
// Prevent choosing export of db struct + data but no table struct.
|
|
if cbxData.Checked then begin
|
|
if Sender = cbxTables then cbxDatabase.Checked := cbxDatabase.Checked And cbxTables.Checked
|
|
else cbxTables.Checked := cbxTables.Checked or cbxDatabase.Checked;
|
|
end;
|
|
|
|
btnExport.Enabled := cbxData.Checked or
|
|
(cbxStructure.Checked and (cbxDatabase.Checked or cbxTables.Checked));
|
|
|
|
if cbxStructure.Checked and cbxDatabase.Checked and (comboDatabase.ItemIndex = DB_DROP_CREATE) then begin
|
|
// 'drop tables', 'truncate data', 'insert ignore' and 'replace into' is useless.
|
|
comboTables.ItemIndex := TAB_CREATE;
|
|
comboTables.Enabled := false;
|
|
comboData.ItemIndex := DATA_INSERT;
|
|
comboData.Enabled := false;
|
|
end;
|
|
|
|
if cbxStructure.Checked and cbxTables.Checked and (comboTables.ItemIndex = TAB_DROP_CREATE) then begin
|
|
// 'truncate data', 'insert ignore' and 'replace into' is useless.
|
|
comboData.ItemIndex := DATA_INSERT;
|
|
comboData.Enabled := false;
|
|
end;
|
|
end;
|
|
|
|
procedure TExportSQLForm.cbxStructureClick(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.cbxDataClick(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.cbxTablesClick(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
procedure TExportSQLForm.checkListTablesKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
// if exist tables and is more than one, 'cause
|
|
// if exists only one, this action is not needed
|
|
// and CTRL Key is pressed
|
|
if ((checkListTables.Count > 1) and (ssCtrl in Shift)) then
|
|
begin
|
|
case (Key) of
|
|
VK_UP: // UP Key
|
|
begin
|
|
// find the selected, starting from the second table
|
|
for i := 1 to (checkListTables.Count - 1) do
|
|
begin
|
|
if (checkListTables.Selected[i]) then
|
|
begin
|
|
// move the selected to up
|
|
checkListTables.Items.Move(i, (i - 1));
|
|
// select it again
|
|
checkListTables.Selected[i] := True;
|
|
// stop the find
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
VK_DOWN: // DOWN Key
|
|
begin
|
|
// find the selected, starting from the first table, but
|
|
// ignore the last
|
|
for i := 0 to (checkListTables.Count - 2) do
|
|
begin
|
|
if (checkListTables.Selected[i]) then
|
|
begin
|
|
// move the selected to down
|
|
checkListTables.Items.Move(i, (i + 1));
|
|
// select it again
|
|
checkListTables.Selected[i] := True;
|
|
// stop the find
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TExportSQLForm.cbxDatabaseClick(Sender: TObject);
|
|
begin
|
|
validateControls(Sender);
|
|
generateExampleSQL;
|
|
end;
|
|
|
|
|
|
procedure TExportSQLForm.radioOtherHostClick(Sender: TObject);
|
|
var
|
|
list: TWindowDataArray;
|
|
i, k: integer;
|
|
begin
|
|
// Check if all the heidisql windows are still alive.
|
|
CheckForCrashedWindows;
|
|
|
|
// Fetch list of heidisql windows.
|
|
list := GetWindowList;
|
|
|
|
// Fill list of hosts.
|
|
comboOtherHost.Items.Clear;
|
|
SetLength(appHandles, High(list));
|
|
k := 0;
|
|
for i := 0 to High(list) do with list[i] do begin
|
|
// Do not include current window.
|
|
if appHandle <> MainForm.Handle then begin
|
|
// Do not include non-connected windows.
|
|
if connected then begin
|
|
if namePostfix <> 0 then name := name + Format(' (%d)', [namePostFix]);
|
|
comboOtherHost.Items.Add(name);
|
|
appHandles[k] := appHandle;
|
|
k := k + 1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// Abort if no other windows.
|
|
if comboOtherHost.Items.Count = 0 then begin
|
|
MessageDLG('You need at least two open connection-windows to enable this option.', mtError, [mbOK], 0);
|
|
radioFile.Checked := true;
|
|
abort;
|
|
end;
|
|
|
|
// Select first host and first database.
|
|
comboOtherHost.ItemIndex := 0;
|
|
comboOtherHost.OnSelect(comboOtherHost);
|
|
comboOtherHostDatabase.ItemIndex := 0;
|
|
|
|
// De-select database structure to enable database dropdown box.
|
|
cbxDatabase.Checked := false;
|
|
|
|
validateRadioControls(Sender);
|
|
validateControls(Sender);
|
|
generateExampleSql;
|
|
end;
|
|
|
|
|
|
|
|
{***
|
|
Save settings in registry, should be called just before closing
|
|
the form, but not when Cancel was pressed.
|
|
}
|
|
procedure TExportSQLForm.SaveSettings;
|
|
var
|
|
OutputTo : Byte;
|
|
begin
|
|
with TRegistry.Create do
|
|
begin
|
|
OpenKey(REGPATH, true);
|
|
// WithUseDB, UseBackticks, CompleteInserts, WithDropTable: deprecated (currently not automagically removed)
|
|
WriteBool('ExportStructure', cbxStructure.Checked);
|
|
WriteBool('WithCreateDatabase', cbxDatabase.Checked);
|
|
WriteBool('WithCreateTable', cbxTables.Checked);
|
|
WriteBool('ExportData', cbxData.Checked);
|
|
WriteInteger('CreateDatabaseHow', comboDatabase.ItemIndex);
|
|
WriteInteger('CreateTablesHow', comboTables.ItemIndex);
|
|
WriteInteger('CreateDataHow', comboData.ItemIndex);
|
|
WriteInteger('Compatibility', comboTargetCompat.ItemIndex);
|
|
WriteString('exportfilename', EditFileName.Text);
|
|
OutputTo := OUTPUT_FILE;
|
|
if radioOtherDatabase.checked then
|
|
OutputTo := OUTPUT_DB
|
|
else if radioOtherHost.checked then
|
|
OutputTo := OUTPUT_HOST;
|
|
WriteInteger('ExportSQL_OutputTo', OutputTo );
|
|
WriteInteger('ExportSQL_WindowWidth', Width );
|
|
WriteInteger('ExportSQL_WindowHeight', Height );
|
|
CloseKey();
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|
|
|