mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-26 11:17:57 +08:00
Implement query helpers: Columns, SQL functions and SQL keywords, presented in a listbox where they can be doubleclicked or dragged to insert into query-memo.
As a benefit, function.txt is read into 3 stringlists at startup now: Names, Declarations and Descriptions. Used in SynCompletionProposal and to fill the above mentioned helpers-list. Also fixes a minor issue in SynMemoQueryDragOver using an unset "Accept" var.
This commit is contained in:
@ -908,7 +908,7 @@ object MDIChild: TMDIChild
|
|||||||
object SynMemoQuery: TSynMemo
|
object SynMemoQuery: TSynMemo
|
||||||
Left = 0
|
Left = 0
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 496
|
Width = 336
|
||||||
Height = 96
|
Height = 96
|
||||||
SingleLineMode = False
|
SingleLineMode = False
|
||||||
Align = alClient
|
Align = alClient
|
||||||
@ -959,6 +959,48 @@ object MDIChild: TMDIChild
|
|||||||
end>
|
end>
|
||||||
AddedKeystrokes = <>
|
AddedKeystrokes = <>
|
||||||
end
|
end
|
||||||
|
object pnlQueryHelpers: TPanel
|
||||||
|
Left = 336
|
||||||
|
Top = 0
|
||||||
|
Width = 160
|
||||||
|
Height = 96
|
||||||
|
Align = alRight
|
||||||
|
BevelOuter = bvNone
|
||||||
|
TabOrder = 1
|
||||||
|
object tabsetQueryHelpers: TTabSet
|
||||||
|
Left = 0
|
||||||
|
Top = 72
|
||||||
|
Width = 160
|
||||||
|
Height = 24
|
||||||
|
Align = alBottom
|
||||||
|
AutoScroll = False
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'Tahoma'
|
||||||
|
Font.Style = []
|
||||||
|
ParentShowHint = False
|
||||||
|
ShowHint = False
|
||||||
|
Style = tsModernTabs
|
||||||
|
Tabs.Strings = (
|
||||||
|
'Cols'
|
||||||
|
'SQL fn'
|
||||||
|
'SQL kw')
|
||||||
|
TabIndex = 0
|
||||||
|
OnChange = tabsetQueryHelpersChange
|
||||||
|
end
|
||||||
|
object lboxQueryHelpers: TListBox
|
||||||
|
Left = 0
|
||||||
|
Top = 0
|
||||||
|
Width = 160
|
||||||
|
Height = 72
|
||||||
|
Align = alClient
|
||||||
|
DragMode = dmAutomatic
|
||||||
|
ItemHeight = 13
|
||||||
|
TabOrder = 1
|
||||||
|
OnDblClick = lboxQueryHelpersDblClick
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
object gridQuery: TSMDBGrid
|
object gridQuery: TSMDBGrid
|
||||||
Left = 0
|
Left = 0
|
||||||
|
@ -21,7 +21,7 @@ uses
|
|||||||
ZAbstractRODataset, ZConnection,
|
ZAbstractRODataset, ZConnection,
|
||||||
ZSqlMonitor, ZPlainMySqlDriver, EDBImage, ZAbstractDataset, ZDbcLogging,
|
ZSqlMonitor, ZPlainMySqlDriver, EDBImage, ZAbstractDataset, ZDbcLogging,
|
||||||
SynCompletionProposal, HeidiComp, SynEditMiscClasses, MysqlQuery,
|
SynCompletionProposal, HeidiComp, SynEditMiscClasses, MysqlQuery,
|
||||||
MysqlQueryThread, queryprogress, communication, MysqlConn, smdbgrid;
|
MysqlQueryThread, queryprogress, communication, MysqlConn, smdbgrid, Tabs;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -267,6 +267,12 @@ type
|
|||||||
btnUnsafeEdit: TToolButton;
|
btnUnsafeEdit: TToolButton;
|
||||||
btnColumnSelection: TSpeedButton;
|
btnColumnSelection: TSpeedButton;
|
||||||
btnAltTerminator: TToolButton;
|
btnAltTerminator: TToolButton;
|
||||||
|
pnlQueryHelpers: TPanel;
|
||||||
|
tabsetQueryHelpers: TTabSet;
|
||||||
|
lboxQueryHelpers: TListBox;
|
||||||
|
procedure lboxQueryHelpersDblClick(Sender: TObject);
|
||||||
|
procedure tabsetQueryHelpersChange(Sender: TObject; NewTab: Integer;
|
||||||
|
var AllowChange: Boolean);
|
||||||
procedure btnTableViewDataClick(Sender: TObject);
|
procedure btnTableViewDataClick(Sender: TObject);
|
||||||
procedure btnDbViewDataClick(Sender: TObject);
|
procedure btnDbViewDataClick(Sender: TObject);
|
||||||
procedure btnColumnSelectionClick(Sender: TObject);
|
procedure btnColumnSelectionClick(Sender: TObject);
|
||||||
@ -1730,6 +1736,8 @@ end;
|
|||||||
Occurs when active tab has changed.
|
Occurs when active tab has changed.
|
||||||
}
|
}
|
||||||
procedure TMDIChild.pcChange(Sender: TObject);
|
procedure TMDIChild.pcChange(Sender: TObject);
|
||||||
|
var
|
||||||
|
dummy : Boolean;
|
||||||
begin
|
begin
|
||||||
tabFilter.tabVisible := (PageControlMain.ActivePage = tabData);
|
tabFilter.tabVisible := (PageControlMain.ActivePage = tabData);
|
||||||
|
|
||||||
@ -1739,10 +1747,14 @@ begin
|
|||||||
if (PageControlMain.ActivePage = tabData) and (not dataselected) then
|
if (PageControlMain.ActivePage = tabData) and (not dataselected) then
|
||||||
viewdata(self);
|
viewdata(self);
|
||||||
if PageControlMain.ActivePage = tabQuery then
|
if PageControlMain.ActivePage = tabQuery then
|
||||||
|
begin
|
||||||
if ActualDatabase <> '' then
|
if ActualDatabase <> '' then
|
||||||
pnlQueryTop.Caption := 'SQL-Query on Database ' + ActualDatabase + ':'
|
pnlQueryTop.Caption := 'SQL-Query on Database ' + ActualDatabase + ':'
|
||||||
else
|
else
|
||||||
pnlQueryTop.Caption := 'SQL-Query on Host ' + FConn.MysqlParams.Host + ':';
|
pnlQueryTop.Caption := 'SQL-Query on Host ' + FConn.MysqlParams.Host + ':';
|
||||||
|
// Manually invoke OnChange event of tabset to fill helper list with data
|
||||||
|
tabsetQueryHelpers.OnChange( Sender, tabsetQueryHelpers.TabIndex, dummy);
|
||||||
|
end;
|
||||||
|
|
||||||
// Move focus to relevant controls in order for them to receive keyboard events.
|
// Move focus to relevant controls in order for them to receive keyboard events.
|
||||||
if PageControlMain.ActivePage = tabDatabase then ListTables.SetFocus;
|
if PageControlMain.ActivePage = tabDatabase then ListTables.SetFocus;
|
||||||
@ -2905,8 +2917,6 @@ procedure TMDIChild.SynCompletionProposal1Execute(Kind: TSynCompletionType;
|
|||||||
var CanExecute: Boolean);
|
var CanExecute: Boolean);
|
||||||
var
|
var
|
||||||
i,j,c,t : Integer;
|
i,j,c,t : Integer;
|
||||||
functionname : String;
|
|
||||||
functiondecl : String;
|
|
||||||
tn, child : TTreeNode;
|
tn, child : TTreeNode;
|
||||||
sql, tmpsql, kw : String;
|
sql, tmpsql, kw : String;
|
||||||
keywords, tables : TStringList;
|
keywords, tables : TStringList;
|
||||||
@ -3069,15 +3079,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Add functions
|
// Add functions
|
||||||
for i := 0 to MainForm.sqlfunctionlist.Count - 1 do
|
for i := 0 to MainForm.SQLFunctionNames.Count - 1 do
|
||||||
begin
|
begin
|
||||||
functionname := Copy(MainForm.sqlfunctionlist[i], 0, Pos('(', MainForm.sqlfunctionlist[i])-1);
|
SynCompletionProposal1.InsertList.Add( MainForm.SQLFunctionNames[i] + MainForm.SQLFunctionDeclarations[i] );
|
||||||
if Pos( '|', MainForm.sqlfunctionlist[i] ) > 0 then
|
SynCompletionProposal1.ItemList.Add( '\hspace{2}\color{'+ColorToString(SynSQLSyn1.FunctionAttri.Foreground)+'}function\color{clWindowText}\column{}' + MainForm.SQLFunctionNames[i] + '\style{-B}' + MainForm.SQLFunctionDeclarations[i] );
|
||||||
functiondecl := Copy(MainForm.sqlfunctionlist[i], Length(functionname)+1, Pos( '|', MainForm.sqlfunctionlist[i] )-Length(functionname)-1)
|
|
||||||
else
|
|
||||||
functiondecl := Copy(MainForm.sqlfunctionlist[i], Length(functionname)+1, Length(MainForm.sqlfunctionlist[i]) );
|
|
||||||
SynCompletionProposal1.InsertList.Add( functionname + functiondecl );
|
|
||||||
SynCompletionProposal1.ItemList.Add( '\hspace{2}\color{'+ColorToString(SynSQLSyn1.FunctionAttri.Foreground)+'}function\color{clWindowText}\column{}' + functionname + '\style{-B}' + functiondecl );
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Add keywords
|
// Add keywords
|
||||||
@ -4099,10 +4104,13 @@ end;
|
|||||||
|
|
||||||
procedure TMDIChild.SynMemoQueryDragOver(Sender, Source: TObject; X,
|
procedure TMDIChild.SynMemoQueryDragOver(Sender, Source: TObject; X,
|
||||||
Y: Integer; State: TDragState; var Accept: Boolean);
|
Y: Integer; State: TDragState; var Accept: Boolean);
|
||||||
|
var
|
||||||
|
src : TControl;
|
||||||
begin
|
begin
|
||||||
// dragging an object over the query-memo
|
// dragging an object over the query-memo
|
||||||
if (Source as TControl).Parent = DBTree then
|
src := Source as TControl;
|
||||||
accept := true;
|
// Accepting drag's from DBTree and QueryHelpers
|
||||||
|
Accept := (src = DBTree) or (src = lboxQueryHelpers);
|
||||||
// set x-position of cursor
|
// set x-position of cursor
|
||||||
SynMemoQuery.CaretX := (x - SynMemoQuery.Gutter.Width) div SynMemoQuery.CharWidth - 1 + SynMemoQuery.LeftChar;
|
SynMemoQuery.CaretX := (x - SynMemoQuery.Gutter.Width) div SynMemoQuery.CharWidth - 1 + SynMemoQuery.LeftChar;
|
||||||
// set y-position of cursor
|
// set y-position of cursor
|
||||||
@ -4114,10 +4122,24 @@ end;
|
|||||||
|
|
||||||
procedure TMDIChild.SynMemoQueryDragDrop(Sender, Source: TObject; X,
|
procedure TMDIChild.SynMemoQueryDragDrop(Sender, Source: TObject; X,
|
||||||
Y: Integer);
|
Y: Integer);
|
||||||
|
var
|
||||||
|
src : TControl;
|
||||||
|
Text : String;
|
||||||
begin
|
begin
|
||||||
// dropping a TTreeNode into the query-memo
|
// dropping a TTreeNode into the query-memo
|
||||||
SynMemoQuery.UndoList.AddGroupBreak;
|
SynMemoQuery.UndoList.AddGroupBreak;
|
||||||
SynMemoQuery.SelText := DBTree.Selected.Text;
|
src := Source as TControl;
|
||||||
|
// Check for allowed controls as source has already
|
||||||
|
// been performed in OnDragOver. So, only do typecasting here.
|
||||||
|
if src is TTreeView then
|
||||||
|
begin
|
||||||
|
Text := (src as TTreeView).Selected.Text;
|
||||||
|
end
|
||||||
|
else if src is TListBox then
|
||||||
|
begin
|
||||||
|
Text := (src as TListBox).Items[(src as TListBox).ItemIndex];
|
||||||
|
end;
|
||||||
|
SynMemoQuery.SelText := Text;
|
||||||
SynMemoQuery.UndoList.AddGroupBreak;
|
SynMemoQuery.UndoList.AddGroupBreak;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5320,6 +5342,68 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{**
|
||||||
|
Tabset right to query-memo was clicked
|
||||||
|
}
|
||||||
|
procedure TMDIChild.tabsetQueryHelpersChange(Sender: TObject; NewTab: Integer;
|
||||||
|
var AllowChange: Boolean);
|
||||||
|
var
|
||||||
|
i : Integer;
|
||||||
|
begin
|
||||||
|
// Leaving early if method was invoked manually without changing
|
||||||
|
// the tabIndex while listbox is already filled
|
||||||
|
if (NewTab = tabsetQueryHelpers.TabIndex) and (lboxQueryHelpers.Items.Count > 0) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
lboxQueryHelpers.Items.BeginUpdate;
|
||||||
|
lboxQueryHelpers.Items.Clear;
|
||||||
|
// By default sorted alpabetically
|
||||||
|
lboxQueryHelpers.Sorted := True;
|
||||||
|
|
||||||
|
case NewTab of
|
||||||
|
0: // Cols
|
||||||
|
begin
|
||||||
|
// Keep native order of columns
|
||||||
|
lboxQueryHelpers.Sorted := False;
|
||||||
|
for i := 0 to ListColumns.Items.Count - 1 do
|
||||||
|
begin
|
||||||
|
lboxQueryHelpers.Items.Add(ListColumns.Items[i].Caption);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
1: // SQL functions
|
||||||
|
begin
|
||||||
|
for i := 0 to Mainform.SQLFunctionNames.Count - 1 do
|
||||||
|
begin
|
||||||
|
lboxQueryHelpers.Items.Add( Mainform.SQLFunctionNames[i] + Mainform.SQLFunctionDeclarations[i] );
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
2: // SQL keywords
|
||||||
|
begin
|
||||||
|
lboxQueryHelpers.Items := MYSQL_KEYWORDS;
|
||||||
|
lboxQueryHelpers.Sorted := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
lboxQueryHelpers.Items.EndUpdate;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{**
|
||||||
|
Insert string from listbox with query helpers into SQL
|
||||||
|
memo at doubleclick
|
||||||
|
}
|
||||||
|
procedure TMDIChild.lboxQueryHelpersDblClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
SynMemoQuery.SelText := lboxQueryHelpers.Items[lboxQueryHelpers.ItemIndex];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,7 +229,9 @@ type
|
|||||||
NativeFieldTypes : Boolean;
|
NativeFieldTypes : Boolean;
|
||||||
LanguageOffset : Integer;
|
LanguageOffset : Integer;
|
||||||
DataNullBackground : TColor;
|
DataNullBackground : TColor;
|
||||||
sqlfunctionlist : TStringList;
|
SQLFunctionNames,
|
||||||
|
SQLFunctionDeclarations,
|
||||||
|
SQLFunctionDescriptions : TStringList;
|
||||||
function GetRegValue( valueName: String; defaultValue: Integer; key: String = '' ) : Integer; Overload;
|
function GetRegValue( valueName: String; defaultValue: Integer; key: String = '' ) : Integer; Overload;
|
||||||
function GetRegValue( valueName: String; defaultValue: Boolean; key: String = '' ) : Boolean; Overload;
|
function GetRegValue( valueName: String; defaultValue: Boolean; key: String = '' ) : Boolean; Overload;
|
||||||
procedure SaveRegValue( valueName: String; value: Integer; key: String = '' ); Overload;
|
procedure SaveRegValue( valueName: String; value: Integer; key: String = '' ); Overload;
|
||||||
@ -432,7 +434,10 @@ var
|
|||||||
ws : String;
|
ws : String;
|
||||||
mi : TMenuItem;
|
mi : TMenuItem;
|
||||||
f : TextFile;
|
f : TextFile;
|
||||||
functionname, functionhint : String;
|
FunctionLine,
|
||||||
|
FunctionName,
|
||||||
|
FunctionDeclaration,
|
||||||
|
FunctionDescription : String;
|
||||||
i, pipeposition : Integer;
|
i, pipeposition : Integer;
|
||||||
begin
|
begin
|
||||||
caption := APPNAME;
|
caption := APPNAME;
|
||||||
@ -499,28 +504,40 @@ begin
|
|||||||
AssignFile(f, ExtractFilePath(paramstr(0)) + 'function.txt');
|
AssignFile(f, ExtractFilePath(paramstr(0)) + 'function.txt');
|
||||||
Reset(f);
|
Reset(f);
|
||||||
i := 1;
|
i := 1;
|
||||||
|
SQLFunctionNames := TStringList.Create;
|
||||||
|
SQLFunctionDeclarations := TStringList.Create;
|
||||||
|
SQLFunctionDescriptions := TStringList.Create;
|
||||||
|
|
||||||
while not eof(f) do
|
while not eof(f) do
|
||||||
begin
|
begin
|
||||||
functionname := '';
|
FunctionName := '';
|
||||||
Readln(f, functionname);
|
FunctionDeclaration := '';
|
||||||
pipeposition := pos('|', functionname);
|
FunctionDescription := '';
|
||||||
if pipeposition > 0 then // read hint
|
Readln(f, FunctionLine);
|
||||||
begin
|
|
||||||
if sqlfunctionlist = nil then
|
if (length(FunctionLine) > 0) and (FunctionLine[1] <> '#') then
|
||||||
sqlfunctionlist := TStringList.Create;
|
|
||||||
sqlfunctionlist.Add( trim(functionname) );
|
|
||||||
functionhint := copy(functionname, 0, pipeposition-1) + ' - ' + copy(functionname, pipeposition+1, length(functionname)-1);
|
|
||||||
functionname := copy(functionname, 0, pos('(', functionname)-1);
|
|
||||||
end else
|
|
||||||
functionhint := '';
|
|
||||||
if (functionname[1] <> '#') and (length(trim(functionname)) > 0) then
|
|
||||||
begin
|
begin
|
||||||
|
FunctionName := FunctionLine;
|
||||||
|
if pos('(', FunctionName) > 0 then
|
||||||
|
FunctionName := copy(FunctionName, 0, pos('(', FunctionName)-1);
|
||||||
|
FunctionName := trim(FunctionName);
|
||||||
|
|
||||||
|
FunctionDeclaration := Copy(FunctionLine, 0, Pos( ')', FunctionLine ) );
|
||||||
|
FunctionDeclaration := Copy(FunctionDeclaration, Pos( '(', FunctionDeclaration ), Length(FunctionDeclaration) );
|
||||||
|
|
||||||
|
pipeposition := pos('|', FunctionLine);
|
||||||
|
if pipeposition > 0 then // read hint
|
||||||
|
begin
|
||||||
|
FunctionDescription := copy(FunctionLine, 0, pipeposition-1) + ' - ' + copy(FunctionLine, pipeposition+1, length(FunctionLine)-1);
|
||||||
|
FunctionDescription := trim(FunctionDescription);
|
||||||
|
end;
|
||||||
|
|
||||||
mi := TMenuItem.Create(self);
|
mi := TMenuItem.Create(self);
|
||||||
mi.Caption := trim(functionname);
|
mi.Caption := FunctionName;
|
||||||
mi.Hint := trim(functionhint);
|
mi.Hint := FunctionDescription;
|
||||||
mi.OnClick := insertFunction;
|
mi.OnClick := insertFunction;
|
||||||
if functionname[1] <> ' ' then // build submenu
|
|
||||||
|
if FunctionLine[1] <> ' ' then // build submenu
|
||||||
begin
|
begin
|
||||||
SQLfunctions.Items.add(mi);
|
SQLfunctions.Items.add(mi);
|
||||||
inc(i);
|
inc(i);
|
||||||
@ -528,6 +545,9 @@ begin
|
|||||||
begin
|
begin
|
||||||
SQLfunctions.Items[i+11].OnClick := nil; // deactivate parent Menuitem
|
SQLfunctions.Items[i+11].OnClick := nil; // deactivate parent Menuitem
|
||||||
SQLfunctions.Items[i+11].Add(mi);
|
SQLfunctions.Items[i+11].Add(mi);
|
||||||
|
SQLFunctionNames.Add(FunctionName);
|
||||||
|
SQLFunctionDeclarations.Add(FunctionDeclaration);
|
||||||
|
SQLFunctionDescriptions.Add(FunctionDescription);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user