Fix bug #693 Import CSV file: LOAD DATA statement breaks data if the CSV file has a different charset than the current DB. Implements the discussed pulldown on the first page of the dialog, below the file input. Defaults to UTF-8 selection.

This commit is contained in:
Ansgar Becker
2008-09-02 23:11:05 +00:00
parent 48aca3d928
commit cc901ae8d3
2 changed files with 88 additions and 20 deletions

View File

@ -60,18 +60,18 @@ object loaddataform: Tloaddataform
415 415
282) 282)
object grpFilename: TGroupBox object grpFilename: TGroupBox
Left = 10 Left = 5
Top = 10 Top = 2
Width = 394 Width = 403
Height = 63 Height = 90
Anchors = [akLeft, akTop, akRight] Anchors = [akLeft, akTop, akRight]
Caption = 'Filename' Caption = 'File'
TabOrder = 0 TabOrder = 0
DesignSize = ( DesignSize = (
394 403
63) 90)
object btnOpenFile: TPngSpeedButton object btnOpenFile: TPngSpeedButton
Left = 353 Left = 362
Top = 24 Top = 24
Width = 22 Width = 22
Height = 22 Height = 22
@ -79,10 +79,26 @@ object loaddataform: Tloaddataform
Flat = True Flat = True
OnClick = btnOpenFileClick OnClick = btnOpenFileClick
end end
object lblFilename: TLabel
Left = 10
Top = 27
Width = 46
Height = 13
Caption = 'Filename:'
FocusControl = editFilename
end
object lblCharset: TLabel
Left = 10
Top = 54
Width = 70
Height = 13
Caption = '&Character set:'
FocusControl = comboCharset
end
object editFilename: TEdit object editFilename: TEdit
Left = 16 Left = 104
Top = 24 Top = 24
Width = 331 Width = 252
Height = 21 Height = 21
Anchors = [akLeft, akTop, akRight] Anchors = [akLeft, akTop, akRight]
TabOrder = 0 TabOrder = 0
@ -90,11 +106,20 @@ object loaddataform: Tloaddataform
OnChange = editFilenameChange OnChange = editFilenameChange
OnDblClick = btnOpenFileClick OnDblClick = btnOpenFileClick
end end
object comboCharset: TComboBox
Left = 104
Top = 51
Width = 252
Height = 21
Style = csDropDownList
ItemHeight = 13
TabOrder = 1
end
end end
object grpFields: TGroupBox object grpFields: TGroupBox
Left = 10 Left = 5
Top = 78 Top = 93
Width = 394 Width = 403
Height = 109 Height = 109
Anchors = [akLeft, akTop, akRight] Anchors = [akLeft, akTop, akRight]
Caption = 'Fields' Caption = 'Fields'
@ -153,9 +178,9 @@ object loaddataform: Tloaddataform
end end
end end
object grpLines: TGroupBox object grpLines: TGroupBox
Left = 10 Left = 5
Top = 193 Top = 202
Width = 394 Width = 403
Height = 74 Height = 74
Anchors = [akLeft, akTop, akRight] Anchors = [akLeft, akTop, akRight]
Caption = 'Lines' Caption = 'Lines'

View File

