Skip to content

Commit 6c2a100

Browse files
committed
Implement combo box for definer in routine + view + trigger editor. Fixes issue HeidiSQL#2189. Some related changes here:
- Remove ensureValidIdentifier() and its partly uncatched exceptions. Instead, disable "OK" buttons for empty table/view/proc name. - QuoteIdent and DeQuoteIdent now take the glue char instead of a "HasMultiSegments" boolean param, so they're more exact when "user@host" or "db.name" come in.
1 parent 62950fa commit 6c2a100

17 files changed

Lines changed: 233 additions & 246 deletions

source/copytable.pas

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ procedure TCopyTableForm.FormDestroy(Sender: TObject);
8888
procedure TCopyTableForm.FormShow(Sender: TObject);
8989
var
9090
Table, Filter: String;
91-
Algorithm, CheckOption, SelectCode: String;
91+
Dummy: String;
9292
DBObjects: TDBObjectList;
9393
Obj: TDBObject;
9494
Values: TStringList;
@@ -127,7 +127,7 @@ procedure TCopyTableForm.FormShow(Sender: TObject);
127127
FForeignKeys.Clear;
128128
case FDBObj.NodeType of
129129
lntTable: FDBObj.Connection.ParseTableStructure(FDBObj.CreateCode, FColumns, FKeys, FForeignKeys);
130-
lntView: FDBObj.Connection.ParseViewStructure(FDBObj.CreateCode, FDBObj.Name, FColumns, Algorithm, CheckOption, SelectCode);
130+
lntView: FDBObj.Connection.ParseViewStructure(FDBObj.CreateCode, FDBObj.Name, FColumns, Dummy, Dummy, Dummy, Dummy);
131131
else raise Exception.Create('Neither table nor view: '+FDBObj.Name);
132132
end;
133133

source/createdatabase.dfm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ object CreateDatabaseForm: TCreateDatabaseForm
6161
Anchors = [akLeft, akTop, akRight]
6262
TabOrder = 0
6363
TextHint = 'Enter database name'
64-
OnChange = editDBNameChange
64+
OnChange = Modified
6565
end
6666
object comboCharset: TComboBox
6767
Left = 88
@@ -82,7 +82,6 @@ object CreateDatabaseForm: TCreateDatabaseForm
8282
Anchors = [akRight, akBottom]
8383
Caption = 'OK'
8484
Default = True
85-
Enabled = False
8685
TabOrder = 3
8786
OnClick = btnOKClick
8887
end

source/createdatabase.pas

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ TCreateDatabaseForm = class(TForm)
2121
procedure btnOKClick(Sender: TObject);
2222
procedure comboCharsetChange(Sender: TObject);
2323
procedure Modified(Sender: TObject);
24-
procedure editDBNameChange(Sender: TObject);
2524
procedure FormClose(Sender: TObject; var Action: TCloseAction);
2625
procedure FormCreate(Sender: TObject);
2726
procedure FormShow(Sender: TObject);
@@ -172,31 +171,6 @@ procedure TCreateDatabaseForm.comboCharsetChange(Sender: TObject);
172171
end;
173172

174173

175-
{**
176-
User writes something into editDBName
177-
}
178-
procedure TCreateDatabaseForm.editDBNameChange(Sender: TObject);
179-
begin
180-
editDBName.Font.Color := clWindowText;
181-
editDBName.Color := clWindow;
182-
// Enable "OK"-Button by default
183-
btnOK.Enabled := True;
184-
try
185-
ensureValidIdentifier( editDBName.Text );
186-
except
187-
// Invalid database name
188-
if editDBName.Text <> '' then begin
189-
editDBName.Font.Color := clRed;
190-
editDBName.Color := clYellow;
191-
end;
192-
btnOK.Enabled := False;
193-
end;
194-
195-
// Invoke SQL preview
196-
Modified(Sender);
197-
end;
198-
199-
200174
{**
201175
Create the database
202176
}

source/event_editor.pas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ procedure TfrmEventEditor.Init(Obj: TDBObject);
196196
procedure TfrmEventEditor.Modification(Sender: TObject);
197197
begin
198198
Modified := True;
199-
btnSave.Enabled := Modified;
199+
btnSave.Enabled := Modified and (editName.Text <> '');
200200
btnDiscard.Enabled := Modified;
201201
CreateCodeValid := False;
202202
AlterCodeValid := False;

source/helpers.pas

