diff --git a/components/heidisql/include/const.inc b/components/heidisql/include/const.inc index 81139f0b..b3928b11 100644 --- a/components/heidisql/include/const.inc +++ b/components/heidisql/include/const.inc @@ -106,10 +106,6 @@ const REGNAME_SQLHELPWINHEIGHT = 'SQLHelp_WindowHeight'; REGNAME_SQLHELPPLWIDTH = 'SQLHelp_PnlLeftWidth'; REGNAME_SQLHELPPRHEIGHT = 'SQLHelp_PnlRightTopHeight'; - REGNAME_PROCEDITOR_WIDTH = 'ProcedureEditorWidth'; - REGNAME_PROCEDITOR_HEIGHT = 'ProcedureEditorHeight'; - REGNAME_TABLEEDITOR_WIDTH = 'TableEditorWidth'; - REGNAME_TABLEEDITOR_HEIGHT = 'TableEditorHeight'; REGNAME_TABLEEDITOR_TABSHEIGHT = 'TableEditorTabsHeight'; REGNAME_HOST = 'Host'; DEFAULT_HOST = '127.0.0.1'; @@ -164,10 +160,6 @@ const REGNAME_LAST_UPDATECHECK = 'UpdatecheckLastrun'; REGNAME_MAINTWINWIDTH = 'Maintenance_WindowWidth'; REGNAME_MAINTWINHEIGHT = 'Maintenance_WindowHeight'; - REGNAME_VIEWWINWIDTH = 'View_WindowWidth'; - REGNAME_VIEWWINHEIGHT = 'View_WindowHeight'; - REGNAME_CRTABLEWINWIDTH = 'CreateTable_WindowWidth'; - REGNAME_CRTABLEWINHEIGHT = 'CreateTable_WindowHeight'; REGNAME_USERMNGR_WINWIDTH = 'Usermanager_WindowWidth'; REGNAME_USERMNGR_WINHEIGHT = 'Usermanager_WindowHeight'; REGNAME_SELECTDBO_WINWIDTH = 'SelectDBO_WindowWidth'; @@ -262,16 +254,6 @@ const TXT_ASC = 'ASC'; // Used for caption of "Direction"-button TXT_DESC = 'DESC'; // dito - // Node types of Virtual Tree nodes - NODETYPE_DEFAULT = 0; - NODETYPE_DB = 1; - NODETYPE_TABLE = 2; - NODETYPE_CRASHED_TABLE = 3; - NODETYPE_VIEW = 4; - NODETYPE_FUNCTION = 5; - NODETYPE_PROCEDURE = 6; - NODETYPE_COLUMN = 7; - // Data grid: How many bytes to fetch from data fields that are potentially large. GRIDMAXDATA: Integer = 256; diff --git a/source/exportsql.pas b/source/exportsql.pas index cfdfef93..14ce04bb 100644 --- a/source/exportsql.pas +++ b/source/exportsql.pas @@ -349,7 +349,7 @@ begin checkListTables.Items.Clear; ds := Mainform.FetchDbTableList(comboSelectDatabase.Text); while not ds.Eof do begin - if GetDBObjectType(ds.Fields) = NODETYPE_TABLE then + if GetDBObjectType(ds.Fields) = lntTable then checkListTables.Items.Add(ds.FieldByName(DBO_NAME).AsWideString); ds.Next; end; diff --git a/source/helpers.pas b/source/helpers.pas index 33f6f7e0..f0f7c538 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -15,11 +15,17 @@ uses Classes, SysUtils, Graphics, db, clipbrd, dialogs, type + TListNodeType = (lntNone, lntDb, lntTable, lntCrashedTable, lntView, lntFunction, lntProcedure, lntColumn); + TListNode = record + Text: WideString; + NodeType: TListNodeType; + end; + // Define a record which can hold everything we need for one row / node in a VirtualStringTree TVTreeData = record Captions: TWideStringList; ImageIndex: Integer; - NodeType: Byte; + NodeType: TListNodeType; end; PVTreedata = ^TVTreeData; @@ -160,11 +166,11 @@ type function FormatByteNumber( Bytes: String; Decimals: Byte = 1 ): String; Overload; function FormatTimeNumber( Seconds: Cardinal ): String; function TColorToHex( Color : TColor ): string; - function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: Integer = NODETYPE_DEFAULT ): TWideStringList; + function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList; procedure SetVTSelection( VT: TVirtualStringTree; Selected: TWideStringList ); function Pos2(const Needle, HayStack: string; const StartPos: Integer) : Integer; function GetTempDir: String; - function GetDBObjectType( TableStatus: TFields ): Byte; + function GetDBObjectType( TableStatus: TFields ): TListNodeType; procedure SetWindowSizeGrip(hWnd: HWND; Enable: boolean); procedure SaveUnicodeFile(Filename: String; Text: WideString); function CreateUnicodeFileStream(Filename: String): TFileStream; @@ -2217,7 +2223,7 @@ end; Return a TStringList with captions from all selected nodes in a VirtualTree Especially helpful when toMultiSelect is True } -function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: Integer = NODETYPE_DEFAULT ): TWideStringList; +function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList; var SelectedNodes : TNodeArray; NodeData: PVTreeData; @@ -2232,7 +2238,7 @@ begin for i := 0 to Length(SelectedNodes) - 1 do begin NodeData := VT.GetNodeData( SelectedNodes[i] ); - if (OnlyNodeType = NODETYPE_DEFAULT) // Add all nodes, regardless of their types + if (OnlyNodeType = lntNone) // Add all nodes, regardless of their types or (NodeData.NodeType = OnlyNodeType) then // Node in loop is of specified type Result.Add( NodeData.Captions[Column] ); end; @@ -2241,7 +2247,7 @@ begin // Fetch all nodes a := Mainform.GetVTreeDataArray( VT )^; for i := 0 to High(a) do begin - if (OnlyNodeType = NODETYPE_DEFAULT) + if (OnlyNodeType = lntNone) or (a[i].NodeType = OnlyNodeType) then Result.Add( a[i].Captions[ Column ] ); end; @@ -2296,7 +2302,7 @@ end; // Tell type of db object (table|view) by a given row from a SHOW TABLE STATUS result -function GetDBObjectType( TableStatus: TFields ): Byte; +function GetDBObjectType( TableStatus: TFields ): TListNodeType; var t: String; begin @@ -2308,28 +2314,28 @@ begin but for views which is missing its tables, it says "Views bla references invalid..." } - Result := NODETYPE_TABLE; + Result := lntTable; if TableStatus.FindField('Type') <> nil then begin t := TableStatus.FindField('Type').AsString; if t = 'BASE TABLE' then - Result := NODETYPE_TABLE + Result := lntTable else if t = 'VIEW' then - Result := NODETYPE_VIEW + Result := lntView else if t = 'FUNCTION' then - Result := NODETYPE_FUNCTION + Result := lntFunction else if t = 'PROCEDURE' then - Result := NODETYPE_PROCEDURE; + Result := lntProcedure; end else begin if TableStatus[1].IsNull and // Engine column is NULL for views TableStatus[2].IsNull and (Pos('VIEW', UpperCase(TableStatus.FieldByName(DBO_COMMENT).AsWideString)) > 0) - then Result := NODETYPE_VIEW; + then Result := lntView; if TableStatus[1].IsNull and TableStatus[2].IsNull and (Pos('MARKED AS CRASHED', UpperCase(TableStatus.FieldByName(DBO_COMMENT).AsWideString)) > 0) - then Result := NODETYPE_CRASHED_TABLE; + then Result := lntCrashedTable; end; end; diff --git a/source/insertfiles.pas b/source/insertfiles.pas index 6c827a99..6261acd0 100644 --- a/source/insertfiles.pas +++ b/source/insertfiles.pas @@ -111,7 +111,7 @@ begin ComboBoxTables.Items.Clear; ds := Mainform.FetchDbTableList(ComboBoxDBs.Text); while not ds.Eof do begin - if GetDBObjectType(ds.Fields) in [NODETYPE_TABLE, NODETYPE_VIEW] then + if GetDBObjectType(ds.Fields) in [lntTable, lntView] then ComboBoxTables.Items.Add(ds.FieldByName(DBO_NAME).AsString); ds.Next; end; diff --git a/source/loaddata.pas b/source/loaddata.pas index 198b7694..74473080 100644 --- a/source/loaddata.pas +++ b/source/loaddata.pas @@ -146,10 +146,10 @@ begin // read tables from db comboTable.Items.Clear; seldb := Mainform.ActiveDatabase; - seltable := Mainform.SelectedTable; + seltable := Mainform.SelectedTable.Text; ds := Mainform.FetchDbTableList(comboDatabase.Text); while not ds.Eof do begin - if GetDBObjectType(ds.Fields) in [NODETYPE_TABLE, NODETYPE_VIEW] then + if GetDBObjectType(ds.Fields) in [lntTable, lntView] then comboTable.Items.Add(ds.FieldByName(DBO_NAME).AsWideString); count := comboTable.Items.Count-1; if (comboDatabase.Text = seldb) and (comboTable.Items[count] = seltable) then diff --git a/source/main.dfm b/source/main.dfm index 18ab435f..1671c48c 100644 --- a/source/main.dfm +++ b/source/main.dfm @@ -362,9 +362,9 @@ object MainForm: TMainForm TreeOptions.AutoOptions = [toAutoDropExpand, toAutoTristateTracking, toAutoDeleteMovedNodes] TreeOptions.PaintOptions = [toHideFocusRect, toHotTrack, toShowButtons, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed] TreeOptions.SelectionOptions = [toRightClickSelect] - OnChange = DBtreeChange OnDblClick = DBtreeDblClick OnExpanded = DBtreeExpanded + OnFocusChanged = DBtreeFocusChanged OnGetText = DBtreeGetText OnPaintText = DBtreePaintText OnGetImageIndex = DBtreeGetImageIndex @@ -917,6 +917,10 @@ object MainForm: TMainForm end> end end + object tabEditor: TTabSheet + Caption = 'Table' + ImageIndex = 14 + end object tabData: TTabSheet Caption = 'Data' ImageIndex = 41 @@ -2122,13 +2126,6 @@ object MainForm: TMainForm ImageIndex = 119 OnExecute = actCreateRoutineExecute end - object actViewData: TAction - Category = 'Data' - Caption = 'Data ...' - Hint = 'Displays data grid and allows row editing' - ImageIndex = 41 - OnExecute = actViewDataExecute - end object actEditObject: TAction Category = 'Database' Caption = 'Edit' @@ -5850,12 +5847,6 @@ object MainForm: TMainForm OnPopup = popupDBPopup Left = 136 Top = 64 - object menuViewData: TMenuItem - Action = actViewData - end - object N16: TMenuItem - Caption = '-' - end object menuEditObject: TMenuItem Action = actEditObject ShortCut = 32781 diff --git a/source/main.pas b/source/main.pas index c540d87d..54251e45 100644 --- a/source/main.pas +++ b/source/main.pas @@ -405,20 +405,18 @@ type btnExit: TToolButton; lblSorryNoData: TLabel; menuPrint: TMenuItem; - N16: TMenuItem; menuEditObject: TMenuItem; menuCreateObject: TMenuItem; menuDeleteObject: TMenuItem; menuMaintenance2: TMenuItem; menuEmptyTables: TMenuItem; - actViewData: TAction; - menuViewData: TMenuItem; actEditObject: TAction; menuCreateDB: TMenuItem; menuCreateTable: TMenuItem; menuCreateTableCopy: TMenuItem; menuCreateView: TMenuItem; menuCreateRoutine: TMenuItem; + tabEditor: TTabSheet; procedure refreshMonitorConfig; procedure loadWindowConfig; procedure saveWindowConfig; @@ -609,7 +607,8 @@ type PVirtualNode; Column: TColumnIndex; var Result: Integer); procedure vstHeaderDraggedOut(Sender: TVTHeader; Column: TColumnIndex; DropPosition: TPoint); - procedure DBtreeChange(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex); procedure DBtreeDblClick(Sender: TObject); procedure DBtreeGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var @@ -678,7 +677,6 @@ type Column: TColumnIndex; var Allowed: Boolean); procedure DBtreeExpanded(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure actEditObjectExecute(Sender: TObject); - procedure actViewDataExecute(Sender: TObject); procedure ListTablesDblClick(Sender: TObject); private ReachedEOT : Boolean; @@ -722,24 +720,25 @@ type procedure DisplayRowCountStats(MatchingRows: Int64 = -1); procedure insertFunction(Sender: TObject); function GetActiveDatabase: WideString; - function GetSelectedTable: WideString; + function GetSelectedTable: TListNode; procedure SetSelectedDatabase(db: WideString); - procedure SetSelectedTable(table: WideString); + procedure SelectDBObject(Text: WideString; NodeType: TListNodeType); procedure SetVisibleListColumns( List: TVirtualStringTree; Columns: WideStrings.TWideStringList ); function GetTableSize(ds: TDataSet): Int64; procedure ToggleFilterPanel(ForceVisible: Boolean = False); function GetSelTableColumns: TDataset; function GetSelTableKeys: TDataset; procedure AutoCalcColWidths(Tree: TVirtualStringTree; PrevLayout: Widestrings.TWideStringlist = nil); + procedure PlaceObjectEditor(Which: TListNodeType); public cancelling: Boolean; virtualDesktopName: string; MaintenanceForm: TOptimize; - ViewForm: TfrmView; + ViewEditor: TfrmView; UserManagerForm: TUserManagerForm; SelectDBObjectForm: TfrmSelectDBObject; SQLHelpForm: TfrmSQLhelp; - RoutineEditForm: TfrmRoutineEditor; + RoutineEditor: TfrmRoutineEditor; OptionsForm: Toptionsform; DatabasesWanted, Databases : Widestrings.TWideStringList; @@ -786,7 +785,7 @@ type prefNullColorDefault, prefNullBG : TColor; CreateDatabaseForm : TCreateDatabaseForm; - TableEditorForm : TfrmTableEditor; + TableEditor : TfrmTableEditor; FDataGridResult, FQueryGridResult : TGridResult; FDataGridSelect : WideStrings.TWideStringList; @@ -819,7 +818,7 @@ type property Conn : TOpenConnProf read FConn; property ActiveDatabase : WideString read GetActiveDatabase write SetSelectedDatabase; - property SelectedTable : WideString read GetSelectedTable write SetSelectedTable; + property SelectedTable : TListNode read GetSelectedTable; function FetchActiveDbTableList: TDataSet; function RefreshActiveDbTableList: TDataSet; @@ -835,8 +834,8 @@ type procedure DeactivateFileLogging; procedure TrimSQLLog; procedure TableEnginesCombo(var Combobox: TCombobox); - function GetNodeType(Node: PVirtualNode): Byte; - function GetSelectedNodeType: Byte; + function GetNodeType(Node: PVirtualNode): TListNodeType; + function GetSelectedNodeType: TListNodeType; procedure RefreshTree(DoResetTableCache: Boolean; SelectDatabase: WideString = ''); procedure RefreshTreeDB(db: WideString); function FindDBNode(db: WideString): PVirtualNode; @@ -861,6 +860,7 @@ type procedure SaveListSetup( List: TVirtualStringTree ); procedure RestoreListSetup( List: TVirtualStringTree ); function GetCollations(Items: TStrings = nil): TDataset; + procedure SetEditorTabCaption(Editor: TFrame; ObjName: WideString); end; @@ -1137,10 +1137,10 @@ begin SaveListSetup(ListCommandStats); SaveListSetup(ListTables); - FreeAndNil(RoutineEditForm); + FreeAndNil(RoutineEditor); FreeAndNil(MaintenanceForm); FreeAndNil(UserManagerForm); - FreeAndNil(ViewForm); + FreeAndNil(ViewEditor); FreeAndNil(SelectDBObjectForm); FreeAndNil(SQLHelpForm); FreeAndNil(OptionsForm); @@ -1696,7 +1696,7 @@ begin FreeAndNil(dsCollations); // Free forms which use session based datasets, fx dsShowEngines - FreeAndNil(TableEditorForm); + FreeAndNil(TableEditor); FreeAndNil(CreateDatabaseForm); // Closing connection @@ -1869,10 +1869,10 @@ end; } procedure TMainForm.actCreateViewExecute(Sender: TObject); begin - if ViewForm = nil then - ViewForm := TfrmView.Create(Self); - ViewForm.EditViewName := ''; - ViewForm.ShowModal; + tabEditor.TabVisible := True; + PagecontrolMain.ActivePage := tabEditor; + PlaceObjectEditor(lntView); + ViewEditor.Init; end; @@ -2080,7 +2080,7 @@ begin // Copy data in focused grid as HTML table Screen.Cursor := crHourglass; S := TMemoryStream.Create; - if ActiveGrid = DataGrid then Title := SelectedTable + if ActiveGrid = DataGrid then Title := SelectedTable.Text else Title := 'SQL query'; try GridData := ActiveData; @@ -2104,7 +2104,7 @@ begin // Copy data in focused grid as XML Screen.Cursor := crHourglass; S := TMemoryStream.Create; - if ActiveGrid = DataGrid then Root := SelectedTable + if ActiveGrid = DataGrid then Root := SelectedTable.Text else Root := 'SQL query'; try GridData := ActiveData; @@ -2128,7 +2128,7 @@ begin // Copy data in focused grid as SQL Screen.Cursor := crHourglass; S := TMemoryStream.Create; - if ActiveGrid = DataGrid then Tablename := SelectedTable + if ActiveGrid = DataGrid then Tablename := SelectedTable.Text else Tablename := 'unknown'; try GridData := ActiveData; @@ -2157,7 +2157,7 @@ begin Grid := ActiveGrid; GridData := ActiveData; if Grid = DataGrid then - Title := SelectedTable + Title := SelectedTable.Text else Title := 'SQL query'; @@ -2259,10 +2259,10 @@ begin InDBTree := TPopupMenu((Comp as TMenuItem).GetParentMenu).PopupComponent = DBTree; if InDBTree then begin // If a table is selected, use that for preselection. If only a db was selected, use all tables inside it. - if SelectedTable <> '' then - f.SelectedTables.Add(Mainform.SelectedTable) + if SelectedTable.Text <> '' then + f.SelectedTables.Add(SelectedTable.Text) else if Mainform.ActiveDatabase <> '' then begin - ds := Mainform.FetchDbTableList(Mainform.ActiveDatabase); + ds := Mainform.FetchDbTableList(ActiveDatabase); while not ds.Eof do begin f.SelectedTables.Add(ds.FieldByName(DBO_NAME).AsWideString); ds.Next; @@ -2323,7 +2323,7 @@ begin if InDBTree then begin // drop table selected in tree view. case GetSelectedNodeType of - NODETYPE_DB: begin + lntDb: begin if MessageDlg('Drop Database "'+activeDB+'"?' + crlf + crlf + 'WARNING: You will lose all tables in database '+activeDB+'!', mtConfirmation, [mbok,mbcancel], 0) <> mrok then Abort; Screen.Cursor := crHourglass; @@ -2342,18 +2342,18 @@ begin end; Exit; end; - NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: Tables.Add(SelectedTable); - NODETYPE_VIEW: Views.Add(SelectedTable); - NODETYPE_PROCEDURE: Procedures.Add(SelectedTable); - NODETYPE_FUNCTION: Functions.Add(SelectedTable); + lntTable, lntCrashedTable: Tables.Add(SelectedTable.Text); + lntView: Views.Add(SelectedTable.Text); + lntProcedure: Procedures.Add(SelectedTable.Text); + lntFunction: Functions.Add(SelectedTable.Text); end; end else begin // Invoked from database tab - Tables := GetVTCaptions(ListTables, True, 0, NODETYPE_TABLE); - Tables.AddStrings(GetVTCaptions(ListTables, True, 0, NODETYPE_CRASHED_TABLE)); - Views := GetVTCaptions(ListTables, True, 0, NODETYPE_VIEW); - Procedures := GetVTCaptions(ListTables, True, 0, NODETYPE_PROCEDURE); - Functions := GetVTCaptions(ListTables, True, 0, NODETYPE_FUNCTION); + Tables := GetVTCaptions(ListTables, True, 0, lntTable); + Tables.AddStrings(GetVTCaptions(ListTables, True, 0, lntCrashedTable)); + Views := GetVTCaptions(ListTables, True, 0, lntView); + Procedures := GetVTCaptions(ListTables, True, 0, lntProcedure); + Functions := GetVTCaptions(ListTables, True, 0, lntFunction); end; // Fix actions temporarily enabled for popup menu. @@ -2551,9 +2551,10 @@ end; procedure TMainForm.actCreateTableExecute(Sender: TObject); begin - if TableEditorForm = nil then - TableEditorForm := TfrmTableEditor.Create(Self); - TableEditorForm.ShowModal; + tabEditor.TabVisible := True; + PagecontrolMain.ActivePage := tabEditor; + PlaceObjectEditor(lntTable); + TableEditor.Init; end; @@ -3285,6 +3286,7 @@ begin ) then PageControlMain.ActivePage := tabHost; tabDatabase.TabVisible := false; + tabEditor.TabVisible := false; tabData.TabVisible := false; Caption := winName; @@ -3300,6 +3302,7 @@ begin ) then PageControlMain.ActivePage := tabDatabase; tabDatabase.TabVisible := true; + tabEditor.TabVisible := false; tabData.TabVisible := false; Caption := winName + ' - /' + db; @@ -3425,16 +3428,14 @@ begin if DataGridHasChanges then actDataPostChangesExecute(Sender); - // Ensure is visible - tabData.TabVisible := true; // Switch to PageControlMain.ActivePage := tabData; try - if (SelectedTable <> '') and (ActiveDatabase <> '') then begin + if (SelectedTable.Text <> '') and (ActiveDatabase <> '') then begin if FDataGridSelect = nil then FDataGridSelect := WideStrings.TWideStringlist.Create; - if DataGridTable <> SelectedTable then begin + if DataGridTable <> SelectedTable.Text then begin FDataGridSelect.Clear; FSelectedTableColumns := nil; FSelectedTableKeys := nil; @@ -3447,7 +3448,7 @@ begin // Disable default if crash indicator on current table is found if MainReg.ValueExists(REGPREFIX_CRASH_IN_DATA) then begin MainReg.DeleteValue(REGNAME_DEFAULTVIEW); - LogSQL('A crash in the previous data loading for this table ('+SelectedTable+') was detected. Filtering was automatically reset to avoid the same crash for now.'); + LogSQL('A crash in the previous data loading for this table ('+SelectedTable.Text+') was detected. Filtering was automatically reset to avoid the same crash for now.'); // Reset crash indicator. MainReg.DeleteValue(REGPREFIX_CRASH_IN_DATA); end else begin @@ -3535,7 +3536,7 @@ begin select_base := copy( select_base, 1, Length(select_base)-1 ); select_base_full := copy( select_base_full, 1, Length(select_base_full)-1 ); // Include db name for cases in which dbtree is switching databases and pending updates are in process - select_from := ' FROM '+mask(ActiveDatabase)+'.'+mask(SelectedTable); + select_from := ' FROM '+mask(ActiveDatabase)+'.'+mask(SelectedTable.Text); // Final SELECT segments DataGridCurrentSelect := select_base; @@ -3571,7 +3572,7 @@ begin debug('mem: browse row initialization complete.'); // Switched to another table - if DataGridTable <> SelectedTable then begin + if DataGridTable <> SelectedTable.Text then begin DataGrid.OffsetXY := Point(0, 0); // Scroll to top left FreeAndNil(PrevTableColWidths); // Throw away remembered, manually resized column widths end; @@ -3583,14 +3584,14 @@ begin DataGrid.Header.Columns.EndUpdate; DataGrid.EndUpdate; FreeAndNil(sl_query); - if DataGridTable = SelectedTable then + if DataGridTable = SelectedTable.Text then DataGrid.OffsetXY := OldOffsetXY; viewingdata := false; EnumerateRecentFilters; Screen.Cursor := crDefault; end; DataGridDB := ActiveDatabase; - DataGridTable := SelectedTable; + DataGridTable := SelectedTable.Text; AutoCalcColWidths(DataGrid, PrevTableColWidths); end; @@ -3607,16 +3608,16 @@ var i: Integer; s: WideString; begin - lblDataTop.Caption := ActiveDatabase + '.' + SelectedTable; + lblDataTop.Caption := ActiveDatabase + '.' + SelectedTable.Text; IsFiltered := self.DataGridCurrentFilter <> ''; - if GetSelectedNodeType = NODETYPE_TABLE then begin + if GetSelectedNodeType = lntTable then begin // Get rowcount from table ds := FetchActiveDbTableList; rows_total := -1; IsInnodb := False; for i := 0 to ds.RecordCount - 1 do begin - if ds.FieldByName(DBO_NAME).AsWideString = SelectedTable then begin + if ds.FieldByName(DBO_NAME).AsWideString = SelectedTable.Text then begin s := ds.FieldByName(DBO_ROWS).AsString; if s <> '' then rows_total := MakeInt(s); IsInnodb := ds.Fields[1].AsString = 'InnoDB'; @@ -3957,21 +3958,21 @@ begin VTRowDataListTables[i-1].NodeType := GetDBObjectType( ds.Fields); // Find icon case VTRowDataListTables[i-1].NodeType of - NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: // A normal table + lntTable, lntCrashedTable: // A normal table begin - if GetDBObjectType(ds.Fields) = NODETYPE_CRASHED_TABLE then + if GetDBObjectType(ds.Fields) = lntCrashedTable then VTRowDataListTables[i-1].ImageIndex := ICONINDEX_CRASHED_TABLE else VTRowDataListTables[i-1].ImageIndex := ICONINDEX_TABLE; end; - NODETYPE_VIEW: + lntView: VTRowDataListTables[i-1].ImageIndex := ICONINDEX_VIEW; - NODETYPE_PROCEDURE: + lntProcedure: VTRowDataListTables[i-1].ImageIndex := ICONINDEX_STOREDPROCEDURE; - NODETYPE_FUNCTION: + lntFunction: VTRowDataListTables[i-1].ImageIndex := ICONINDEX_STOREDFUNCTION; end; @@ -4396,11 +4397,11 @@ const if Fields.FindField(DBO_TYPE) <> nil then ObjType := LowerCase(Fields.FieldByName(DBO_TYPE).AsString); case GetDBObjectType(Fields) of - NODETYPE_TABLE: Icon := ICONINDEX_TABLE; - NODETYPE_CRASHED_TABLE: Icon := ICONINDEX_CRASHED_TABLE; - NODETYPE_FUNCTION: Icon := ICONINDEX_STOREDFUNCTION; - NODETYPE_PROCEDURE: Icon := ICONINDEX_STOREDPROCEDURE; - NODETYPE_VIEW: Icon := ICONINDEX_VIEW; + lntTable: Icon := ICONINDEX_TABLE; + lntCrashedTable: Icon := ICONINDEX_CRASHED_TABLE; + lntFunction: Icon := ICONINDEX_STOREDFUNCTION; + lntProcedure: Icon := ICONINDEX_STOREDPROCEDURE; + lntView: Icon := ICONINDEX_VIEW; else Icon := -1; end; SynCompletionProposal1.InsertList.Add( ObjName ); @@ -4610,7 +4611,7 @@ var begin // Tables and views can be renamed, routines cannot NodeData := Sender.GetNodeData(Node); - Allowed := NodeData.NodeType in [NODETYPE_TABLE, NODETYPE_VIEW]; + Allowed := NodeData.NodeType in [lntTable, lntView]; end; @@ -4678,15 +4679,6 @@ begin end; -procedure TMainForm.actViewDataExecute(Sender: TObject); -begin - if Assigned(ListTables.FocusedNode) then begin - SelectedTable := ListTables.Text[ListTables.FocusedNode, ListTables.FocusedColumn]; - PageControlMain.ActivePage := tabData; - end; -end; - - {** Column-title clicked -> generate "ORDER BY" } @@ -4956,8 +4948,8 @@ begin actCreateView.Enabled := L in [1,2]; actCreateRoutine.Enabled := L in [1,2]; actDropObjects.Enabled := L in [1,2]; - actCopyTable.Enabled := HasFocus and (GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW]); - actEmptyTables.Enabled := HasFocus and (GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW]); + actCopyTable.Enabled := HasFocus and (GetSelectedNodeType in [lntTable, lntCrashedTable, lntView]); + actEmptyTables.Enabled := HasFocus and (GetSelectedNodeType in [lntTable, lntCrashedTable, lntView]); actEditObject.Enabled := L > 0; // Show certain items which are valid only here actViewData.Visible := False; @@ -4975,7 +4967,7 @@ begin actEmptyTables.Enabled := False; if HasFocus then begin NodeData := ListTables.GetNodeData(ListTables.FocusedNode); - actEmptyTables.Enabled := NodeData.NodeType in [NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW]; + actEmptyTables.Enabled := NodeData.NodeType in [lntTable, lntCrashedTable, lntView]; end; actEditObject.Enabled := HasFocus; // Show certain items which are valid only here @@ -5515,23 +5507,25 @@ begin end; -function TMainForm.GetSelectedTable: WideString; +function TMainForm.GetSelectedTable: TListNode; begin - if DBtree.GetFirstSelected = nil then Result := '' - else case DBtree.GetNodeLevel(DBtree.GetFirstSelected) of - 2: Result := DBtree.Text[DBtree.GetFirstSelected, 0]; - else Result := ''; + if Assigned(DBtree.FocusedNode) and (DBtree.GetNodeLevel(DBtree.FocusedNode)=2) then begin + Result.Text := DBtree.Text[DBtree.FocusedNode, 0]; + Result.NodeType := GetSelectedNodeType; + end else begin + Result.Text := ''; + Result.NodeType := lntNone; end; end; -function TMainForm.GetNodeType(Node: PVirtualNode): Byte; +function TMainForm.GetNodeType(Node: PVirtualNode): TListNodeType; var ds: TDataset; begin - Result := NODETYPE_DEFAULT; + Result := lntNone; if Assigned(Node) then case DBtree.GetNodeLevel(Node) of - 1: Result := NODETYPE_DB; + 1: Result := lntDb; 2: begin ds := FetchDbTableList(DBTree.Text[Node.Parent, 0]); ds.RecNo := Node.Index+1; @@ -5540,17 +5534,18 @@ begin end; end; -function TMainForm.GetSelectedNodeType: Byte; +function TMainForm.GetSelectedNodeType: TListNodeType; begin Result := GetNodeType(DBtree.GetFirstSelected); end; -procedure TMainForm.SetSelectedTable(table: WideString); +procedure TMainForm.SelectDBObject(Text: WideString; NodeType: TListNodeType); var i: integer; dbnode, tnode, snode: PVirtualNode; begin + debug('SelectDBObject()'); // Detect db node case DBtree.GetNodeLevel( DBtree.GetFirstSelected ) of 1: dbnode := DBtree.GetFirstSelected; @@ -5562,7 +5557,7 @@ begin tnode := DBtree.GetFirstChild(dbnode); for i := 0 to dbnode.ChildCount - 1 do begin // Select table node if it has the wanted caption - if DBtree.Text[tnode, 0] = table then begin + if (DBtree.Text[tnode, 0] = Text) and (GetNodeType(tnode) = NodeType) then begin snode := tnode; break; end; @@ -5573,7 +5568,7 @@ begin tnode := DBtree.GetFirstChild(dbnode); for i := 0 to dbnode.ChildCount - 1 do begin // Select table node if it has the wanted caption - if AnsiCompareText(DBtree.Text[tnode, 0], table) = 0 then begin + if (AnsiCompareText(DBtree.Text[tnode, 0], Text) = 0) and (GetNodeType(tnode) = NodeType) then begin snode := tnode; break; end; @@ -5585,9 +5580,11 @@ begin DBTree.ScrollIntoView(snode, False); DBtree.Expanded[dbnode] := True; DBtree.Selected[snode] := True; + // Implicitely calls OnFocusChanged: + DBTree.FocusedNode := snode; exit; end; - raise Exception.Create('Table node ' + table + ' not found in tree.'); + raise Exception.Create('Table node ' + Text + ' not found in tree.'); end; @@ -5664,7 +5661,7 @@ begin begin // Keep native order of columns lboxQueryHelpers.Sorted := False; - if SelectedTable <> '' then begin + if SelectedTable.Text <> '' then begin FSelectedTableColumns.First; while not FSelectedTableColumns.Eof do begin lboxQueryHelpers.Items.Add(FSelectedTableColumns.Fields[0].AsWideString); @@ -6172,13 +6169,15 @@ var Value : WideString; ValueList : WideStrings.TWideStringList; Regname: String; + frm: TCustomForm; begin ValueList := WideStrings.TWideStringList.Create; // Column widths Regname := List.Name; - if GetParentForm(List) <> Self then - Regname := GetParentForm(List).Name + '.' + Regname; + frm := GetParentForm(List); + if (frm <> Self) and (Assigned(frm)) then + Regname := frm.Name + '.' + Regname; Value := GetRegValue(REGPREFIX_COLWIDTHS + Regname, ''); if Value <> '' then begin ValueList := Explode( ',', Value ); @@ -6634,7 +6633,7 @@ begin end; 1: case GetNodeType(Node) of // Calculate and display the sum of all table sizes in ALL dbs if all table lists are cached - NODETYPE_DEFAULT: begin + lntNone: begin AllListsCached := true; for i := 0 to Databases.Count - 1 do begin if not DbTableListCachedAndValid(Databases[i]) then begin @@ -6658,7 +6657,7 @@ begin else CellText := ''; end; // Calculate and display the sum of all table sizes in ONE db, if the list is already cached. - NODETYPE_DB: begin + lntDb: begin db := DBtree.Text[Node, 0]; if not DbTableListCachedAndValid(db) then CellText := '' @@ -6676,7 +6675,7 @@ begin else CellText := ''; end; end; - NODETYPE_TABLE: begin + lntTable: begin db := DBtree.Text[Node.Parent, 0]; ds := FetchDbTableList(db); ds.RecNo := Node.Index + 1; @@ -6709,21 +6708,21 @@ begin ds := FetchDbTableList(Databases[Node.Parent.Index]); ds.RecNo := Node.Index+1; case GetDBObjectType(ds.Fields) of - NODETYPE_TABLE: + lntTable: if Kind = ikSelected then ImageIndex := ICONINDEX_TABLE_HIGHLIGHT else ImageIndex := ICONINDEX_TABLE; - NODETYPE_VIEW: + lntView: if Kind = ikSelected then ImageIndex := ICONINDEX_VIEW_HIGHLIGHT else ImageIndex := ICONINDEX_VIEW; - NODETYPE_CRASHED_TABLE: + lntCrashedTable: if Kind = ikSelected then ImageIndex := ICONINDEX_CRASHED_TABLE_HIGHLIGHT else ImageIndex := ICONINDEX_CRASHED_TABLE; - NODETYPE_PROCEDURE: + lntProcedure: ImageIndex := ICONINDEX_STOREDPROCEDURE; - NODETYPE_FUNCTION: + lntFunction: ImageIndex := ICONINDEX_STOREDFUNCTION; end; end; @@ -6823,10 +6822,12 @@ end; {** Selection in database tree has changed } -procedure TMainForm.DBtreeChange(Sender: TBaseVirtualTree; Node: PVirtualNode); +procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; + Node: PVirtualNode; Column: TColumnIndex); var newDb: WideString; begin + debug('DBtreeFocusChanged()'); if not Assigned(Node) then Exit; // Post pending UPDATE @@ -6840,13 +6841,15 @@ begin end; 2: begin newDb := Databases[Node.Parent.Index]; - lblSorryNoData.Visible := False; - if GetSelectedNodeType = NODETYPE_PROCEDURE then lblSorryNoData.Visible := True; - if GetSelectedNodeType = NODETYPE_FUNCTION then lblSorryNoData.Visible := True; - dataselected := false; - PageControlMain.ActivePage := tabData; - viewdata(self); - PageControlMainChange(Self); + tabEditor.TabVisible := True; + tabData.TabVisible := SelectedTable.NodeType in [lntTable, lntCrashedTable, lntView]; + if tabEditor.TabVisible then begin + actEditObjectExecute(Sender); + if (PagecontrolMain.ActivePage <> tabEditor) and (PagecontrolMain.ActivePage <> tabData) then + PagecontrolMain.ActivePage := tabEditor + else if PagecontrolMain.ActivePage = tabData then + ViewData(Sender); + end; end; end; if newDb <> '' then @@ -6888,7 +6891,8 @@ end; } procedure TMainForm.RefreshTree(DoResetTableCache: Boolean; SelectDatabase: WideString = ''); var - oldActiveDatabase, oldSelectedTable, db: WideString; + oldActiveDatabase, db: WideString; + oldSelectedTable: TListNode; Node: PVirtualNode; ExpandedDBs, TablesFetched: WideStrings.TWideStringList; i: Integer; @@ -6938,7 +6942,7 @@ begin TablesFetched.Free; try - if oldSelectedTable <> '' then SelectedTable := oldSelectedTable; + if oldSelectedTable.Text <> '' then SelectDBObject(oldSelectedTable.Text, oldSelectedTable.NodeType); except end; DBTree.EndUpdate; @@ -7191,7 +7195,7 @@ begin // Set indicator for possibly crashing query OpenRegistry(SessionName); - regCrashIndicName := Utf8Encode(REGPREFIX_CRASH_IN_DATA + ActiveDatabase + '.' + SelectedTable); + regCrashIndicName := Utf8Encode(REGPREFIX_CRASH_IN_DATA + ActiveDatabase + '.' + SelectedTable.Text); MainReg.WriteBool(regCrashIndicName, True); // start query @@ -7807,7 +7811,7 @@ var msg: String; begin Node := Sender.GetFirstSelected; - sql := 'DELETE FROM '+mask(SelectedTable)+' WHERE'; + sql := 'DELETE FROM '+mask(SelectedTable.Text)+' WHERE'; while Assigned(Node) do begin EnsureChunkLoaded(Sender, Node); sql := sql + ' (' + @@ -7928,7 +7932,7 @@ begin if CheckUniqueKeyClause then begin sql := 'SELECT ' + mask(Col.Name) + - ' FROM ' + mask(SelectedTable) + + ' FROM ' + mask(SelectedTable.Text) + ' WHERE ' + GetWhereClause(Row, @Data.Columns) ; ds := GetResults(sql); @@ -8016,9 +8020,9 @@ begin if (FLastSelectedTableColumns = nil) or (FLastSelectedTableColumns.State = dsInactive) then begin FreeAndNil(FLastSelectedTableColumns); // Avoid SQL error on routines - if GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_VIEW] then begin + if GetSelectedNodeType in [lntTable, lntView] then begin ShowStatus('Reading table columns ...'); - FLastSelectedTableColumns := GetResults( 'SHOW /*!32332 FULL */ COLUMNS FROM ' + mask(SelectedTable), false ); + FLastSelectedTableColumns := GetResults( 'SHOW /*!32332 FULL */ COLUMNS FROM ' + mask(SelectedTable.Text), false ); end; end; Result := FLastSelectedTableColumns; @@ -8029,9 +8033,9 @@ begin if (FLastSelectedTableKeys = nil) or (FLastSelectedTableKeys.State = dsInactive) then begin FreeAndNil(FLastSelectedTableKeys); // Avoid SQL error on routines - if GetSelectedNodeType in [NODETYPE_TABLE, NODETYPE_VIEW] then begin + if GetSelectedNodeType in [lntTable, lntView] then begin ShowStatus('Reading table keys ...'); - FLastSelectedTableKeys := GetResults( 'SHOW KEYS FROM ' + mask(SelectedTable) ); + FLastSelectedTableKeys := GetResults( 'SHOW KEYS FROM ' + mask(SelectedTable.Text) ); end; end; Result := FLastSelectedTableKeys; @@ -8298,7 +8302,7 @@ function TMainForm.GetRegKeyTable: String; begin // Return the slightly complex registry path to \Servers\ThisServer\curdb|curtable Result := REGPATH + REGKEY_SESSIONS + SessionName + '\' + - Utf8Encode(ActiveDatabase) + REGDELIM + Utf8Encode(SelectedTable); + Utf8Encode(ActiveDatabase) + REGDELIM + Utf8Encode(SelectedTable.Text); end; @@ -8756,9 +8760,10 @@ end; procedure TMainForm.actCreateRoutineExecute(Sender: TObject); begin - if not Assigned(RoutineEditForm) then - RoutineEditForm := TfrmRoutineEditor.Create(Self); - RoutineEditForm.ShowModal; + tabEditor.TabVisible := True; + PagecontrolMain.ActivePage := tabEditor; + PlaceObjectEditor(lntProcedure); + RoutineEditor.Init; end; @@ -8838,56 +8843,101 @@ begin end; +procedure TMainForm.PlaceObjectEditor(Which: TListNodeType); +var + frm: TFrame; +begin + // Place the relevant editor frame onto the editor tab, hide all others + if (not (Which in [lntTable, lntCrashedTable])) and Assigned(TableEditor) then + FreeAndNil(TableEditor); + if (Which <> lntView) and Assigned(ViewEditor) then + FreeAndNil(ViewEditor); + if (not (Which in [lntProcedure, lntFunction])) and Assigned(RoutineEditor) then + FreeAndNil(RoutineEditor); + if Which in [lntTable, lntCrashedTable] then begin + if not Assigned(TableEditor) then + TableEditor := TfrmTableEditor.Create(tabEditor); + frm := TableEditor; + end else if Which = lntView then begin + if not Assigned(ViewEditor) then + ViewEditor := TfrmView.Create(tabEditor); + frm := ViewEditor; + end else if Which in [lntProcedure, lntFunction] then begin + if not Assigned(RoutineEditor) then + RoutineEditor := TfrmRoutineEditor.Create(tabEditor); + frm := RoutineEditor; + end else + Exit; + frm.Parent := tabEditor; +end; + + +procedure TMainForm.SetEditorTabCaption(Editor: TFrame; ObjName: WideString); +var + ObjType, Cap: WideString; + IconIndex: Integer; +begin + if Editor = TableEditor then begin + ObjType := 'Table'; + IconIndex := ICONINDEX_TABLE; + end else if Editor = ViewEditor then begin + ObjType := 'View'; + IconIndex := ICONINDEX_VIEW; + end else if Editor = RoutineEditor then begin + ObjType := 'Routine'; + IconIndex := ICONINDEX_STOREDPROCEDURE; + end else + Exit; + tabEditor.ImageIndex := IconIndex; + Cap := ObjType+': '; + if ObjName = '' then + Cap := Cap + '[Untitled]' + else + Cap := sstr(Cap + ObjName, 30); + tabEditor.Caption := Cap; +end; + + procedure TMainForm.actEditObjectExecute(Sender: TObject); var - Act: TAction; - InDBTree: Boolean; - ObjectType: Byte; - ObjectName: WideString; NodeData: PVTreeData; + RoutineType: String; begin - Act := Sender as TAction; - InDBTree := (Act.ActionComponent is TMenuItem) - and (TPopupMenu((Act.ActionComponent as TMenuItem).GetParentMenu).PopupComponent = DBTree); - - if InDBTree then begin - ObjectType := GetSelectedNodeType; - ObjectName := DBTree.Text[DBTree.FocusedNode, DBTree.FocusedColumn]; - end else begin + debug('actEditObjectExecute()'); + if ListTables.Focused then begin + // Got here from ListTables.OnDblClick or ListTables's context menu item "Edit" NodeData := ListTables.GetNodeData(ListTables.FocusedNode); - ObjectType := NodeData.NodeType; - ObjectName := ListTables.Text[ListTables.FocusedNode, ListTables.FocusedColumn]; + if (NodeData.Captions[0] <> SelectedTable.Text) or (NodeData.NodeType <> SelectedTable.NodeType) then + SelectDBObject(NodeData.Captions[0], NodeData.NodeType); end; - case ObjectType of - NODETYPE_DB: begin + case SelectedTable.NodeType of + lntDb: begin if CreateDatabaseForm = nil then CreateDatabaseForm := TCreateDatabaseForm.Create(Self); - CreateDatabaseForm.modifyDB := ObjectName; + CreateDatabaseForm.modifyDB := ActiveDatabase; CreateDatabaseForm.ShowModal; end; - NODETYPE_TABLE, NODETYPE_CRASHED_TABLE: begin - if TableEditorForm = nil then - TableEditorForm := TfrmTableEditor.Create(Self); - TableEditorForm.AlterTableName := ObjectName; - TableEditorForm.ShowModal; + + lntTable, lntCrashedTable: begin + PlaceObjectEditor(SelectedTable.NodeType); + TableEditor.Init(SelectedTable.Text); end; - NODETYPE_VIEW: begin - if ViewForm = nil then - ViewForm := TfrmView.Create(Self); - ViewForm.EditViewName := ObjectName; - ViewForm.ShowModal; + + lntView: begin + PlaceObjectEditor(SelectedTable.NodeType); + ViewEditor.Init(SelectedTable.Text); end; - NODETYPE_FUNCTION, NODETYPE_PROCEDURE: begin - if not Assigned(RoutineEditForm) then - RoutineEditForm := TfrmRoutineEditor.Create(Self); - RoutineEditForm.AlterRoutineName := ObjectName; - if ObjectType = NODETYPE_FUNCTION then - RoutineEditForm.AlterRoutineType := 'FUNCTION' + + lntFunction, lntProcedure: begin + PlaceObjectEditor(SelectedTable.NodeType); + if SelectedTable.NodeType = lntFunction then + RoutineType := 'FUNCTION' else - RoutineEditForm.AlterRoutineType := 'PROCEDURE'; - RoutineEditForm.ShowModal; + RoutineType := 'PROCEDURE'; + RoutineEditor.Init(SelectedTable.Text, RoutineType); end; + end; end; @@ -8896,13 +8946,11 @@ procedure TMainForm.ListTablesDblClick(Sender: TObject); var NodeData: PVTreeData; begin - // DoubleClick: Display datagrid for tables and views, editor dialog for routines - NodeData := ListTables.GetNodeData(ListTables.FocusedNode); - case NodeData.NodeType of - NODETYPE_TABLE, NODETYPE_CRASHED_TABLE, NODETYPE_VIEW: - actViewDataExecute(actViewData); - NODETYPE_FUNCTION, NODETYPE_PROCEDURE: - actEditObjectExecute(actEditObject); + // DoubleClick: Display editor + debug('ListTablesDblClick()'); + if Assigned(ListTables.FocusedNode) then begin + NodeData := ListTables.GetNodeData(ListTables.FocusedNode); + SelectDBObject(ListTables.Text[ListTables.FocusedNode, ListTables.FocusedColumn], NodeData.NodeType); end; end; diff --git a/source/optimizetables.pas b/source/optimizetables.pas index b3341329..a47ca5de 100644 --- a/source/optimizetables.pas +++ b/source/optimizetables.pas @@ -120,7 +120,7 @@ begin ds := Mainform.FetchDbTableList(DBComboBox.Text); TablesCheckListBox.Items.Clear; while not ds.Eof do begin - if GetDBObjectType(ds.Fields) = NODETYPE_TABLE then + if GetDBObjectType(ds.Fields) = lntTable then TablesCheckListBox.Items.Add(ds.FieldByName(DBO_NAME).AsWideString); ds.Next; end; diff --git a/source/routine_editor.dfm b/source/routine_editor.dfm index 7bd6e455..d65a7c3b 100644 --- a/source/routine_editor.dfm +++ b/source/routine_editor.dfm @@ -1,30 +1,22 @@ object frmRoutineEditor: TfrmRoutineEditor Left = 0 Top = 0 - Caption = 'Stored routine editor' - ClientHeight = 464 - ClientWidth = 384 - Color = clBtnFace - Constraints.MinHeight = 500 - Constraints.MinWidth = 400 + Width = 475 + Height = 484 + Constraints.MinHeight = 240 + Constraints.MinWidth = 320 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False - Position = poMainFormCenter - OnClose = FormClose - OnCreate = FormCreate - OnDestroy = FormDestroy - OnShow = FormShow + ParentFont = False + TabOrder = 0 DesignSize = ( - 384 - 464) - PixelsPerInch = 96 - TextHeight = 13 + 475 + 484) object lblName: TLabel - Left = 8 + Left = 3 Top = 11 Width = 31 Height = 13 @@ -32,7 +24,7 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = editName end object lblType: TLabel - Left = 8 + Left = 3 Top = 36 Width = 28 Height = 13 @@ -40,7 +32,7 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = comboType end object lblReturns: TLabel - Left = 8 + Left = 3 Top = 61 Width = 42 Height = 13 @@ -48,14 +40,14 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = comboReturns end object lblParameters: TLabel - Left = 8 + Left = 3 Top = 187 Width = 59 Height = 13 Caption = 'Parameters:' end object lblSQL: TLabel - Left = 8 + Left = 3 Top = 87 Width = 62 Height = 13 @@ -63,7 +55,7 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = comboDataAccess end object lblSecurity: TLabel - Left = 8 + Left = 3 Top = 112 Width = 65 Height = 13 @@ -71,7 +63,7 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = comboSecurity end object lblComment: TLabel - Left = 8 + Left = 3 Top = 137 Width = 49 Height = 13 @@ -79,49 +71,39 @@ object frmRoutineEditor: TfrmRoutineEditor FocusControl = editComment end object lblSQLcode: TLabel - Left = 8 + Left = 3 Top = 317 Width = 68 Height = 13 Caption = '&Routine body:' FocusControl = SynMemoBody end - object btnApply: TButton - Left = 301 - Top = 432 + object btnSave: TButton + Left = 165 + Top = 455 Width = 75 Height = 25 - Anchors = [akRight, akBottom] - Caption = 'Apply' - TabOrder = 13 - OnClick = PostChanges - end - object btnCancel: TButton - Left = 220 - Top = 432 - Width = 75 - Height = 25 - Anchors = [akRight, akBottom] - Cancel = True - Caption = 'Cancel' - ModalResult = 2 - TabOrder = 12 - end - object btnOK: TButton - Left = 139 - Top = 432 - Width = 75 - Height = 25 - Anchors = [akRight, akBottom] - Caption = 'OK' + Anchors = [akLeft, akBottom] + Caption = 'Save' Default = True - ModalResult = 1 - TabOrder = 11 + TabOrder = 12 OnClick = PostChanges end + object btnDiscard: TButton + Left = 84 + Top = 455 + Width = 75 + Height = 25 + Anchors = [akLeft, akBottom] + Cancel = True + Caption = 'Discard' + ModalResult = 2 + TabOrder = 11 + OnClick = btnDiscardClick + end object btnHelp: TButton - Left = 8 - Top = 432 + Left = 3 + Top = 455 Width = 75 Height = 25 Anchors = [akLeft, akBottom] @@ -130,9 +112,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnClick = btnHelpClick end object comboReturns: TComboBox - Left = 100 + Left = 95 Top = 58 - Width = 276 + Width = 377 Height = 21 Anchors = [akLeft, akTop, akRight] ItemHeight = 13 @@ -141,9 +123,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnChange = Modification end object comboType: TTntComboBox - Left = 100 + Left = 95 Top = 33 - Width = 276 + Width = 377 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -152,9 +134,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnSelect = comboTypeSelect end object editName: TTntEdit - Left = 100 + Left = 95 Top = 8 - Width = 276 + Width = 377 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 0 @@ -162,7 +144,7 @@ object frmRoutineEditor: TfrmRoutineEditor OnChange = editNameChange end object tlbParameters: TToolBar - Left = 8 + Left = 3 Top = 206 Width = 72 Height = 84 @@ -198,9 +180,9 @@ object frmRoutineEditor: TfrmRoutineEditor end end object listParameters: TVirtualStringTree - Left = 100 + Left = 95 Top = 206 - Width = 276 + Width = 377 Height = 100 Anchors = [akLeft, akTop, akRight] DragImageKind = diMainColumnOnly @@ -236,7 +218,7 @@ object frmRoutineEditor: TfrmRoutineEditor item Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible, coAllowFocus] Position = 1 - Width = 87 + Width = 188 WideText = 'Name' end item @@ -253,9 +235,9 @@ object frmRoutineEditor: TfrmRoutineEditor end> end object comboDataAccess: TComboBox - Left = 100 + Left = 95 Top = 84 - Width = 276 + Width = 377 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -264,9 +246,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnChange = Modification end object comboSecurity: TComboBox - Left = 100 + Left = 95 Top = 109 - Width = 276 + Width = 377 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -275,9 +257,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnChange = Modification end object editComment: TTntEdit - Left = 100 + Left = 95 Top = 134 - Width = 276 + Width = 377 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 5 @@ -285,9 +267,9 @@ object frmRoutineEditor: TfrmRoutineEditor OnChange = Modification end object chkDeterministic: TCheckBox - Left = 100 + Left = 95 Top = 161 - Width = 276 + Width = 377 Height = 17 Anchors = [akLeft, akTop, akRight] Caption = '&Deterministic' @@ -295,10 +277,10 @@ object frmRoutineEditor: TfrmRoutineEditor OnClick = Modification end object SynMemoBody: TSynMemo - Left = 8 + Left = 3 Top = 336 - Width = 368 - Height = 90 + Width = 469 + Height = 113 SingleLineMode = False Anchors = [akLeft, akTop, akRight, akBottom] Font.Charset = DEFAULT_CHARSET diff --git a/source/routine_editor.pas b/source/routine_editor.pas index 514ba5ff..ddc40552 100644 --- a/source/routine_editor.pas +++ b/source/routine_editor.pas @@ -8,10 +8,9 @@ uses VirtualTrees, WideStrings, db, SynRegExpr, WideStrUtils; type - TfrmRoutineEditor = class(TForm) - btnApply: TButton; - btnCancel: TButton; - btnOK: TButton; + TfrmRoutineEditor = class(TFrame) + btnSave: TButton; + btnDiscard: TButton; btnHelp: TButton; lblName: TLabel; lblType: TLabel; @@ -34,10 +33,6 @@ type chkDeterministic: TCheckBox; lblSQLcode: TLabel; SynMemoBody: TSynMemo; - procedure FormCreate(Sender: TObject); - procedure FormDestroy(Sender: TObject); - procedure FormShow(Sender: TObject); - procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure comboTypeSelect(Sender: TObject); procedure PostChanges(Sender: TObject); procedure btnHelpClick(Sender: TObject); @@ -68,16 +63,19 @@ type procedure listParametersPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); + procedure btnDiscardClick(Sender: TObject); private { Private declarations } Parameters: TWideStringList; FModified: Boolean; + FAlterRoutineName: WideString; + FAlterRoutineType: String; procedure SetModified(Value: Boolean); property Modified: Boolean read FModified write SetModified; public { Public declarations } - AlterRoutineName: WideString; - AlterRoutineType: String; + constructor Create(AOwner: TComponent); override; + procedure Init(AlterRoutineName: WideString=''; AlterRoutineType: String=''); end; @@ -91,13 +89,12 @@ const DELIM = '|'; -procedure TfrmRoutineEditor.FormCreate(Sender: TObject); +constructor TfrmRoutineEditor.Create(AOwner: TComponent); var i: Integer; begin - // Restore form dimensions - Width := GetRegValue(REGNAME_PROCEDITOR_WIDTH, Width); - Height := GetRegValue(REGNAME_PROCEDITOR_HEIGHT, Height); + inherited Create(AOwner); + Align := alClient; // Combo items in a .dfm are sporadically lost after an IDE restart, // so we set them here to avoid developer annoyance comboType.Items.Add('Procedure (doesn''t return a result)'); @@ -120,16 +117,7 @@ begin end; -procedure TfrmRoutineEditor.FormDestroy(Sender: TObject); -begin - // Store form dimensions - OpenRegistry; - MainReg.WriteInteger(REGNAME_PROCEDITOR_WIDTH, Width); - MainReg.WriteInteger(REGNAME_PROCEDITOR_HEIGHT, Height); -end; - - -procedure TfrmRoutineEditor.FormShow(Sender: TObject); +procedure TfrmRoutineEditor.Init(AlterRoutineName: WideString=''; AlterRoutineType: String=''); var ds: TDataSet; Create: WideString; @@ -138,34 +126,36 @@ var rx: TRegExpr; i: Integer; begin - editName.Text := AlterRoutineName; + FAlterRoutineName := AlterRoutineName; + FAlterRoutineType := AlterRoutineType; + editName.Text := FAlterRoutineName; comboType.ItemIndex := 0; comboReturns.Text := ''; listParameters.Clear; + Parameters.Clear; comboDataAccess.ItemIndex := 0; comboSecurity.ItemIndex := 0; editComment.Clear; SynMemoBody.Text := 'BEGIN'+CRLF+CRLF+'END'; - if editName.Text <> '' then begin + if FAlterRoutineName <> '' then begin // Editing existing routine + Mainform.SetEditorTabCaption(Self, FAlterRoutineName); ds := Mainform.GetResults('SELECT * FROM '+DBNAME_INFORMATION_SCHEMA+'.ROUTINES'+ ' WHERE ROUTINE_SCHEMA='+esc(Mainform.ActiveDatabase)+ - ' AND ROUTINE_NAME='+esc(AlterRoutineName)+ - ' AND ROUTINE_TYPE='+esc(AlterRoutineType) + ' AND ROUTINE_NAME='+esc(FAlterRoutineName)+ + ' AND ROUTINE_TYPE='+esc(FAlterRoutineType) ); - if ds.RecordCount <> 1 then begin - MessageDlg('Cannot find properties of stored routine '+AlterRoutineName, mtError, [mbOK], 0); - Close; - end; + if ds.RecordCount <> 1 then + Exception.Create('Cannot find properties of stored routine '+FAlterRoutineName); ds.First; - comboType.ItemIndex := ListIndexByRegExpr(comboType.Items, '^'+AlterRoutineType+'\b'); + comboType.ItemIndex := ListIndexByRegExpr(comboType.Items, '^'+FAlterRoutineType+'\b'); chkDeterministic.Checked := ds.FieldByName('IS_DETERMINISTIC').AsString = 'YES'; comboReturns.Text := ds.FieldByName('DTD_IDENTIFIER').AsWideString; comboDataAccess.ItemIndex := comboDataAccess.Items.IndexOf(ds.FieldByName('SQL_DATA_ACCESS').AsString); comboSecurity.ItemIndex := comboSecurity.Items.IndexOf(ds.FieldByName('SECURITY_TYPE').AsString); editComment.Text := ds.FieldByName('ROUTINE_COMMENT').AsWideString; SynMemoBody.Text := ds.FieldByName('ROUTINE_DEFINITION').AsWideString; - Create := Mainform.GetVar('SHOW CREATE '+AlterRoutineType+' '+Mainform.mask(editName.Text), 2); + Create := Mainform.GetVar('SHOW CREATE '+FAlterRoutineType+' '+Mainform.mask(editName.Text), 2); rx := TRegExpr.Create; rx.ModifierI := True; rx.ModifierG := False; @@ -185,23 +175,15 @@ begin FreeAndNil(Params); end; FreeAndNil(ds); - end; - editName.SetFocus; - editNameChange(Sender); + end else + Mainform.SetEditorTabCaption(Self, ''); + editNameChange(Self); comboTypeSelect(comboType); btnRemoveParam.Enabled := Assigned(listParameters.FocusedNode); Modified := False; end; -procedure TfrmRoutineEditor.FormClose(Sender: TObject; var Action: TCloseAction); -begin - // Reset edited proc name for the next call - AlterRoutineName := ''; - Parameters.Clear; -end; - - procedure TfrmRoutineEditor.editNameChange(Sender: TObject); begin editName.Font.Color := clWindowText; @@ -418,12 +400,10 @@ begin if editName.Text = '' then begin MessageDlg('Please specify the routine''s name.', mtError, [mbOK], 0); editName.SetFocus; - ModalResult := mrNone; Exit; end else if (ProcOrFunc = 'FUNCTION') and (comboReturns.Text = '') then begin MessageDlg('Please specify the function''s returning datatype.', mtError, [mbOK], 0); comboReturns.SetFocus; - ModalResult := mrNone; Exit; end; @@ -448,63 +428,63 @@ begin BaseSQL := BaseSQL + 'COMMENT ' + esc(editComment.Text)+' '; BaseSQL := BaseSQL + SynMemoBody.Text; - try - // There is no way to ALTER parameters or the name of it. - // Create a temp routine, check for syntax errors, then drop the old routine and create it. - // See also: http://dev.mysql.com/doc/refman/5.0/en/alter-procedure.html - if AlterRoutineName <> '' then begin - // Create temp name - i := 0; - allRoutineNames := Mainform.GetCol('SELECT ROUTINE_NAME FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.'+Mainform.mask('ROUTINES')+ - ' WHERE ROUTINE_SCHEMA = '+esc(Mainform.ActiveDatabase)+ - ' AND ROUTINE_TYPE = '+esc(ProcOrFunc) - ); - TargetExists := ((editName.Text <> AlterRoutineName) or (ProcOrFunc <> AlterRoutineType)) and - (allRoutineNames.IndexOf(editName.Text) > -1); - if TargetExists then begin - if MessageDlg('Routine "'+editName.Text+'" already exists. Overwrite it?', - mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then begin - ModalResult := mrNone; - Exit; - end; - end; - while True do begin - inc(i); - TempName := APPNAME + '_temproutine_' + IntToStr(i); - if allRoutineNames.IndexOf(TempName) = -1 then - break; - end; - TempSQL := 'CREATE '+ProcOrFunc+' '+Mainform.mask(tempName)+'(' + BaseSQL; - Mainform.ExecUpdateQuery(TempSQL, False, True); - // Drop temporary routine, used for syntax checking - Mainform.ExecUpdateQuery('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(TempName)); - // Drop edited routine - Mainform.ExecUpdateQuery('DROP '+AlterRoutineType+' IF EXISTS '+Mainform.mask(AlterRoutineName)); - if TargetExists then begin - // Drop target routine - overwriting has been confirmed, see above - Mainform.ExecUpdateQuery('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(editName.Text)); + // There is no way to ALTER parameters or the name of it. + // Create a temp routine, check for syntax errors, then drop the old routine and create it. + // See also: http://dev.mysql.com/doc/refman/5.0/en/alter-procedure.html + if FAlterRoutineName <> '' then begin + // Create temp name + i := 0; + allRoutineNames := Mainform.GetCol('SELECT ROUTINE_NAME FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.'+Mainform.mask('ROUTINES')+ + ' WHERE ROUTINE_SCHEMA = '+esc(Mainform.ActiveDatabase)+ + ' AND ROUTINE_TYPE = '+esc(ProcOrFunc) + ); + TargetExists := ((editName.Text <> FAlterRoutineName) or (ProcOrFunc <> FAlterRoutineType)) and + (allRoutineNames.IndexOf(editName.Text) > -1); + if TargetExists then begin + if MessageDlg('Routine "'+editName.Text+'" already exists. Overwrite it?', + mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then begin + Exit; end; end; - FinalSQL := 'CREATE '+ProcOrFunc+' '+Mainform.mask(editName.Text)+'(' + BaseSQL; - Mainform.ExecUpdateQuery(FinalSQL, False, True); - // Set editing name if create/alter query was successful - AlterRoutineName := editName.Text; - AlterRoutineType := ProcOrFunc; - Mainform.actRefresh.Execute; - Modified := False; - except - On E:Exception do begin - ModalResult := mrNone; + while True do begin + inc(i); + TempName := APPNAME + '_temproutine_' + IntToStr(i); + if allRoutineNames.IndexOf(TempName) = -1 then + break; + end; + TempSQL := 'CREATE '+ProcOrFunc+' '+Mainform.mask(tempName)+'(' + BaseSQL; + Mainform.ExecUpdateQuery(TempSQL, False, True); + // Drop temporary routine, used for syntax checking + Mainform.ExecUpdateQuery('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(TempName)); + // Drop edited routine + Mainform.ExecUpdateQuery('DROP '+FAlterRoutineType+' IF EXISTS '+Mainform.mask(FAlterRoutineName)); + if TargetExists then begin + // Drop target routine - overwriting has been confirmed, see above + Mainform.ExecUpdateQuery('DROP '+ProcOrFunc+' IF EXISTS '+Mainform.mask(editName.Text)); end; end; + FinalSQL := 'CREATE '+ProcOrFunc+' '+Mainform.mask(editName.Text)+'(' + BaseSQL; + Mainform.ExecUpdateQuery(FinalSQL, False, True); + // Set editing name if create/alter query was successful + FAlterRoutineName := editName.Text; + FAlterRoutineType := ProcOrFunc; + Mainform.SetEditorTabCaption(Self, FAlterRoutineName); + Mainform.actRefresh.Execute; + Modified := False; end; procedure TfrmRoutineEditor.SetModified(Value: Boolean); begin FModified := Value; - btnOK.Enabled := FModified; - btnApply.Enabled := FModified; + btnSave.Enabled := FModified; + btnDiscard.Enabled := FModified; +end; + + +procedure TfrmRoutineEditor.btnDiscardClick(Sender: TObject); +begin + Init(FAlterRoutineName, FAlterRoutineType); end; diff --git a/source/selectdbobject.pas b/source/selectdbobject.pas index 6f4f050e..b43f64c0 100644 --- a/source/selectdbobject.pas +++ b/source/selectdbobject.pas @@ -171,9 +171,9 @@ begin ds := Mainform.FetchDbTableList(Mainform.Databases[Node.Parent.Index]); ds.RecNo := Node.Index+1; case GetDBObjectType(ds.Fields) of - NODETYPE_CRASHED_TABLE: ImageIndex := ICONINDEX_CRASHED_TABLE; - NODETYPE_TABLE: ImageIndex := ICONINDEX_TABLE; - NODETYPE_VIEW: ImageIndex := ICONINDEX_VIEW; + lntCrashedTable: ImageIndex := ICONINDEX_CRASHED_TABLE; + lntTable: ImageIndex := ICONINDEX_TABLE; + lntView: ImageIndex := ICONINDEX_VIEW; end; end; 2: ImageIndex := ICONINDEX_FIELD; diff --git a/source/table_editor.dfm b/source/table_editor.dfm index e71bcb01..7c9c3ac5 100644 --- a/source/table_editor.dfm +++ b/source/table_editor.dfm @@ -1,84 +1,62 @@ object frmTableEditor: TfrmTableEditor Left = 0 Top = 0 - Caption = 'Table editor' - ClientHeight = 412 - ClientWidth = 598 - Color = clBtnFace + Width = 607 + Height = 391 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False - Position = poMainFormCenter - OnClose = FormClose - OnCreate = FormCreate - OnDestroy = FormDestroy - OnShow = FormShow + ParentFont = False + TabOrder = 0 DesignSize = ( - 598 - 412) - PixelsPerInch = 96 - TextHeight = 13 + 607 + 391) object SplitterTopBottom: TSplitter AlignWithMargins = True - Left = 8 - Top = 158 - Width = 582 + Left = 3 + Top = 153 + Width = 601 Height = 8 Cursor = crSizeNS - Margins.Left = 8 Margins.Top = 0 - Margins.Right = 8 Margins.Bottom = 0 Align = alTop ResizeStyle = rsUpdate end object lblStatus: TLabel - Left = 104 - Top = 384 + Left = 246 + Top = 367 Width = 41 Height = 13 Anchors = [akLeft, akBottom] Caption = 'lblStatus' end - object btnApply: TButton - Left = 515 - Top = 379 + object btnSave: TButton + Left = 165 + Top = 362 Width = 75 Height = 25 - Anchors = [akRight, akBottom] - Caption = 'Apply' - TabOrder = 6 - OnClick = btnApplyClick - end - object btnCancel: TButton - Left = 434 - Top = 379 - Width = 75 - Height = 25 - Anchors = [akRight, akBottom] - Cancel = True - Caption = 'Cancel' - ModalResult = 2 - TabOrder = 5 - end - object btnOK: TButton - Left = 353 - Top = 379 - Width = 75 - Height = 25 - Anchors = [akRight, akBottom] - Caption = 'OK' + Anchors = [akLeft, akBottom] + Caption = 'Save' Default = True - ModalResult = 1 + TabOrder = 5 + OnClick = btnSaveClick + end + object btnDiscard: TButton + Left = 84 + Top = 362 + Width = 75 + Height = 25 + Anchors = [akLeft, akBottom] + Caption = 'Discard' TabOrder = 4 - OnClick = btnApplyClick + OnClick = btnDiscardClick end object btnHelp: TButton - Left = 8 - Top = 379 + Left = 3 + Top = 362 Width = 75 Height = 25 Anchors = [akLeft, akBottom] @@ -88,17 +66,15 @@ object frmTableEditor: TfrmTableEditor end object listColumns: TVirtualStringTree AlignWithMargins = True - Left = 8 - Top = 196 - Width = 582 - Height = 176 - Margins.Left = 8 - Margins.Top = 8 - Margins.Right = 8 - Margins.Bottom = 40 + Left = 3 + Top = 186 + Width = 601 + Height = 173 + Margins.Bottom = 32 Align = alClient + BottomSpace = 60 CheckImageKind = ckSystem - Constraints.MinHeight = 50 + Constraints.MinHeight = 4 DragMode = dmAutomatic Header.AutoSizeIndex = -1 Header.DefaultHeight = 17 @@ -188,18 +164,15 @@ object frmTableEditor: TfrmTableEditor end object PageControlMain: TPageControl AlignWithMargins = True - Left = 8 - Top = 8 - Width = 582 + Left = 3 + Top = 3 + Width = 601 Height = 150 - Margins.Left = 8 - Margins.Top = 8 - Margins.Right = 8 Margins.Bottom = 0 - ActivePage = tabBasic + ActivePage = tabSQLCode Align = alTop Constraints.MinHeight = 150 - Constraints.MinWidth = 500 + Constraints.MinWidth = 304 Images = MainForm.PngImageListMain TabOrder = 0 OnChange = PageControlMainChange @@ -207,7 +180,7 @@ object frmTableEditor: TfrmTableEditor Caption = 'Basic' ImageIndex = 14 DesignSize = ( - 574 + 593 121) object lblName: TLabel Left = 4 @@ -224,9 +197,9 @@ object frmTableEditor: TfrmTableEditor Caption = 'Comment:' end object editName: TTntEdit - Left = 123 + Left = 72 Top = 3 - Width = 448 + Width = 520 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 0 @@ -234,10 +207,10 @@ object frmTableEditor: TfrmTableEditor OnChange = editNameChange end object memoComment: TTntMemo - Left = 123 + Left = 72 Top = 30 - Width = 448 - Height = 83 + Width = 520 + Height = 87 Anchors = [akLeft, akTop, akRight, akBottom] Lines.Strings = ( 'memoComment') @@ -250,7 +223,7 @@ object frmTableEditor: TfrmTableEditor Caption = 'Options' ImageIndex = 39 DesignSize = ( - 574 + 593 121) object lblAutoinc: TLabel Left = 4 @@ -347,7 +320,7 @@ object frmTableEditor: TfrmTableEditor object memoUnionTables: TTntMemo Left = 354 Top = 49 - Width = 217 + Width = 238 Height = 44 Anchors = [akLeft, akTop, akRight] Lines.Strings = ( @@ -358,7 +331,7 @@ object frmTableEditor: TfrmTableEditor object comboInsertMethod: TComboBox Left = 354 Top = 95 - Width = 217 + Width = 238 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -377,7 +350,7 @@ object frmTableEditor: TfrmTableEditor object comboCollation: TComboBox Left = 354 Top = 3 - Width = 104 + Width = 119 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -389,7 +362,7 @@ object frmTableEditor: TfrmTableEditor object comboEngine: TComboBox Left = 354 Top = 26 - Width = 217 + Width = 238 Height = 21 Style = csDropDownList Anchors = [akLeft, akTop, akRight] @@ -399,7 +372,7 @@ object frmTableEditor: TfrmTableEditor OnSelect = comboEngineSelect end object chkCharsetConvert: TCheckBox - Left = 464 + Left = 481 Top = 5 Width = 107 Height = 17 @@ -413,13 +386,13 @@ object frmTableEditor: TfrmTableEditor Caption = 'Indexes' ImageIndex = 13 DesignSize = ( - 574 + 593 121) object treeIndexes: TVirtualStringTree Left = 75 Top = 3 - Width = 251 - Height = 110 + Width = 300 + Height = 114 Anchors = [akLeft, akTop, akRight, akBottom] DragMode = dmAutomatic EditDelay = 0 @@ -453,7 +426,7 @@ object frmTableEditor: TfrmTableEditor item Options = [coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible, coAllowFocus] Position = 0 - Width = 151 + Width = 196 WideText = 'Name' end item @@ -522,10 +495,10 @@ object frmTableEditor: TfrmTableEditor end end object StaticText1: TStaticText - Left = 341 + Left = 381 Top = 25 - Width = 221 - Height = 39 + Width = 188 + Height = 66 Anchors = [akTop, akRight] AutoSize = False Caption = @@ -540,7 +513,7 @@ object frmTableEditor: TfrmTableEditor object SynMemoSQLcode: TSynMemo Left = 0 Top = 0 - Width = 574 + Width = 593 Height = 121 SingleLineMode = False Align = alClient @@ -568,13 +541,11 @@ object frmTableEditor: TfrmTableEditor end object pnlColumnsTop: TPanel AlignWithMargins = True - Left = 8 - Top = 166 - Width = 582 + Left = 3 + Top = 161 + Width = 601 Height = 22 - Margins.Left = 8 Margins.Top = 0 - Margins.Right = 8 Margins.Bottom = 0 Align = alTop Alignment = taLeftJustify @@ -638,8 +609,8 @@ object frmTableEditor: TfrmTableEditor end object popupIndexes: TPopupMenu Images = MainForm.PngImageListMain - Left = 296 - Top = 376 + Left = 344 + Top = 360 object menuAddIndex: TMenuItem Caption = 'Add index' ImageIndex = 45 @@ -679,8 +650,8 @@ object frmTableEditor: TfrmTableEditor end object popupColumns: TPopupMenu Images = MainForm.PngImageListMain - Left = 264 - Top = 376 + Left = 312 + Top = 360 object menuAddColumn: TMenuItem Caption = 'Add column' ImageIndex = 45 diff --git a/source/table_editor.pas b/source/table_editor.pas index b1bc0396..55075378 100644 --- a/source/table_editor.pas +++ b/source/table_editor.pas @@ -8,10 +8,9 @@ uses SynRegExpr, ActiveX, DB, ExtCtrls, ImgList, SynEdit, SynMemo, Menus; type - TfrmTableEditor = class(TForm) - btnApply: TButton; - btnCancel: TButton; - btnOK: TButton; + TfrmTableEditor = class(TFrame) + btnSave: TButton; + btnDiscard: TButton; btnHelp: TButton; listColumns: TVirtualStringTree; PageControlMain: TPageControl; @@ -72,8 +71,6 @@ type menuMoveUpColumn: TMenuItem; menuMoveDownColumn: TMenuItem; chkCharsetConvert: TCheckBox; - procedure FormCreate(Sender: TObject); - procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure editNameChange(Sender: TObject); procedure Modification(Sender: TObject); procedure btnAddColumnClick(Sender: TObject); @@ -84,11 +81,9 @@ type procedure btnHelpClick(Sender: TObject); procedure listColumnsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); - procedure FormShow(Sender: TObject); procedure listColumnsEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean); procedure listColumnsNewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; NewText: WideString); procedure btnMoveUpColumnClick(Sender: TObject); - procedure FormDestroy(Sender: TObject); procedure btnMoveDownColumnClick(Sender: TObject); procedure listColumnsDragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode; var Effect: Integer; var Accept: Boolean); @@ -105,7 +100,7 @@ type procedure treeIndexesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); procedure btnClearIndexesClick(Sender: TObject); - procedure btnApplyClick(Sender: TObject); + procedure btnSaveClick(Sender: TObject); procedure editNumEditChange(Sender: TObject); procedure comboEngineSelect(Sender: TObject); procedure listColumnsClick(Sender: TObject); @@ -130,10 +125,12 @@ type procedure PageControlMainChange(Sender: TObject); procedure chkCharsetConvertClick(Sender: TObject); procedure treeIndexesClick(Sender: TObject); + procedure btnDiscardClick(Sender: TObject); private { Private declarations } FModified: Boolean; FLoaded: Boolean; + FAlterTableName: WideString; SQLCodeValid: Boolean; Columns, ColumnsChanges, Indexes, OldIndexes: TWideStringList; @@ -154,7 +151,9 @@ type procedure UpdateSQLcode; public { Public declarations } - AlterTableName: WideString; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Init(AlterTableName: WideString=''); end; @@ -175,13 +174,13 @@ const {$R *.dfm} -procedure TfrmTableEditor.FormCreate(Sender: TObject); +constructor TfrmTableEditor.Create(AOwner: TComponent); begin - // Restore form dimensions - Width := GetRegValue(REGNAME_TABLEEDITOR_WIDTH, Width); - Height := GetRegValue(REGNAME_TABLEEDITOR_HEIGHT, Height); + inherited Create(AOwner); + // Do not set alClient via DFM! In conjunction with ExplicitXXX properties that + // repeatedly breaks the GUI layout when you reload the project + Align := alClient; PageControlMain.Height := GetRegValue(REGNAME_TABLEEDITOR_TABSHEIGHT, PageControlMain.Height); - SetWindowSizeGrip(Handle, True); InheritFont(Font); FixVT(listColumns); FixVT(treeIndexes); @@ -202,19 +201,18 @@ begin end; -procedure TfrmTableEditor.FormDestroy(Sender: TObject); +destructor TfrmTableEditor.Destroy; begin - // Store form dimensions + // Store GUI setup OpenRegistry; - MainReg.WriteInteger(REGNAME_TABLEEDITOR_WIDTH, Width); - MainReg.WriteInteger(REGNAME_TABLEEDITOR_HEIGHT, Height); MainReg.WriteInteger(REGNAME_TABLEEDITOR_TABSHEIGHT, PageControlMain.Height); Mainform.SaveListSetup(listColumns); Mainform.SaveListSetup(treeIndexes); + Inherited; end; -procedure TfrmTableEditor.FormShow(Sender: TObject); +procedure TfrmTableEditor.Init(AlterTableName: WideString=''); var ds: TDataset; Props: TWideStringlist; @@ -223,15 +221,20 @@ var rx: TRegExpr; begin SetStatus('Initializing ...'); - // Always start with "basic" tab activated - PageControlMain.ActivePage := tabBasic; + // Start with "basic" tab activated when just called + if FAlterTableName <> AlterTableName then + PageControlMain.ActivePage := tabBasic; Mainform.TableEnginesCombo(comboEngine); comboCollation.Items.Clear; Mainform.GetCollations(comboCollation.Items); + FAlterTableName := AlterTableName; + btnClearColumnsClick(Self); + btnClearIndexesClick(Self); - if AlterTableName = '' then begin + if FAlterTableName = '' then begin // Creating new table editName.Clear; + Mainform.SetEditorTabCaption(Self, ''); memoComment.Text := ''; editAutoInc.Text := ''; editAvgRowLen.Text := ''; @@ -243,12 +246,12 @@ begin comboInsertMethod.ItemIndex := -1; PageControlMain.ActivePage := tabBasic; - editName.SetFocus; end else begin // Editing existing table - editName.Text := AlterTableName; - ds := Mainform.GetResults('SHOW TABLE STATUS LIKE '+esc(AlterTableName)); + editName.Text := FAlterTableName; + Mainform.SetEditorTabCaption(Self, FAlterTableName); + ds := Mainform.GetResults('SHOW TABLE STATUS LIKE '+esc(FAlterTableName)); memoComment.Text := ds.FieldByName(DBO_COMMENT).AsWideString; if ds.FindField(DBO_ENGINE) <> nil then engine := ds.FieldByName(DBO_ENGINE).AsString @@ -261,7 +264,7 @@ begin editAvgRowLen.Text := ds.FieldByName(DBO_AVGROWLEN).AsString; comboRowFormat.ItemIndex := comboRowFormat.Items.IndexOf(ds.FieldByName(DBO_ROWFORMAT).AsString); FreeAndNil(ds); - CreateTable := Mainform.GetVar('SHOW CREATE TABLE '+Mainform.mask(AlterTableName), 1); + CreateTable := Mainform.GetVar('SHOW CREATE TABLE '+Mainform.mask(FAlterTableName), 1); rx := TRegExpr.Create; rx.ModifierI := True; rx.Expression := '\bUNION=\((.+)\)'; @@ -271,7 +274,8 @@ begin memoUnionTables.Clear; FreeAndNil(rx); - ds := Mainform.GetResults('SHOW FULL COLUMNS FROM '+Mainform.mask(AlterTableName)); + ds := Mainform.GetResults('SHOW FULL COLUMNS FROM '+Mainform.mask(FAlterTableName)); + listColumns.BeginUpdate; while not ds.Eof do begin Props := TWideStringlist.Create; Props.OnChange := ColumnsChange; @@ -299,8 +303,9 @@ begin ds.Next; end; FreeAndNil(ds); + listColumns.EndUpdate; - ds := Mainform.GetResults('SHOW KEYS FROM '+Mainform.mask(AlterTableName)); + ds := Mainform.GetResults('SHOW KEYS FROM '+Mainform.mask(FAlterTableName)); LastKeyName := ''; Props := nil; while not ds.Eof do begin @@ -326,48 +331,53 @@ begin end; // Validate controls - ColumnsChange(Sender); + ColumnsChange(Self); comboEngineSelect(comboEngine); ValidateColumnControls; ValidateIndexControls; ResetModificationFlags; - // Indicate change mechanisms can call their events now. See Modification(). + // Indicate change mechanisms can call their events now. See Modification(). FLoaded := True; // Empty status label SetStatus; end; -procedure TfrmTableEditor.btnApplyClick(Sender: TObject); +procedure TfrmTableEditor.btnDiscardClick(Sender: TObject); +begin + // Reinit GUI, discarding changes + Init(FAlterTableName); +end; + + +procedure TfrmTableEditor.btnSaveClick(Sender: TObject); var sql: WideString; i: Integer; Props: TWideStringlist; begin // Create or alter table - if AlterTableName = '' then + if FAlterTableName = '' then sql := ComposeCreateStatement else sql := ComposeAlterStatement; - try - Mainform.ExecUpdateQuery(sql, False, True); - // Set table name for altering if Apply was clicked - AlterTableName := editName.Text; - if chkCharsetConvert.Checked then begin - // Autoadjust column collations - for i:=0 to Columns.Count-1 do begin - Props := TWideStringlist(Columns.Objects[i]); - if Props[6] <> '' then begin - Props.OnChange := nil; - Props[6] := comboCollation.Text; - Props.OnChange := ColumnsChange; - end; + Mainform.ExecUpdateQuery(sql); + // Set table name for altering if Apply was clicked + FAlterTableName := editName.Text; + Mainform.SetEditorTabCaption(Self, FAlterTableName); + Mainform.tabData.TabVisible := True; + if chkCharsetConvert.Checked then begin + // Autoadjust column collations + for i:=0 to Columns.Count-1 do begin + Props := TWideStringlist(Columns.Objects[i]); + if Props[6] <> '' then begin + Props.OnChange := nil; + Props[6] := comboCollation.Text; + Props.OnChange := ColumnsChange; end; end; - ResetModificationFlags; - except - ModalResult := mrNone; end; + ResetModificationFlags; end; @@ -398,16 +408,6 @@ begin end; -procedure TfrmTableEditor.FormClose(Sender: TObject; var Action: TCloseAction); -begin - // Reset edited table name for the next call - AlterTableName := ''; - FLoaded := False; - btnClearColumnsClick(Sender); - btnClearIndexesClick(Sender); -end; - - function TfrmTableEditor.ComposeAlterStatement: WideString; var Specs, Props, IndexesComposed, OldIndexesComposed: TWideStringlist; @@ -421,7 +421,7 @@ begin // Compose ALTER query, called by buttons and for SQL code tab SetStatus('Composing ALTER statement ...'); Specs := TWideStringlist.Create; - if editName.Text <> AlterTableName then + if editName.Text <> FAlterTableName then Specs.Add('RENAME TO ' + Mainform.mask(editName.Text)); if memoComment.Tag = ModifiedFlag then Specs.Add('COMMENT = ' + esc(memoComment.Text)); @@ -532,7 +532,7 @@ begin Specs.Add('ADD '+IndexesComposed[i]); end; - Result := 'ALTER TABLE '+Mainform.mask(AlterTableName) + CRLF + #9 + ImplodeStr(',' + CRLF + #9, Specs); + Result := 'ALTER TABLE '+Mainform.mask(FAlterTableName) + CRLF + #9 + ImplodeStr(',' + CRLF + #9, Specs); FreeAndNil(Specs); FreeAndNil(IndexesComposed); FreeAndNil(OldIndexesComposed); @@ -1010,8 +1010,8 @@ procedure TfrmTableEditor.SetModified(Value: Boolean); begin // Some value has changed FModified := Value; - btnOK.Enabled := FModified; - btnApply.Enabled := FModified; + btnSave.Enabled := FModified; + btnDiscard.Enabled := FModified; SQLCodeValid := False; UpdateSQLcode; end; @@ -1491,7 +1491,7 @@ begin if (PageControlMain.ActivePage = tabSQLCode) and (not SQLCodeValid) then begin SynMemoSQLcode.BeginUpdate; OldTopLine := SynMemoSQLcode.TopLine; - if AlterTableName <> '' then + if FAlterTableName <> '' then SynMemoSQLcode.Text := ComposeAlterStatement else SynMemoSQLcode.Text := ComposeCreateStatement; @@ -1508,7 +1508,7 @@ begin listColumns.Header.Columns[8].Color := clBtnFace else listColumns.Header.Columns[8].Color := clWindow; - chkCharsetConvert.Enabled := (AlterTablename <> '') and (comboCollation.ItemIndex > -1); + chkCharsetConvert.Enabled := (FAlterTablename <> '') and (comboCollation.ItemIndex > -1); listColumns.Repaint; Modification(Sender); end; diff --git a/source/usermanager.pas b/source/usermanager.pas index 206571e2..ae27b489 100644 --- a/source/usermanager.pas +++ b/source/usermanager.pas @@ -6,7 +6,7 @@ interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, CheckLst, ExtCtrls, Buttons, DB, - ToolWin, TntCheckLst, WideStrings, WideStrUtils; + ToolWin, TntCheckLst, WideStrings, WideStrUtils, helpers; {$I const.inc} @@ -14,7 +14,7 @@ uses type TPrivilege = class(TObject) private - FDBOType: Byte; + FDBOType: TListNodeType; // Internal Flags FDeleted: Boolean; FAdded: Boolean; @@ -28,7 +28,7 @@ type SelectedPrivNames: TWideStringList; constructor Create(Fields: TFields; FieldDefs: TDataset = nil; AvoidFieldDefs: TDataSet = nil; CropFieldDefs: TDataSet = nil; SimulateDbField: Boolean = False); procedure Merge(Fields: TFields); - property DBOType: Byte read FDBOType; + property DBOType: TListNodeType read FDBOType; property DBOKey: String read GetDBOKey; property DBOPrettyKey: String read GetDBOPrettyKey; property PrettyPrivNames: TWideStringList read GetPrettyPrivNames; @@ -202,13 +202,13 @@ type { Public declarations } end; -procedure GetPrivilegeRowKey(Fields: TFields; SimulateDbField: Boolean; out DBOType: Byte; out DBONames: TWideStringList); +procedure GetPrivilegeRowKey(Fields: TFields; SimulateDbField: Boolean; out DBOType: TListNodeType; out DBONames: TWideStringList); implementation uses - main, helpers, selectdbobject; + main, selectdbobject; var @@ -448,11 +448,11 @@ begin for i := 0 to u.Privileges.Count - 1 do begin Icon := -1; case u.Privileges[i].DBOType of - NODETYPE_DEFAULT: Icon := ICONINDEX_SERVER; - NODETYPE_DB: Icon := ICONINDEX_DB; - NODETYPE_TABLE: Icon := ICONINDEX_TABLE; - NODETYPE_VIEW: Icon := ICONINDEX_VIEW; - NODETYPE_COLUMN: Icon := ICONINDEX_FIELD; + lntNone: Icon := ICONINDEX_SERVER; + lntDb: Icon := ICONINDEX_DB; + lntTable: Icon := ICONINDEX_TABLE; + lntView: Icon := ICONINDEX_VIEW; + lntColumn: Icon := ICONINDEX_FIELD; end; pname := u.Privileges[i].DBOPrettyKey; if u.Privileges[i].Deleted then begin @@ -585,7 +585,7 @@ begin for i := 0 to priv.PrivNames.Count - 1 do begin boxPrivs.Checked[i] := priv.SelectedPrivNames.IndexOf(priv.PrivNames[i]) > -1; end; - EnableDelete := (priv.DBOType <> NODETYPE_DEFAULT) and + EnableDelete := (priv.DBOType <> lntNone) and (priv.DBOKey <> '%') and (not priv.Deleted); end; if comboUsers.ItemIndex > -1 then @@ -1058,28 +1058,28 @@ begin // Go. LogSQL('Applying privilege to account ' + u.Name + '@' + u.Host + ' for ' + p.DBOPrettyKey + '.'); case p.DBOType of - NODETYPE_DEFAULT: begin + lntNone: begin TableSet := dsUser; TableName := mask(PRIVTABLE_USERS); SetFieldName := ''; end; - NODETYPE_DB: begin + lntDb: begin TableSet := dsDb; TableName := mask(PRIVTABLE_DB); SetFieldName := ''; end; - NODETYPE_TABLE: begin + lntTable: begin TableSet := dsTables; TableName := mask(PRIVTABLE_TABLES); SetFieldName := 'table_priv'; end; - NODETYPE_COLUMN: begin + lntColumn: begin TableSet := dsColumns; TableName := mask(PRIVTABLE_COLUMNS); SetFieldName := 'column_priv'; end; else begin - raise Exception.Create('Processed privilege has an undefined db object type: ' + IntToStr(p.DBOType)); + raise Exception.Create('Processed privilege has an undefined db object type: ' + IntToStr(Integer(p.DBOType))); end; end; // Deduce a key for this privilege definition, appropriate for DELETE. @@ -1092,7 +1092,7 @@ begin end; end; // Special case: remove redundant privileges in mysql.user. - if (p.DBOType = NODETYPE_DB) and (p.DBOKey = '%') then begin + if (p.DBOType = lntDb) and (p.DBOKey = '%') then begin PrivUpdates.Clear; for k := 0 to p.PrivNames.Count - 1 do begin if dsUser.FindField(p.PrivNames[k] + '_priv') <> nil then @@ -1103,7 +1103,7 @@ begin Exec(sql + AcctWhere); end; // Remove old privilege definition. - if (p.DBOType <> NODETYPE_DEFAULT) then begin + if (p.DBOType <> lntNone) then begin sql := 'DELETE FROM ' + db + '.' + TableName; Exec(sql + AcctWhere + PrivWhere); end else begin @@ -1150,7 +1150,7 @@ begin PrivUpdates.Add(mask(SetFieldName) + '=' + esc(Delim(PrivValues, False))); sql := sql + ' SET ' + PrivWhere + ', ' + Delim(PrivUpdates); // Special case: UPDATE instead of INSERT for server-level privileges (see further above). - if (p.DBOType = NODETYPE_DEFAULT) then begin + if (p.DBOType = lntNone) then begin // Server barfs if we do not set missing defaults, sigh. PrivValues.Clear; if dsUser.FindField('ssl_cipher') <> nil then @@ -1166,7 +1166,7 @@ begin end; Exec(sql); // Special case: update redundant column privileges in mysql.tables_priv. - if (p.DBOType = NODETYPE_COLUMN) and (dsTables.FindField('column_priv') <> nil) then begin + if (p.DBOType = lntColumn) and (dsTables.FindField('column_priv') <> nil) then begin // We need to deduce a completely new key because column_priv in mysql.tables_priv does not have a column field next to it, sigh. PrivUpdates.Clear; PrivUpdates.Add(mask('Host') + '=' + esc(u.Host)); @@ -1471,7 +1471,7 @@ end; function TPrivileges.FindPrivilege(Fields: TFields; SimulateDbField: Boolean): TPrivilege; var i : Integer; - DBOType: Byte; + DBOType: TListNodeType; DBONames: TWideStringList; begin Result := nil; @@ -1493,7 +1493,7 @@ begin SetLength(FPrivilegeItems, Length(FPrivilegeItems)+1); FPrivilegeItems[Length(FPrivilegeItems)-1] := Result; // Minimum default privs for a new user should be read only for everything, or? - if FOwner.Added and (Result.FDBOType = NODETYPE_DB) and (Result.DBOKey = '%') then begin + if FOwner.Added and (Result.FDBOType = lntDb) and (Result.DBOKey = '%') then begin Result.SelectedPrivNames.Add('Select'); Result.Modified := True; end; @@ -1629,14 +1629,14 @@ function TPrivilege.GetDBOPrettyKey: String; begin Result := ''; case FDBOType of - NODETYPE_DEFAULT: Result := Result + 'Server privileges'; - NODETYPE_DB: Result := Result + 'Database: '; - NODETYPE_TABLE: Result := Result + 'Table: '; - NODETYPE_COLUMN: Result := Result + 'Column: '; + lntNone: Result := Result + 'Server privileges'; + lntDb: Result := Result + 'Database: '; + lntTable: Result := Result + 'Table: '; + lntColumn: Result := Result + 'Column: '; end; Result := Result + GetDBOKey; // Special case "db=%" - if (FDBOType = NODETYPE_DB) and (DBOKey = '%') then + if (FDBOType = lntDb) and (DBOKey = '%') then Result := 'All databases'; end; @@ -1663,25 +1663,25 @@ begin end; -procedure GetPrivilegeRowKey(Fields: TFields; SimulateDbField: Boolean; out DBOType: Byte; out DBONames: TWideStringList); +procedure GetPrivilegeRowKey(Fields: TFields; SimulateDbField: Boolean; out DBOType: TListNodeType; out DBONames: TWideStringList); begin - DBOType := NODETYPE_DEFAULT; + DBOType := lntNone; DBONames := TWideStringList.Create; DBONames.Delimiter := '.'; if SimulateDbField then begin - DBOType := NODETYPE_DB; + DBOType := lntDb; DBONames.Add('%'); end; if Fields.FindField('Db') <> nil then begin - DBOType := NODETYPE_DB; + DBOType := lntDb; DBONames.Add(Fields.FieldByName('Db').AsString); end; if Fields.FindField('Table_name') <> nil then begin - DBOType := NODETYPE_TABLE; + DBOType := lntTable; DBONames.Add(Fields.FieldByName('Table_name').AsString); end; if Fields.FindField('Column_name') <> nil then begin - DBOType := NODETYPE_COLUMN; + DBOType := lntColumn; DBONames.Add(Fields.FieldByName('Column_name').AsString); end; end; diff --git a/source/view.dfm b/source/view.dfm index 987e4f05..2425d4cc 100644 --- a/source/view.dfm +++ b/source/view.dfm @@ -1,46 +1,38 @@ object frmView: TfrmView Left = 0 Top = 0 - BorderIcons = [biSystemMenu, biMaximize] - Caption = 'frmView' - ClientHeight = 275 - ClientWidth = 422 - Color = clBtnFace - Constraints.MinHeight = 250 - Constraints.MinWidth = 360 + Width = 451 + Height = 304 + Constraints.MinHeight = 240 + Constraints.MinWidth = 320 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False - Position = poOwnerFormCenter - OnCreate = FormCreate - OnDestroy = FormDestroy - OnShow = FormShow + ParentFont = False + TabOrder = 0 DesignSize = ( - 422 - 275) - PixelsPerInch = 96 - TextHeight = 13 + 451 + 304) object lblName: TLabel - Left = 8 - Top = 8 + Left = 3 + Top = 6 Width = 31 Height = 13 Caption = 'Name:' end object lblSelect: TLabel - Left = 8 + Left = 3 Top = 124 Width = 85 Height = 13 Caption = 'Select statement:' end object editName: TEdit - Left = 45 - Top = 5 - Width = 371 + Left = 42 + Top = 3 + Width = 405 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 0 @@ -48,9 +40,9 @@ object frmView: TfrmView OnChange = editNameChange end object rgAlgorithm: TRadioGroup - Left = 8 + Left = 3 Top = 32 - Width = 201 + Width = 206 Height = 86 Caption = 'Algorithm' ItemIndex = 0 @@ -61,10 +53,10 @@ object frmView: TfrmView TabOrder = 1 end object SynMemoSelect: TSynMemo - Left = 8 + Left = 3 Top = 143 - Width = 408 - Height = 95 + Width = 444 + Height = 128 SingleLineMode = False Anchors = [akLeft, akTop, akRight, akBottom] Font.Charset = DEFAULT_CHARSET @@ -97,33 +89,32 @@ object frmView: TfrmView ShortCut = 16473 end> end - object btnCancel: TButton - Left = 341 - Top = 244 + object btnDiscard: TButton + Left = 84 + Top = 276 Width = 75 Height = 25 - Anchors = [akRight, akBottom] + Anchors = [akLeft, akBottom] Cancel = True - Caption = 'Cancel' - ModalResult = 2 + Caption = 'Discard' TabOrder = 3 + OnClick = btnDiscardClick end - object btnOK: TButton - Left = 260 - Top = 244 + object btnSave: TButton + Left = 162 + Top = 276 Width = 75 Height = 25 - Anchors = [akRight, akBottom] - Caption = 'OK' + Anchors = [akLeft, akBottom] + Caption = 'Save' Default = True - ModalResult = 1 TabOrder = 4 - OnClick = btnOKClick + OnClick = btnSaveClick end object rgCheck: TRadioGroup Left = 215 Top = 32 - Width = 201 + Width = 232 Height = 86 Anchors = [akLeft, akTop, akRight] Caption = 'Check option for updates' @@ -135,8 +126,8 @@ object frmView: TfrmView TabOrder = 5 end object btnHelp: TButton - Left = 8 - Top = 244 + Left = 3 + Top = 276 Width = 75 Height = 25 Anchors = [akLeft, akBottom] diff --git a/source/view.pas b/source/view.pas index a506983f..3a86c7b6 100644 --- a/source/view.pas +++ b/source/view.pas @@ -7,27 +7,27 @@ uses Dialogs, StdCtrls, ComCtrls, SynEdit, SynMemo, ExtCtrls, DB, SynRegExpr; type - TfrmView = class(TForm) + TfrmView = class(TFrame) editName: TEdit; lblName: TLabel; rgAlgorithm: TRadioGroup; SynMemoSelect: TSynMemo; lblSelect: TLabel; - btnCancel: TButton; - btnOK: TButton; + btnDiscard: TButton; + btnSave: TButton; rgCheck: TRadioGroup; btnHelp: TButton; procedure btnHelpClick(Sender: TObject); - procedure btnOKClick(Sender: TObject); + procedure btnSaveClick(Sender: TObject); procedure editNameChange(Sender: TObject); - procedure FormDestroy(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormShow(Sender: TObject); + procedure btnDiscardClick(Sender: TObject); private { Private declarations } + FEditViewName: WideString; public { Public declarations } - EditViewName: String; + constructor Create(AOwner: TComponent); override; + procedure Init(EditViewName: WideString=''); end; @@ -39,49 +39,37 @@ uses main, helpers; {** - FormCreate: Restore GUI setup + Create: Restore GUI setup } -procedure TfrmView.FormCreate(Sender: TObject); +constructor TfrmView.Create(AOwner: TComponent); begin - Width := GetRegValue(REGNAME_VIEWWINWIDTH, Width); - Height := GetRegValue(REGNAME_VIEWWINHEIGHT, Height); + inherited Create(AOwner); + Align := alClient; SynMemoSelect.Highlighter := Mainform.SynSQLSyn1; SynMemoSelect.Font := Mainform.SynMemoQuery.Font; - SetWindowSizeGrip( Self.Handle, True ); InheritFont(Font); end; -{** - FormDestroy: Save GUI setup -} -procedure TfrmView.FormDestroy(Sender: TObject); -begin - OpenRegistry; - MainReg.WriteInteger( REGNAME_VIEWWINWIDTH, Width ); - MainReg.WriteInteger( REGNAME_VIEWWINHEIGHT, Height ); - Close; -end; - - {** FormShow: Fill controls with content in edit mode } -procedure TfrmView.FormShow(Sender: TObject); +procedure TfrmView.Init(EditViewName: WideString=''); var ds: TDataset; db: String; rx: TRegExpr; begin - if EditViewName <> '' then begin + FEditViewName := EditViewName; + if FEditViewName <> '' then begin // Edit mode - Caption := 'Edit view ...'; - editName.Text := EditViewName; + editName.Text := FEditViewName; + Mainform.SetEditorTabCaption(Self, FEditViewName); db := Mainform.ActiveDatabase; ds := Mainform.GetResults('SELECT * FROM '+Mainform.mask(DBNAME_INFORMATION_SCHEMA)+'.VIEWS ' + - 'WHERE TABLE_SCHEMA = '+esc(db)+' AND TABLE_NAME = '+esc(EditViewName)); + 'WHERE TABLE_SCHEMA = '+esc(db)+' AND TABLE_NAME = '+esc(FEditViewName)); if ds.RecordCount = 0 then - raise Exception.Create('Can''t find view definition for "'+EditViewName+'" in '+DBNAME_INFORMATION_SCHEMA); + raise Exception.Create('Can''t find view definition for "'+FEditViewName+'" in '+DBNAME_INFORMATION_SCHEMA); // Algorithm is not changeable as we cannot look up its current state! rgAlgorithm.Enabled := False; rgAlgorithm.ItemIndex := 0; @@ -96,7 +84,7 @@ begin rx.Free; end else begin // Create mode - Caption := 'Create view ...'; + Mainform.SetEditorTabCaption(Self, ''); editName.Text := 'myview'; rgAlgorithm.Enabled := True; rgAlgorithm.ItemIndex := 0; @@ -105,7 +93,7 @@ begin SynMemoSelect.Text := 'SELECT '; end; // Ensure name is validated - editNameChange(Sender); + editNameChange(Self); end; @@ -114,12 +102,12 @@ end; } procedure TfrmView.editNameChange(Sender: TObject); begin - btnOK.Enabled := False; + btnSave.Enabled := False; try ensureValidIdentifier( editName.Text ); editName.Font.Color := clWindowText; editName.Color := clWindow; - btnOK.Enabled := True; + btnSave.Enabled := True; except editName.Font.Color := clRed; editName.Color := clYellow; @@ -134,7 +122,7 @@ procedure TfrmView.btnHelpClick(Sender: TObject); var keyword: String; begin - if EditViewName = '' then + if FEditViewName = '' then keyword := 'CREATE VIEW' else keyword := 'ALTER VIEW'; @@ -142,20 +130,27 @@ begin end; +procedure TfrmView.btnDiscardClick(Sender: TObject); +begin + // Reinit editor, discarding changes + Init(FEditViewName); +end; + + {** Apply changes: Compose and execute SQL } -procedure TfrmView.btnOKClick(Sender: TObject); +procedure TfrmView.btnSaveClick(Sender: TObject); var sql, viewname, renamed: String; begin // Compose CREATE or ALTER statement - if EditViewName = '' then begin + if FEditViewName = '' then begin sql := 'CREATE '; viewname := editName.Text; end else begin sql := 'ALTER '; - viewname := EditViewName; + viewname := FEditViewName; end; viewname := Mainform.mask(viewname); if rgAlgorithm.Enabled and (rgAlgorithm.ItemIndex > -1) then @@ -165,20 +160,13 @@ begin sql := sql + 'WITH '+Uppercase(rgCheck.Items[rgCheck.ItemIndex])+' CHECK OPTION'; // Execute query and keep form open in any error case - try - Mainform.ExecUpdateQuery(sql); - // Probably rename view - if (EditViewName <> '') and (EditViewName <> editName.Text) then begin - renamed := Mainform.mask(editName.Text); - Mainform.ExecUpdateQuery('RENAME TABLE '+viewname + ' TO '+renamed); - end; - Mainform.RefreshTreeDB(Mainform.ActiveDatabase); - except - on E: THandledSQLError do begin - MessageDlg(E.Message, mtError, [mbOK], 0); - ModalResult := mrNone; - end; + Mainform.ExecUpdateQuery(sql); + // Probably rename view + if (FEditViewName <> '') and (FEditViewName <> editName.Text) then begin + renamed := Mainform.mask(editName.Text); + Mainform.ExecUpdateQuery('RENAME TABLE '+viewname + ' TO '+renamed); end; + Mainform.RefreshTreeDB(Mainform.ActiveDatabase); end;