@ -11,7 +11,7 @@ interface
uses uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, comctrls, Buttons, CheckLst, Registry, PngSpeedButton, StdCtrls, ExtCtrls, comctrls, Buttons, CheckLst, Registry, PngSpeedButton,
WideStrings, TntCheckLst, TntStdCtrls; WideStrings, TntCheckLst, TntStdCtrls, db, SynRegExpr;
type type
Tloaddataform = class(TForm) Tloaddataform = class(TForm)
@ -52,6 +52,9 @@ type
editLineTerminator: TEdit; editLineTerminator: TEdit;
lblLineTerminator: TLabel; lblLineTerminator: TLabel;
lblIgnoreLines: TLabel; lblIgnoreLines: TLabel;
lblFilename: TLabel;
comboCharset: TComboBox;
lblCharset: TLabel;
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure editFilenameChange(Sender: TObject); procedure editFilenameChange(Sender: TObject);
procedure FormShow(Sender: TObject); procedure FormShow(Sender: TObject);
@ -65,6 +68,7 @@ type
procedure btnColDownClick(Sender: TObject); procedure btnColDownClick(Sender: TObject);
private private
{ Private declarations } { Private declarations }
dsCharsets: TDataset;
public public
{ Public declarations } { Public declarations }
end; end;
@ -73,7 +77,7 @@ type
implementation implementation
uses Main, Childwin, helpers, Db; uses Main, Childwin, helpers;
{$R *.DFM} {$R *.DFM}
@ -133,9 +137,11 @@ end;
procedure Tloaddataform.comboDatabaseChange(Sender: TObject); procedure Tloaddataform.comboDatabaseChange(Sender: TObject);
var var
count: Integer; count, i, selCharsetIndex: Integer;
ds: TDataset; ds: TDataset;
seldb, seltable: String; seldb, seltable, dbcreate: WideString;
rx: TRegExpr;
DefCharset: String;
begin begin
// read tables from db // read tables from db
comboTable.Items.Clear; comboTable.Items.Clear;
@ -153,6 +159,38 @@ begin
comboTable.ItemIndex := 0; comboTable.ItemIndex := 0;
comboTableChange(self); comboTableChange(self);
selCharsetIndex := comboCharset.ItemIndex;
comboCharset.Enabled := False;
comboCharset.Clear;
try
if dsCharsets = nil then
dsCharsets := Mainform.Childwin.GetResults('SHOW CHARSET');
comboCharset.Enabled := True;
// Detect db charset
DefCharset := 'Let server/database decide';
dbcreate := Mainform.Childwin.GetVar('SHOW CREATE DATABASE '+Mainform.mask(comboDatabase.Text), 1);
rx := TRegExpr.Create;
rx.ModifierG := True;
rx.Expression := 'CHARACTER SET (\w+)';
if rx.Exec(dbcreate) then
DefCharset := DefCharset + ' ('+rx.Match[1]+')';
comboCharset.Items.Add(DefCharset);
dsCharsets.First;
for i:=1 to dsCharsets.RecordCount do begin
comboCharset.Items.Add(dsCharsets.Fields[1].AsWideString + ' ('+dsCharsets.Fields[0].AsWideString+')');
if dsCharsets.Fields[0].AsWideString = 'utf8' then begin
comboCharset.Items[i] := comboCharset.Items[i] + ' - '+APPNAME+' output';
if selCharsetIndex = -1 then
selCharsetIndex := i;
end;
dsCharsets.Next;
end;
comboCharset.ItemIndex := selCharsetIndex;
except
// Ignore it when the above statements don't work on pre 4.1 servers.
// In that case, the combobox is disabled and we load the file without specifying charset.
end;
end; end;
@ -230,6 +268,11 @@ begin
query := query + 'IGNORE '; query := query + 'IGNORE ';
query := query + 'INTO TABLE ' + Mainform.Mask(comboDatabase.Text) + '.' + Mainform.Mask(comboTable.Text) + ' '; query := query + 'INTO TABLE ' + Mainform.Mask(comboDatabase.Text) + '.' + Mainform.Mask(comboTable.Text) + ' ';
if comboCharset.ItemIndex > 0 then begin
dsCharsets.RecNo := comboCharset.ItemIndex;
query := query + 'CHARACTER SET '+dsCharsets.Fields[0].AsString+' ';
end;
// Fields: // Fields:
if (editFieldTerminator.Text <> '') or (editFieldEncloser.Text <> '') or (editFieldEscaper.Text <> '') then if (editFieldTerminator.Text <> '') or (editFieldEncloser.Text <> '') or (editFieldEscaper.Text <> '') then
query := query + 'FIELDS '; query := query + 'FIELDS ';