Lines changed: 22 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ TOrderCol = class(TObject)
4040
TDBObjectEditor = class(TFrame)
4141
private
4242
FModified: Boolean;
43+
FDefiners: TStringList;
4344
procedure SetModified(Value: Boolean);
4445
protected
4546
public
@@ -48,6 +49,7 @@ TDBObjectEditor = class(TFrame)
4849
destructor Destroy; override;
4950
procedure Init(Obj: TDBObject); virtual;
5051
function DeInit: TModalResult;
52+
function GetDefiners: TStringList;
5153
property Modified: Boolean read FModified write SetModified;
5254
function ApplyModifications: TModalResult; virtual; abstract;
5355
end;
@@ -75,7 +77,6 @@ TSQLSentence = class(TObject)
7577
function implodestr(seperator: String; a: TStrings) :String;
7678
function Explode(Separator, Text: String) :TStringList;
7779
procedure ExplodeQuotedList(Text: String; var List: TStringList);
78-
procedure ensureValidIdentifier(name: String);
7980
function getEnumValues(str: String): String;
8081
function GetSQLSplitMarkers(const SQL: String): TSQLBatch;
8182
function SplitSQL(const SQL: String): TSQLBatch;
@@ -238,81 +239,6 @@ function Explode(Separator, Text: String): TStringList;
238239
end;
239240

240241

241-
242-
{***
243-
Check for valid identifier (table-/db-/column-name) ?
244-
245-
@param string Identifier
246-
@return boolean Name is valid?
247-
@note rosenfield, 2007-02-01:
248-
Those certain characters are standard filesystem wildcards * ?,
249-
pipe redirection characters | < >, standard path separators / \,
250-
Windows mount point identifiers :, DBMS security / container separator
251-
characters . and so on. In other words, characters that may or may
252-
not be allowed by MySQL and the underlying filesystem, but which are
253-
really, really, really stupid to use in a table name, since you'll
254-
get into trouble once trying to use the table/db in a query or move it
255-
to a different filesystem, or what not.
256-
@note ansgarbecker, 2007-02-01:
257-
Since mysql 5.1.6 those problematic characters are encoded in
258-
a hexadecimal manner if they apply to a file (table) or folder (database)
259-
But after testing that by renaming a table to a name with a dot
260-
I still get an error, so we currently should be careful also on a 5.1.6+
261-
@see http://dev.mysql.com/doc/refman/5.1/en/identifier-mapping.html
262-
}
263-
procedure ensureValidIdentifier( name: String );
264-
var
265-
i : Integer;
266-
invalidChars, invalidCharsShown : String;
267-
isToolong, hasInvalidChars : Boolean;
268-
msgStr : String;
269-
begin
270-
isToolong := false;
271-
hasInvalidChars := false;
272-
273-
// Check length
274-
if (length(name) < 1) or (length(name) > 64) then
275-
isToolong := true;
276-
277-
// Check for invalid chars
278-
invalidChars := '\/:*?"<>|.';
279-
for i:=1 to length(name) do
280-
begin
281-
if (pos( name[i], invalidChars ) > 0 ) then
282-
begin
283-
hasInvalidChars := true;
284-
break;
285-
end;
286-
end;
287-
288-
// Raise exception which explains what's wrong
289-
if isTooLong or hasInvalidChars then
290-
begin
291-
if hasInvalidChars then
292-
begin
293-
// Add space between chars for better readability
294-
invalidCharsShown := '';
295-
for i:=1 to length(invalidChars) do
296-
begin
297-
invalidCharsShown := invalidCharsShown + invalidChars[i] + ' ';
298-
end;
299-
msgStr := 'The name "%s" contains some invalid characters.'+
300-
CRLF+CRLF + 'An identifier must not contain the following characters:'+CRLF+invalidCharsShown;
301-
end
302-
else if isToolong then
303-
begin
304-
msgStr := 'The name "%s" has '+IntToStr(Length(name))
305-
+' characters and exceeds the maximum length of 64 characters.';
306-
end;
307-
308-
Raise Exception.CreateFmt(msgStr, [name]);
309-
end;
310-
311-
312-
end;
313-
314-
315-
316242
{***
317243
Get values from an enum- or set-typed column definition
318244
@@ -2347,6 +2273,26 @@ function TDBObjectEditor.DeInit: TModalResult;
23472273
end;
23482274

23492275

2276+
function TDBObjectEditor.GetDefiners: TStringList;
2277+
function q(s: String): String;
2278+
begin
2279+
Result := DBObject.Connection.QuoteIdent(s);
2280+
end;
2281+
begin
2282+
// For populating combobox items
2283+
if not Assigned(FDefiners) then begin
2284+
try
2285+
FDefiners := DBObject.Connection.GetCol('SELECT CONCAT('+q('User')+', '+esc('@')+', '+q('Host')+') FROM '+
2286+
q('mysql')+'.'+q('user')+' WHERE '+q('User')+'!='+esc('')+' ORDER BY '+q('User')+', '+q('Host'));
2287+
except on E:EDatabaseError do
2288+
FDefiners := TStringList.Create;
2289+
end;
2290+
end;
2291+
Result := FDefiners;
2292+
end;
2293+
2294+
2295+
23502296

23512297
// Following code taken from OneInst.pas, http://assarbad.net/de/stuff/!import/nico.old/
23522298
// Slightly modified to better integrate that into our code, comments translated from german.

source/loaddata.pas

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ procedure Tloaddataform.comboEncodingSelect(Sender: TObject);
220220

221221
procedure Tloaddataform.comboTableChange(Sender: TObject);
222222
var
223-
Algorithm, CheckOption, SelectCode: String;
223+
DummyStr: String;
224224
Col: TTableColumn;
225225
DBObjects: TDBObjectList;
226226
Obj: TDBObject;
@@ -235,7 +235,7 @@ procedure Tloaddataform.comboTableChange(Sender: TObject);
235235
if (Obj.Database=comboDatabase.Text) and (Obj.Name=comboTable.Text) then begin
236236
case Obj.NodeType of
237237
lntTable: Obj.Connection.ParseTableStructure(Obj.CreateCode, Columns, nil, nil);
238-
lntView: Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, Algorithm, CheckOption, SelectCode);
238+
lntView: Obj.Connection.ParseViewStructure(Obj.CreateCode, Obj.Name, Columns, DummyStr, DummyStr, DummyStr, DummyStr);
239239
end;
240240
end;
241241
end;

source/main.pas

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ TMainForm = class(TForm)
527527
procedure actPrintListExecute(Sender: TObject);
528528
procedure actCopyTableExecute(Sender: TObject);
529529
procedure ShowStatusMsg(Msg: String=''; PanelNr: Integer=6);
530-
function mask(str: String; HasMultiSegments: Boolean=False) : String;
530+
function mask(str: String; Glue: Char=#0) : String;
531531
procedure actExecuteQueryExecute(Sender: TObject);
532532
procedure actCreateDatabaseExecute(Sender: TObject);
533533
procedure actDataCancelChangesExecute(Sender: TObject);
@@ -2104,9 +2104,9 @@ procedure TMainForm.actWebbrowse(Sender: TObject);
21042104

21052105

21062106
// Escape database, table, field, index or key name.
2107-
function TMainform.mask(str: String; HasMultiSegments: Boolean=False) : String;
2107+
function TMainform.mask(str: String; Glue: Char=#0) : String;
21082108
begin
2109-
result := ActiveConnection.QuoteIdent(str, HasMultiSegments);
2109+
result := ActiveConnection.QuoteIdent(str, Glue);
21102110
end;
21112111

21122112

@@ -2935,8 +2935,8 @@ procedure TMainForm.actRunRoutinesExecute(Sender: TObject);
29352935
var
29362936
Tab: TQueryTab;
29372937
Query, ParamInput,
2938-
Returns, DataAccess, Security, Comment, Body: String;
2939-
Deterministic: Boolean;
2938+
DummyStr: String;
2939+
DummyBool: Boolean;
29402940
i: Integer;
29412941
pObj: PDBObject;
29422942
Obj: TDBObject;
@@ -2968,7 +2968,7 @@ procedure TMainForm.actRunRoutinesExecute(Sender: TObject);
29682968
lntFunction: Query := 'SELECT ';
29692969
end;
29702970
Parameters := TRoutineParamList.Create;
2971-
Obj.Connection.ParseRoutineStructure(Obj.CreateCode, Parameters, Deterministic, Returns, DataAccess, Security, Comment, Body);
2971+
Obj.Connection.ParseRoutineStructure(Obj.CreateCode, Parameters, DummyBool, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr);
29722972
Query := Query + mask(Obj.Name);
29732973
ParamInput := '';
29742974
for i:=0 to Parameters.Count-1 do begin
@@ -4664,7 +4664,7 @@ procedure TMainForm.ParameterCompletionProposalExecute(Kind: SynCompletionType;
46644664
for DbObj in DbObjects do begin
46654665
if (CompareText(DbObj.Name, Identifier)=0) and (DbObj.NodeType in [lntFunction, lntProcedure]) then begin
46664666
Params := TRoutineParamList.Create(True);
4667-
DbObj.Connection.ParseRoutineStructure(DbObj.CreateCode, Params, DummyBool, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr);
4667+
DbObj.Connection.ParseRoutineStructure(DbObj.CreateCode, Params, DummyBool, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr, DummyStr);
46684668
ItemText := '';
46694669
for i:=0 to Params.Count-1 do
46704670
ItemText := ItemText + '"' + Params[i].Name + ': ' + Params[i].Datatype + '", ';
@@ -4733,7 +4733,6 @@ procedure TMainForm.ListTablesNewText(Sender: TBaseVirtualTree; Node:
47334733

47344734
// Try to rename, on any error abort and don't rename ListItem
47354735
try
4736-
ensureValidIdentifier( NewText );
47374736
// rename table
47384737
ActiveConnection.Query('RENAME TABLE ' + mask(Obj.Name) + ' TO ' + mask(NewText));
47394738

@@ -6751,7 +6750,7 @@ function TMainForm.TreeClickHistoryPrevious(MayBeNil: Boolean=False): PVirtualNo
67516750

67526751
procedure TMainForm.ParseSelectedTableStructure;
67536752
var
6754-
Algorithm, CheckOption, SelectCode: String;
6753+
DummyStr: String;
67556754
begin
67566755
SelectedTableColumns.Clear;
67576756
SelectedTableKeys.Clear;
@@ -6762,7 +6761,7 @@ procedure TMainForm.ParseSelectedTableStructure;
67626761
lntTable:
67636762
ActiveConnection.ParseTableStructure(ActiveDbObj.CreateCode, SelectedTableColumns, SelectedTableKeys, SelectedTableForeignKeys);
67646763
lntView:
6765-
ActiveConnection.ParseViewStructure(ActiveDbObj.CreateCode, ActiveDbObj.Name, SelectedTableColumns, Algorithm, CheckOption, SelectCode);
6764+
ActiveConnection.ParseViewStructure(ActiveDbObj.CreateCode, ActiveDbObj.Name, SelectedTableColumns, DummyStr, DummyStr, DummyStr, DummyStr);
67666765
end;
67676766
except on E:EDatabaseError do
67686767
MessageDlg(E.Message, mtError, [mbOK], 0);
@@ -7310,7 +7309,7 @@ procedure TMainForm.AnyGridCreateEditor(Sender: TBaseVirtualTree; Node:
73107309
idx := ForeignKey.Columns.IndexOf(DataGrid.Header.Columns[Column].Text);
73117310
if idx > -1 then begin
73127311
// Find the first text column if available and use that for displaying in the pulldown instead of using meaningless id numbers
7313-
CreateTable := ActiveConnection.GetVar('SHOW CREATE TABLE '+Mask(ForeignKey.ReferenceTable, True), 1);
7312+
CreateTable := ActiveConnection.GetVar('SHOW CREATE TABLE '+Mask(ForeignKey.ReferenceTable, '.'), 1);
73147313
Columns := TTableColumnList.Create;
73157314
Keys := nil;
73167315
ForeignKeys := nil;
@@ -7326,7 +7325,7 @@ procedure TMainForm.AnyGridCreateEditor(Sender: TBaseVirtualTree; Node:
73267325
KeyCol := Mask(ForeignKey.ForeignColumns[idx]);
73277326
SQL := 'SELECT '+KeyCol;
73287327
if TextCol <> '' then SQL := SQL + ', LEFT(' + Mask(TextCol) + ', 256)';
7329-
SQL := SQL + ' FROM '+Mask(ForeignKey.ReferenceTable, True)+' GROUP BY '+KeyCol+' ORDER BY ';
7328+
SQL := SQL + ' FROM '+Mask(ForeignKey.ReferenceTable, '.')+' GROUP BY '+KeyCol+' ORDER BY ';
73307329
if TextCol <> '' then SQL := SQL + Mask(TextCol) else SQL := SQL + KeyCol;
73317330
SQL := SQL + ' LIMIT 1000';
73327331

0 commit comments

Comments
 (0)