////////////////////////////////////////////////////////////////////////// // // pgAdmin III - PostgreSQL Tools // // Copyright (C) 2002 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // frmQuery.cpp - SQL Query Box // ////////////////////////////////////////////////////////////////////////// #include "pgAdmin3.h" // wxWindows headers #include #include #include #include #include #include #include #include #include #include #include #include #include // App headers #include "frm/frmAbout.h" #include "frm/frmMain.h" #include "frm/frmQuery.h" #include "frm/menu.h" #include "ctl/explainCanvas.h" #include "db/pgConn.h" #include "ctl/ctlMenuToolbar.h" #include "ctl/ctlSQLResult.h" #include "dlg/dlgSelectConnection.h" #include "dlg/dlgAddFavourite.h" #include "dlg/dlgManageFavourites.h" #include "dlg/dlgManageMacros.h" #include "dlg/dlgFunction.h" #include "frm/frmReport.h" #include "gqb/gqbViewController.h" #include "gqb/gqbModel.h" #include "gqb/gqbViewPanels.h" #include "gqb/gqbEvents.h" #include "schema/pgDatabase.h" #include "schema/pgFunction.h" #include "schema/pgTable.h" #include "schema/pgForeignTable.h" #include "schema/pgView.h" #include "schema/gpExtTable.h" #include "schema/pgServer.h" #include "utils/favourites.h" #include "utils/sysLogger.h" #include "utils/sysSettings.h" #include "utils/utffile.h" #include "utils/misc.h" #include "pgscript/pgsApplication.h" #include "schema/pgPartition.h" #include "dlg/dlgVariable.h" // Icons #include "images/sql-32.pngc" // Bitmaps #include "images/file_new.pngc" #include "images/file_open.pngc" #include "images/file_save.pngc" #include "images/clip_cut.pngc" #include "images/clip_copy.pngc" #include "images/clip_paste.pngc" #include "images/edit_clear.pngc" #include "images/edit_find.pngc" #include "images/edit_undo.pngc" #include "images/edit_redo.pngc" #include "images/query_execute.pngc" #include "images/query_pgscript.pngc" #include "images/query_execfile.pngc" #include "images/query_explain.pngc" #include "images/query_cancel.pngc" #include "images/query_commit.pngc" #include "images/query_rollback.pngc" #include "images/mode_transaction.pngc" #include "images/mode_autocommit.pngc" #include "images/help.pngc" #include "images/gqbJoin.pngc" #include #define CTRLID_CONNECTION 4200 #define CTRLID_DATABASELABEL 4201 #define CTL_SQLQUERYBOOK 4202 #define CTL_BUTTONTRANSACTION 4203 #define XML_FROM_WXSTRING(s) ((const xmlChar *)(const char *)s.mb_str(wxConvUTF8)) #define WXSTRING_FROM_XML(s) wxString((char *)s, wxConvUTF8) #define XML_STR(s) ((const xmlChar *)s) extern wxString dataDir; // Initialize execution 'mutex'. As this will always run in the // main thread, there aren't any real concurrency issues, so // a simple flag will suffice. // Required because the pgScript parser isn't currently thread-safe :-( bool frmQuery::ms_pgScriptRunning = false; BEGIN_EVENT_TABLE(frmQuery, pgFrame) EVT_ERASE_BACKGROUND( frmQuery::OnEraseBackground) EVT_SIZE( frmQuery::OnSize) EVT_COMBOBOX(CTRLID_CONNECTION, frmQuery::OnChangeConnection) EVT_COMBOBOX(CTL_SQLQUERYCBOX, frmQuery::OnChangeQuery) EVT_CLOSE( frmQuery::OnClose) EVT_SET_FOCUS( frmQuery::OnSetFocus) EVT_MENU(MNU_NEW, frmQuery::OnNew) EVT_MENU(MNU_OPEN, frmQuery::OnOpen) EVT_MENU(MNU_SAVE, frmQuery::OnSave) EVT_MENU(MNU_SAVEAS, frmQuery::OnSaveAs) EVT_MENU(MNU_NEWSQLTAB, frmQuery::OnSqlBookAddPage) EVT_MENU(MNU_EXPORT, frmQuery::OnExport) EVT_MENU(MNU_SAVEAS_IMAGE_GQB, frmQuery::SaveExplainAsImage) EVT_MENU(MNU_SAVEAS_IMAGE_EXPLAIN, frmQuery::SaveExplainAsImage) EVT_MENU(MNU_EXIT, frmQuery::OnExit) EVT_MENU(MNU_CUT, frmQuery::OnCut) EVT_MENU(MNU_COPY, frmQuery::OnCopy) EVT_MENU(MNU_PASTE, frmQuery::OnPaste) EVT_MENU(MNU_CLEAR, frmQuery::OnClear) EVT_MENU(MNU_SUMMARY_COL, frmQuery::OnSummary_Column) EVT_MENU(MNU_COMPARE_2CELL, frmQuery::OnCompare_2Cell) EVT_MENU(MNU_COPY_INSERT, frmQuery::OnCopy_Insert) EVT_MENU(MNU_COPY_INLIST, frmQuery::OnCopy_InList) EVT_MENU(MNU_COPY_WHERELIST, frmQuery::OnCopy_WhereList) EVT_MENU(MNU_COPY_TABLEHTML, frmQuery::OnCopy_TableToHtml) EVT_MENU(MNU_CLEAR_FILTER, frmQuery::OnClear_Filter) EVT_MENU(MNU_CHECK_COLUMN_DATE, frmQuery::OnCheck_Column_Date) EVT_MENU(MNU_COPY_LISTCOLTYPE, frmQuery::OnCopy_NameTypeCols) EVT_MENU(MNU_AUTOCOLSPLOT, frmQuery::OnAutoColsPlot) EVT_MENU(MNU_FIND, frmQuery::OnSearchReplace) EVT_MENU(MNU_TRANSFORM, frmQuery::OnTransformText) EVT_MENU(MNU_UNDO, frmQuery::OnUndo) EVT_MENU(MNU_REDO, frmQuery::OnRedo) EVT_MENU(MNU_EXECUTE, frmQuery::OnExecute) EVT_MENU(MNU_EXECUTE_2, frmQuery::OnExecuteShift) EVT_MENU(MNU_EXECPGS, frmQuery::OnExecScript) EVT_MENU(MNU_EXECFILE, frmQuery::OnExecFile) EVT_MENU(MNU_EXPLAIN, frmQuery::OnExplain) EVT_MENU(MNU_EXPLAINANALYZE, frmQuery::OnExplain) EVT_MENU(MNU_DOCOMMIT, frmQuery::OnCommit) EVT_MENU(MNU_DOROLLBACK, frmQuery::OnRollback) EVT_MENU(MNU_CANCEL, frmQuery::OnCancel) EVT_MENU(MNU_AUTOSELECTQUERY, frmQuery::OnAutoSelectQuery) EVT_MENU(MNU_AUTOROLLBACK, frmQuery::OnAutoRollback) EVT_MENU(MNU_AUTOCOMMIT, frmQuery::OnAutoCommit) EVT_MENU(MNU_MODE_TRANSACTION, frmQuery::OnModeTransaction) EVT_MENU(MNU_CONTENTS, frmQuery::OnContents) EVT_MENU(MNU_HELP, frmQuery::OnHelp) EVT_MENU(MNU_CLEARHISTORY, frmQuery::OnClearHistory) EVT_MENU(MNU_SAVEHISTORY, frmQuery::OnSaveHistory) EVT_MENU(MNU_SELECTALL, frmQuery::OnSelectAll) EVT_MENU(MNU_QUICKREPORT, frmQuery::OnQuickReport) EVT_MENU(MNU_AUTOINDENT, frmQuery::OnAutoIndent) EVT_MENU(MNU_WORDWRAP, frmQuery::OnWordWrap) EVT_MENU(MNU_SHOWINDENTGUIDES, frmQuery::OnShowIndentGuides) EVT_MENU(MNU_SHOWWHITESPACE, frmQuery::OnShowWhitespace) EVT_MENU(MNU_SHOWLINEENDS, frmQuery::OnShowLineEnds) EVT_MENU(MNU_SHOWLINENUMBER, frmQuery::OnShowLineNumber) EVT_MENU(MNU_FAVOURITES_ADD, frmQuery::OnAddFavourite) EVT_MENU(MNU_FAVOURITES_INJECT, frmQuery::OnInjectFavourite) EVT_MENU(MNU_FAVOURITES_MANAGE, frmQuery::OnManageFavourites) EVT_MENU(MNU_MACROS_MANAGE, frmQuery::OnMacroManage) EVT_MENU(MNU_AUTOREPLACE_MANAGE,frmQuery::OnAutoReplaceManage) EVT_MENU(MNU_DATABASEBAR, frmQuery::OnToggleDatabaseBar) EVT_MENU(MNU_TOOLBAR, frmQuery::OnToggleToolBar) EVT_MENU(MNU_SCRATCHPAD, frmQuery::OnToggleScratchPad) EVT_MENU(MNU_OUTPUTPANE, frmQuery::OnToggleOutputPane) EVT_MENU(MNU_DEFAULTVIEW, frmQuery::OnDefaultView) EVT_MENU(MNU_BLOCK_INDENT, frmQuery::OnBlockIndent) EVT_MENU(MNU_BLOCK_OUTDENT, frmQuery::OnBlockOutDent) EVT_MENU(MNU_UPPER_CASE, frmQuery::OnChangeToUpperCase) EVT_MENU(MNU_LOWER_CASE, frmQuery::OnChangeToLowerCase) EVT_MENU(MNU_COMMENT_TEXT, frmQuery::OnCommentText) EVT_MENU(MNU_UNCOMMENT_TEXT, frmQuery::OnUncommentText) EVT_MENU(MNU_DOUBLEQUOTE_TEXT, frmQuery::OnDoubleText) EVT_MENU(MNU_UNDOUBLEQUOTE_TEXT,frmQuery::OnUnDoubleText) EVT_MENU(MNU_EXTERNALFORMAT, frmQuery::OnExternalFormat) EVT_MENU(MNU_EXTERNALALIGN, frmQuery::OnExternalAlign) EVT_MENU(MNU_LF, frmQuery::OnSetEOLMode) EVT_MENU(MNU_CRLF, frmQuery::OnSetEOLMode) EVT_MENU(MNU_CR, frmQuery::OnSetEOLMode) EVT_MENU(MNU_AUTOEDITOBJECT, frmQuery::OnAutoEditObject) EVT_MENU_RANGE(MNU_FAVOURITES_MANAGE + 1, MNU_FAVOURITES_MANAGE + 999, frmQuery::OnSelectFavourite) EVT_MENU_RANGE(MNU_MACROS_MANAGE + 1, MNU_MACROS_MANAGE + 99, frmQuery::OnMacroInvoke) EVT_MENU_RANGE(MNU_GENERATESQL + 1, MNU_GENERATESQL + 199, frmQuery::OnGenerateInvoke) EVT_ACTIVATE( frmQuery::OnActivate) EVT_STC_MODIFIED(CTL_SQLQUERY, frmQuery::OnChangeStc) EVT_STC_UPDATEUI(CTL_SQLQUERY, frmQuery::OnPositionStc) EVT_GRID_LABEL_RIGHT_CLICK( frmQuery::OnLabelRightClick) EVT_GRID_CELL_LEFT_DCLICK( frmQuery::OnCellLeftDClick) EVT_AUI_PANE_CLOSE( frmQuery::OnAuiUpdate) EVT_TIMER(CTL_TIMERSIZES, frmQuery::OnAdjustSizesTimer) EVT_TIMER(CTL_TIMERFRM, frmQuery::OnTimer) // These fire when the queries complete EVT_PGQUERYRESULT(QUERY_COMPLETE, frmQuery::OnQueryComplete) EVT_MENU(PGSCRIPT_COMPLETE, frmQuery::OnScriptComplete) EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_NTBKCENTER, frmQuery::OnChangeNotebook) EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_NTBKGQB, frmQuery::OnChangeNotebookOutpane) EVT_AUINOTEBOOK_TAB_RIGHT_DOWN(CTL_NTBKGQB, frmQuery::OnNotebookOutpaneTabRDown) EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageChanged) EVT_AUINOTEBOOK_PAGE_CHANGING(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageChanging) EVT_AUINOTEBOOK_PAGE_CLOSE(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageClose) EVT_AUINOTEBOOK_TAB_RIGHT_DOWN(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookTabRDown) EVT_AUINOTEBOOK_PAGE_CLOSED(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageClosed) EVT_SPLITTER_SASH_POS_CHANGED(GQB_HORZ_SASH, frmQuery::OnResizeHorizontally) EVT_BUTTON(CTL_DELETECURRENTBTN, frmQuery::OnDeleteCurrent) EVT_BUTTON(CTL_DELETEALLBTN, frmQuery::OnDeleteAll) EVT_BUTTON(CTL_BUTTONTRANSACTION,frmQuery::OnModeTransaction) END_EVENT_TABLE() class DnDFile : public wxFileDropTarget { public: DnDFile(frmQuery *fquery) { m_fquery = fquery; } virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) { size_t nFiles = filenames.GetCount(); if ((int) nFiles > 1) wxLogError(_("Drag one file at a time")); else if ((int) nFiles == 1) { wxString str; bool modeUnicode = settings->GetUnicodeFile(); wxUtfFile file(filenames[0], wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) file.Read(str); if (!str.IsEmpty() && !m_fquery->CheckChanged(true)) { m_fquery->SetLastPath(filenames[0]); m_fquery->SetQueryText(str); m_fquery->ColouriseQuery(0, str.Length()); wxSafeYield(); // needed to process sqlQuery modify event m_fquery->SetChanged(false); m_fquery->SetOrigin(ORIGIN_FILE); m_fquery->setExtendedTitle(); m_fquery->SetLineEndingStyle(); m_fquery->UpdateRecentFiles(true); m_fquery->UpdateAllRecentFiles(); } } return true; } private: frmQuery *m_fquery; }; void frmQuery::seticon() { wxString str; wxString filename; wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"icons"+wxFileName::GetPathSeparator(); wxString db = conn->GetDbname(); wxString host = conn->GetHostName(); wxString f = tempDir + host+"_"+db+wxT(".png"); if (!wxFileExists(f)) { f = tempDir + host + wxT(".png"); if (!wxFileExists(f)) { f = tempDir + db + wxT(".png"); if (!wxFileExists(f)) f = ""; } } if (f.empty()) { f = tempDir + host + "_" + db + wxT(".svg"); if (!wxFileExists(f)) { f = tempDir + host + wxT(".svg"); if (!wxFileExists(f)) { f = tempDir + db + wxT(".svg"); if (!wxFileExists(f)) f = ""; } } } while (!f.empty()) { wxIcon* ico = new wxIcon(); wxBitmapBundle bb = GetBundleSVG(NULL, f, wxSize(32, 32)); wxBitmap bitmap = bb.GetBitmap(wxSize(32, 32)); //wxBitmap bitmap(f, wxBITMAP_TYPE_PNG); if (!bitmap.Ok()) { wxMessageBox(wxT("Sorry, could not load png file.\n")+f); } ico->CopyFromBitmap(bitmap); //SetIcon(*sql_32_png_ico); SetIcon(*ico); delete ico; return; //f = wxFindNextFile(); } wxColor cl=GetServerColour(conn); int rgb = cl.GetRGB(); int b = (rgb >> 16) & 255; int g = (rgb >> 8) & 255; int r = rgb & 255; if (r == 255 && g == 255 && b == 255) { //SetBitmapBundle() SetIcon(*sql_32_png_ico); } else { wxImage img = *sql_32_png_img; int w = img.GetWidth(); int h = img.GetHeight(); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { if (img.IsTransparent(x, y)) img.SetRGB(x, y, r, g, b); } //wxIcon ico=img. wxIcon* ico = new wxIcon(); wxBitmap* bmp = new wxBitmap(img); ico->CopyFromBitmap(*bmp); //SetIcon(*sql_32_png_ico); SetIcon(*ico); delete ico; delete bmp; } } frmQuery::frmQuery(frmMain *form, const wxString &_title, pgConn *_conn, const wxString &query, const wxString &file) : pgFrame(NULL, _title), timer(this, CTL_TIMERFRM), pgScript(new pgsApplication(_conn)), pgsStringOutput(&pgsOutputString), pgsOutput(pgsStringOutput, wxEOL_UNIX), pgsTimer(new pgScriptTimer(this)), m_loadingfile(false) { pgScript->SetCaller(this, PGSCRIPT_COMPLETE); mainForm = form; conn = _conn; autoSave = settings->GetAutosaveQuery(); loading = true; closing = false; dlgName = wxT("frmQuery"); recentKey = wxT("RecentFiles"); RestorePosition(100, 100, 600, 500, 450, 300); wxLogInfo(wxT("frmQuery::Create window")); explainCanvas = NULL; // notify wxAUI which frame to use manager.SetManagedWindow(this); manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG); SetMinSize(FromDIP(wxSize(450, 300))); //seticon(); SetFont(settings->GetSystemFont()); menuBar = new wxMenuBar(); fileMenu = new wxMenu(); recentFileMenu = new wxMenu(); fileMenu->Append(MNU_NEW, _("&New window\tCtrl-N"), _("Open a new query window")); fileMenu->Append(MNU_OPEN, _("&Open...\tCtrl-O"), _("Open a query file")); fileMenu->Append(MNU_SAVE, _("&Save\tCtrl-S"), _("Save current file")); saveasImageMenu = new wxMenu(); saveasImageMenu->Append(MNU_SAVEAS, _("Query (text)"), _("Save file under new name")); saveasImageMenu->Append(MNU_SAVEAS_IMAGE_GQB, _("Graphical Query (image)"), _("Save Graphical Query as an image")); saveasImageMenu->Append(MNU_SAVEAS_IMAGE_EXPLAIN, _("Explain (image)"), _("Save output of Explain as an image")); fileMenu->Append(wxID_ANY, _("Save as"), saveasImageMenu); // SQL tabs related menu items fileMenu->AppendSeparator(); fileMenu->Append(MNU_NEWSQLTAB, _("New SQL &tab\tCtrl-T"), _("Open a new query tab")); fileMenu->AppendSeparator(); fileMenu->Append(MNU_EXPORT, _("&Export...\tAlt+E"), _("Export data to file")); fileMenu->Append(MNU_QUICKREPORT, _("&Quick report..."), _("Run a quick report...")); fileMenu->AppendSeparator(); fileMenu->Append(MNU_RECENT, _("&Recent files"), recentFileMenu); fileMenu->Append(MNU_EXIT, _("E&xit\tCtrl-W"), _("Exit query window")); menuBar->Append(fileMenu, _("&File")); lineEndMenu = new wxMenu(); lineEndMenu->AppendRadioItem(MNU_LF, _("Unix (LF)"), _("Use Unix style line endings")); lineEndMenu->AppendRadioItem(MNU_CRLF, _("DOS (CRLF)"), _("Use DOS style line endings")); lineEndMenu->AppendRadioItem(MNU_CR, _("Mac (CR)"), _("Use Mac style line endings")); editMenu = new wxMenu(); editMenu->Append(MNU_UNDO, _("&Undo\tCtrl-Z"), _("Undo last action"), wxITEM_NORMAL); editMenu->Append(MNU_REDO, _("&Redo\tCtrl-Y"), _("Redo last action"), wxITEM_NORMAL); editMenu->AppendSeparator(); editMenu->Append(MNU_CUT, _("Cu&t\tCtrl-X"), _("Cut selected text to clipboard"), wxITEM_NORMAL); editMenu->Append(MNU_COPY, _("&Copy\tCtrl-C"), _("Copy selected text to clipboard"), wxITEM_NORMAL); editMenu->Append(MNU_PASTE, _("&Paste\tCtrl-V"), _("Paste selected text from clipboard"), wxITEM_NORMAL); editMenu->Append(MNU_CLEAR, _("C&lear window"), _("Clear edit window"), wxITEM_NORMAL); editMenu->AppendSeparator(); editMenu->Append(MNU_FIND, _("&Find and Replace\tCtrl-F"), _("Find and replace text"), wxITEM_NORMAL); editMenu->AppendSeparator(); editMenu->Append(MNU_AUTOINDENT, _("&Auto indent"), _("Automatically indent text to the same level as the preceding line"), wxITEM_CHECK); // editMenu->AppendSeparator(); formatMenu = new wxMenu(); formatMenu->Append(MNU_UPPER_CASE, _("&Upper case\tCtrl-U"), _("Change the selected text to upper case")); formatMenu->Append(MNU_LOWER_CASE, _("&Lower case\tCtrl-Shift-U"), _("Change the selected text to lower case")); formatMenu->AppendSeparator(); formatMenu->Append(MNU_BLOCK_INDENT, _("Block &Indent\tTab"), _("Indent the selected block")); formatMenu->Append(MNU_BLOCK_OUTDENT, _("Block &Outdent\tShift-Tab"), _("Outdent the selected block")); formatMenu->Append(MNU_COMMENT_TEXT, _("Co&mment Text\tCtrl-K"), _("Comment out the selected text")); formatMenu->Append(MNU_UNCOMMENT_TEXT, _("Uncomme&nt Text\tCtrl-Shift-K"), _("Uncomment the selected text")); formatMenu->Append(MNU_DOUBLEQUOTE_TEXT, _("Double the single quote\tCtrl-'"), _("Double the single quote")); formatMenu->Append(MNU_UNDOUBLEQUOTE_TEXT, _("Undouble the single quote\tCtrl-Shift-'"), _("Undouble the single quote")); formatMenu->AppendSeparator(); formatMenu->Append(MNU_EXTERNALFORMAT, _("External Format\tCtrl-Shift-F"), _("Call external formatting command")); formatMenu->Append(MNU_EXTERNALALIGN, _("External Align...\tCtrl-Shift-A"), _("Call external align command")); editMenu->AppendSubMenu(formatMenu, _("F&ormat")); editMenu->Append(MNU_LINEENDS, _("&Line ends"), lineEndMenu); editMenu->Append(MNU_AUTOREPLACE_MANAGE, _("Manage autoreplace..."), _("Edit and delete autoreplace strings")); editMenu->Append(MNU_AUTOEDITOBJECT, _("Open object\tF4"), _("Open object in brouser tree")); editMenu->Append(MNU_TRANSFORM, _("Text transform...\tCtrl+M"), _("Open dialog transform")); autoreplace = queryMacroFileProvider::LoadAutoReplace(true); menuBar->Append(editMenu, _("&Edit")); queryMenu = new wxMenu(); queryMenu->Append(MNU_EXECUTE, _("&Execute\tF8"), _("Execute query")); queryMenu->Append(MNU_EXECUTE_2, _("&Execute new output\tShift-F8"), _("Execute query in new output")); queryMenu->Append(MNU_EXECPGS, _("Execute &pgScript\tF6"), _("Execute pgScript")); queryMenu->Append(MNU_EXECFILE, _("Execute to file\tF5"), _("Execute query, write result to file")); queryMenu->Append(MNU_EXPLAIN, _("E&xplain\tF7"), _("Explain query")); queryMenu->Append(MNU_EXPLAINANALYZE, _("Explain analyze\tShift-F7"), _("Explain and analyze query")); wxMenu *eo = new wxMenu(); eo->Append(MNU_VERBOSE, _("Verbose"), _("Explain verbose query"), wxITEM_CHECK); eo->Append(MNU_COSTS, _("Costs"), _("Explain analyze query with (or without) costs"), wxITEM_CHECK); eo->Append(MNU_BUFFERS, _("Buffers"), _("Explain analyze query with (or without) buffers"), wxITEM_CHECK); eo->Append(MNU_TIMING, _("Timing"), _("Explain analyze query with (or without) timing"), wxITEM_CHECK); queryMenu->Append(MNU_EXPLAINOPTIONS, _("Explain &options"), eo, _("Options modifying Explain output")); queryMenu->AppendSeparator(); queryMenu->Append(MNU_SAVEHISTORY, _("Save history"), _("Save history of executed commands.")); queryMenu->Append(MNU_CLEARHISTORY, _("Clear history"), _("Clear history window.")); queryMenu->AppendSeparator(); queryMenu->Append(MNU_AUTOSELECTQUERY, _("&Auto-Select"), _("Auto select query"), wxITEM_CHECK); queryMenu->Append(MNU_AUTOROLLBACK, _("&Auto-Rollback"), _("Rollback the current transaction if an error is detected"), wxITEM_CHECK); queryMenu->Append(MNU_AUTOCOMMIT, _("&Auto-Commit"), _("Auto commit the cuurent transaction"), wxITEM_CHECK); queryMenu->AppendSeparator(); queryMenu->Append(MNU_CANCEL, _("&Cancel\tAlt-Break"), _("Cancel query")); queryMenu->AppendSeparator(); queryMenu->Append(MNU_DOCOMMIT, _("Commit\tF10"), _("Commit")); queryMenu->Append(MNU_DOROLLBACK, _("Rollback\tShift-F10"), _("Rollback")); menuBar->Append(queryMenu, _("&Query")); favouritesMenu = new wxMenu(); favouritesMenu->Append(MNU_FAVOURITES_ADD, _("Add favourite..."), _("Add current query to favourites")); favouritesMenu->Append(MNU_FAVOURITES_INJECT, _("Inject\tF2"), _("Replace a word under cursor with a favourite with same name")); favouritesMenu->Append(MNU_FAVOURITES_MANAGE, _("Manage favourites..."), _("Edit and delete favourites")); favouritesMenu->AppendSeparator(); favourites = 0L; UpdateFavouritesList(); menuBar->Append(favouritesMenu, _("Fav&ourites")); macrosMenu = new wxMenu(); macrosMenu->Append(MNU_MACROS_MANAGE, _("Manage macros..."), _("Edit and delete macros")); macrosMenu->AppendSeparator(); macros = 0L; UpdateMacrosList(); menuBar->Append(macrosMenu, _("&Macros")); // View menu viewMenu = new wxMenu(); viewMenu->Append(MNU_DATABASEBAR, _("&Connection bar\tCtrl-Alt-B"), _("Show or hide the database selection bar."), wxITEM_CHECK); viewMenu->Append(MNU_OUTPUTPANE, _("&Output pane\tCtrl-Alt-O"), _("Show or hide the output pane."), wxITEM_CHECK); viewMenu->Append(MNU_SCRATCHPAD, _("S&cratch pad\tCtrl-Alt-S"), _("Show or hide the scratch pad."), wxITEM_CHECK); viewMenu->Append(MNU_TOOLBAR, _("&Tool bar\tCtrl-Alt-T"), _("Show or hide the tool bar."), wxITEM_CHECK); viewMenu->AppendSeparator(); viewMenu->Append(MNU_SHOWINDENTGUIDES, _("&Indent guides"), _("Enable or disable display of indent guides"), wxITEM_CHECK); viewMenu->Append(MNU_SHOWLINEENDS, _("&Line ends"), _("Enable or disable display of line ends"), wxITEM_CHECK); viewMenu->Append(MNU_SHOWWHITESPACE, _("&Whitespace"), _("Enable or disable display of whitespaces"), wxITEM_CHECK); viewMenu->Append(MNU_WORDWRAP, _("&Word wrap"), _("Enable or disable word wrapping"), wxITEM_CHECK); viewMenu->Append(MNU_SHOWLINENUMBER, _("&Line number"), _("Enable or disable display of line number"), wxITEM_CHECK); viewMenu->AppendSeparator(); viewMenu->Append(MNU_DEFAULTVIEW, _("&Default view\tCtrl-Alt-V"), _("Restore the default view.")); menuBar->Append(viewMenu, _("&View")); wxMenu *helpMenu = new wxMenu(); helpMenu->Append(MNU_CONTENTS, _("&Help"), _("Open the helpfile.")); helpMenu->Append(MNU_HELP, _("&SQL Help\tF1"), _("Display help on SQL commands.")); #ifdef __WXMAC__ menuFactories = new menuFactoryList(); aboutFactory *af = new aboutFactory(menuFactories, helpMenu, 0); wxApp::s_macAboutMenuItemId = af->GetId(); menuFactories->RegisterMenu(this, wxCommandEventHandler(pgFrame::OnAction)); #endif menuBar->Append(helpMenu, _("&Help")); SetMenuBar(menuBar); queryMenu->Check(MNU_VERBOSE, settings->GetExplainVerbose()); queryMenu->Check(MNU_COSTS, settings->GetExplainCosts()); queryMenu->Check(MNU_BUFFERS, settings->GetExplainBuffers()); queryMenu->Check(MNU_TIMING, settings->GetExplainTiming()); UpdateRecentFiles(); #define USER_KEY_DEF 15 wxAcceleratorEntry entries[16+ USER_KEY_DEF]; std::map mapping; mapping["MNU_EXECFILE"] = MNU_EXECFILE; mapping["MNU_EXECPGS"] = MNU_EXECPGS; mapping["MNU_EXECUTE"] = MNU_EXECUTE; mapping["MNU_EXECUTE_2"] = MNU_EXECUTE_2; mapping["MNU_EXPLAIN"] = MNU_EXPLAIN; mapping["MNU_NEWSQLTAB"] = MNU_NEWSQLTAB; mapping["MNU_EXPLAINANALYZE"] = MNU_EXPLAINANALYZE; mapping["MNU_EXIT"] = MNU_EXIT; mapping["MNU_EXPORT"] = MNU_EXPORT; mapping["MNU_EXTERNALFORMAT"] = MNU_EXTERNALFORMAT; mapping["MNU_COMMENT_TEXT"] = MNU_COMMENT_TEXT; mapping["MNU_UNCOMMENT_TEXT"] = MNU_UNCOMMENT_TEXT; mapping["MNU_DOROLLBACK"] = MNU_DOROLLBACK; mapping["MNU_DOCOMMIT"] = MNU_DOCOMMIT; wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"keymap.txt"; wxLogInfo(wxT("frmQuery::Create key map ...")); int idx = 0; if (wxFileName::FileExists(tempDir) ) { wxUtfFile filer(tempDir, wxFile::read, wxFONTENCODING_UTF8); filer.IsOpened(); wxString str = ""; filer.Read(str); filer.Close(); #ifdef WIN32 wxStringTokenizer tk(str, "\n\r", wxTOKEN_DEFAULT); #else wxStringTokenizer tk(str, "\n", wxTOKEN_DEFAULT); #endif int d = 0; while (tk.HasMoreTokens()) { d++; wxString l = tk.GetNextToken(); wxString mnu = l.BeforeFirst(' '); wxString cmdkey = l.AfterLast(' '); if (l.IsEmpty()) continue; if (idx >= (USER_KEY_DEF)) break; int imnu = 0; auto f = mapping.find(std::string(mnu.mb_str())); if (f== mapping.end()) { std::string s=""; for (auto& t : mapping) s += t.first + ","; wxLogError(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%s] bad menu name. Possible value(%s) "), d, mnu,wxString(s) ); continue; } imnu = f->second; if (entries[idx].FromString(cmdkey)) { entries[idx].Set(entries[idx].GetFlags(), entries[idx].GetKeyCode(), imnu); wxLogInfo(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%d] key=[%s] "), d, imnu, entries[idx].ToString()); } else { wxLogError(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%s] key=[%s] bad key. Ignore this line"), d, mnu, cmdkey); continue; } idx++; } } entries[idx++].Set(wxACCEL_CTRL, (int)'E', MNU_EXECUTE); entries[idx++].Set(wxACCEL_CTRL, (int)'O', MNU_OPEN); entries[idx++].Set(wxACCEL_CTRL, (int)'S', MNU_SAVE); entries[idx++].Set(wxACCEL_CTRL, (int)'F', MNU_FIND); entries[idx++].Set(wxACCEL_CTRL, (int)'R', MNU_REPLACE); entries[idx++].Set(wxACCEL_NORMAL, WXK_F8, MNU_EXECUTE); entries[idx++].Set(wxACCEL_NORMAL, WXK_F7, MNU_EXPLAIN); entries[idx++].Set(wxACCEL_ALT, WXK_PAUSE, MNU_CANCEL); entries[idx++].Set(wxACCEL_CTRL, (int)'A', MNU_SELECTALL); entries[idx++].Set(wxACCEL_NORMAL, WXK_F1, MNU_HELP); entries[idx++].Set(wxACCEL_CTRL, (int)'N', MNU_NEW); entries[idx++].Set(wxACCEL_NORMAL, WXK_F6, MNU_EXECPGS); entries[idx++].Set(wxACCEL_NORMAL, WXK_F5, MNU_EXECFILE); entries[idx++].Set(wxACCEL_CTRL, (int)'T', MNU_NEWSQLTAB); entries[idx++].Set(wxACCEL_CTRL, (int)'1', MNU_GENERATESQL+1); entries[idx++].Set(wxACCEL_CTRL, (int)'2', MNU_GENERATESQL+2); wxAcceleratorTable accel(idx, entries); SetAcceleratorTable(accel); wxLogInfo(wxT("frmQuery::Create key map Ok")); queryMenu->Enable(MNU_CANCEL, false); int iWidths[7] = {0, -1, 40, 250, 80, 80, 80}; statusBar = CreateStatusBar(7); SetStatusBarPane(-1); SetStatusWidths(7, iWidths); SetStatusText(_("ready"), STATUSPOS_MSGS); toolBar = new ctlMenuToolbar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_NODIVIDER); wxSize tbsz((32), (32)); toolBar->SetToolBitmapSize(FromDIP(wxSize(32, 32))); wxLogInfo(wxT("frmQuery::Create tool bar ..")); toolBar->AddTool(MNU_NEWSQLTAB, wxEmptyString, GetBundleSVG(file_new_png_bmp, "file_new.svg", tbsz), _("New SQL tab"), wxITEM_NORMAL); toolBar->AddTool(MNU_OPEN, wxEmptyString, GetBundleSVG(file_open_png_bmp, "file_open.svg", tbsz) , _("Open file"), wxITEM_NORMAL); toolBar->AddTool(MNU_SAVE, wxEmptyString, GetBundleSVG(file_save_png_bmp, "file_save.svg", tbsz) , _("Save file"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_CUT, wxEmptyString, GetBundleSVG(clip_cut_png_bmp, "clip_cut.svg", tbsz) , _("Cut selected text to clipboard"), wxITEM_NORMAL); toolBar->AddTool(MNU_COPY, wxEmptyString, GetBundleSVG(clip_copy_png_bmp, "clip_copy.svg", tbsz), _("Copy selected text to clipboard"), wxITEM_NORMAL); toolBar->AddTool(MNU_PASTE, wxEmptyString, GetBundleSVG(clip_paste_png_bmp, "clip_paste.svg", tbsz), _("Paste selected text from clipboard"), wxITEM_NORMAL); toolBar->AddTool(MNU_CLEAR, wxEmptyString, GetBundleSVG(edit_clear_png_bmp, "edit_clear.svg", tbsz), _("Clear edit window"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_UNDO, wxEmptyString, GetBundleSVG(edit_undo_png_bmp, "edit_undo.svg", tbsz), _("Undo last action"), wxITEM_NORMAL); toolBar->AddTool(MNU_REDO, wxEmptyString, GetBundleSVG(edit_redo_png_bmp, "edit_redo.svg", tbsz), _("Redo last action"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_FIND, wxEmptyString, GetBundleSVG(edit_find_png_bmp, "edit_find.svg", tbsz), _("Find and replace text"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_EXECUTE, wxEmptyString, GetBundleSVG(query_execute_png_bmp, "query_execute.svg", tbsz), _("Execute query"), wxITEM_NORMAL); toolBar->AddTool(MNU_EXECPGS, wxEmptyString, GetBundleSVG(query_pgscript_png_bmp, "query_pgscript.svg", tbsz), _("Execute pgScript"), wxITEM_NORMAL); toolBar->AddTool(MNU_EXECFILE, wxEmptyString, GetBundleSVG(query_execfile_png_bmp, "query_execfile.svg", tbsz), _("Execute query, write result to file"), wxITEM_NORMAL); toolBar->AddTool(MNU_EXPLAIN, wxEmptyString, GetBundleSVG(query_explain_png_bmp, "query_explain.svg", tbsz), _("Explain query"), wxITEM_NORMAL); toolBar->AddTool(MNU_CANCEL, wxEmptyString, GetBundleSVG(query_cancel_png_bmp, "query_cancel.svg", tbsz), _("Cancel query"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_DOCOMMIT, wxEmptyString, GetBundleSVG(query_commit_png_bmp, "query_commit.svg", tbsz), _("Commit"), wxITEM_NORMAL); toolBar->AddTool(MNU_DOROLLBACK, wxEmptyString, GetBundleSVG(query_rollback_png_bmp, "query_rollback.svg", tbsz), _("Rollback"), wxITEM_NORMAL); bool chk = settings->GetAutoCommit(); mode_a = GetBundleSVG(mode_autocommit_png_bmp, "mode_autocommit.svg", tbsz); mode_t = GetBundleSVG(mode_transaction_png_bmp, "mode_transaction.svg", tbsz); if (chk) toolBar->AddTool(MNU_MODE_TRANSACTION, wxEmptyString, mode_a, _("Mode transaction"), wxITEM_NORMAL); else toolBar->AddTool(MNU_MODE_TRANSACTION, wxEmptyString, mode_t, _("Mode transaction"), wxITEM_NORMAL); toolBar->AddSeparator(); toolBar->AddTool(MNU_HELP, wxEmptyString, GetBundleSVG(help_png_bmp, "help.svg", tbsz), _("Display help on SQL commands."), wxITEM_NORMAL); toolBar->Realize(); wxLogInfo(wxT("frmQuery::Create tool bar Ok")); wxSize toolw = toolBar->GetBestSize(); // Add the database selection bar cbConnection = new wxBitmapComboBox(this, CTRLID_CONNECTION, wxEmptyString, wxDefaultPosition, wxSize(-1, -1), wxArrayString(), wxCB_READONLY | wxCB_DROPDOWN); cbConnection->Append(conn->GetName(), CreateBitmap(GetServerColour(conn)), (void *)conn); cbConnection->Append(_(""), wxNullBitmap, (void *) NULL); //Create SQL editor notebook sqlNotebook = new ctlAuiNotebook(this, CTL_NTBKCENTER, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON); // Create panel for query wxPanel *pnlQuery = new wxPanel(sqlNotebook); // Create the outer box sizer wxBoxSizer *boxQuery = new wxBoxSizer(wxVERTICAL); // Create the inner box sizer // This one will contain the label, the combobox, and the two buttons wxBoxSizer *boxHistory = new wxBoxSizer(wxHORIZONTAL); // Label wxStaticText *label = new wxStaticText(pnlQuery, 0, _("Previous queries")); boxHistory->Add(label, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1); // Query combobox sqlQueries = new wxComboBox(pnlQuery, CTL_SQLQUERYCBOX, wxT(""), wxDefaultPosition, wxDefaultSize, wxArrayString(), wxCB_DROPDOWN | wxCB_READONLY); sqlQueries->SetToolTip(_("Previous queries")); LoadQueries(); boxHistory->Add(sqlQueries, 1, wxEXPAND | wxALL , 1); // Delete Current button btnDeleteCurrent = new wxButton(pnlQuery, CTL_DELETECURRENTBTN, _("Delete")); btnDeleteCurrent->Enable(false); boxHistory->Add(btnDeleteCurrent, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1); // Delete All button btnDeleteAll = new wxButton(pnlQuery, CTL_DELETEALLBTN, _("Delete All")); btnDeleteAll->Enable(sqlQueries->GetCount() > 0); boxHistory->Add(btnDeleteAll, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1); boxQuery->Add(boxHistory, 0, wxEXPAND | wxALL, 1); boxHistory->ShowItems(!settings->GetHideQueryHistory()); // Create the other inner box sizer // This one will contain the SQL box wxBoxSizer *boxSQL = new wxBoxSizer(wxHORIZONTAL); // Use sqlQueryBook instead of sqlQuery and put the book inside boxSQL sizer. // We don't add any SQL tabs until all menu items are initialized from settings. sqlQueryBook = new ctlAuiNotebook(pnlQuery, CTL_SQLQUERYBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_CLOSE_ON_ACTIVE_TAB | wxAUI_NB_WINDOWLIST_BUTTON); sqlQueryCounter = 0; sqlQueryExec = NULL; sqlQueryExecLast = NULL; boxSQL->Add(sqlQueryBook, 1, wxEXPAND | wxRIGHT | wxLEFT | wxBOTTOM, 1); boxQuery->Add(boxSQL, 1, wxEXPAND | wxRIGHT | wxLEFT | wxBOTTOM, 1); // Auto-sizing pnlQuery->SetSizer(boxQuery); boxQuery->Fit(pnlQuery); // Results pane outputPane = new ctlAuiNotebook(this, CTL_NTBKGQB, wxDefaultPosition, wxSize(500, 300), wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON); sqlResult = new ctlSQLResult(outputPane, conn, CTL_SQLRESULT, wxDefaultPosition, wxDefaultSize); int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]); for (int i=0;iSetFont(settings->GetSQLFont()); msgHistory = new wxTextCtrl(outputPane, CTL_MSGHISTORY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); msgHistory->SetFont(settings->GetSQLFont()); // Graphical Canvas // initialize values model = new gqbModel(); controller = new gqbController(model, sqlNotebook, outputPane, wxSize(GQB_MIN_WIDTH, GQB_MIN_HEIGHT)); firstTime = true; // Inform to GQB that the tree of table haven't filled. gqbUpdateRunning = false; // Are we already updating the SQL query - event recursion protection. adjustSizesTimer = NULL; // Timer used to avoid a bug when close outputPane // Setup SQL editor notebook NBP_SQLEDTR sqlNotebook->AddPage(pnlQuery, _("SQL Editor")); sqlNotebook->AddPage(controller->getViewContainer(), _("Graphical Query Builder")); sqlNotebook->SetSelection(0); outputPane->AddPage(sqlResult, _("Data Output")); outputPane->AddPage(explainCanvas, _("Explain")); outputPane->AddPage(msgResult, _("Messages")); outputPane->AddPage(msgHistory, _("History")); sqlResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); msgResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); msgHistory->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); // Now, the scratchpad scratchPad = new wxTextCtrl(this, CTL_SCRATCHPAD, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxHSCROLL); wxSize w1 = cbConnection->GetBestSize(); // Kickstart wxAUI manager.AddPane(toolBar, wxAuiPaneInfo().Name(wxT("toolBar")).Caption(_("Tool bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false)); manager.AddPane(cbConnection, wxAuiPaneInfo().Name(wxT("databaseBar")).Caption(_("Connection bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false)); manager.AddPane(outputPane, wxAuiPaneInfo().Name(wxT("outputPane")).Caption(_("Output pane")).Bottom().MinSize(wxSize(200, 100)).BestSize(wxSize(550, 300))); manager.AddPane(scratchPad, wxAuiPaneInfo().Name(wxT("scratchPad")).Caption(_("Scratch pad")).Right().MinSize(wxSize(100, 100)).BestSize(wxSize(250, 200))); manager.AddPane(sqlNotebook, wxAuiPaneInfo().Name(wxT("sqlQuery")).Caption(_("SQL query")).Center().CaptionVisible(false).CloseButton(false).MinSize(wxSize(200, 100)).BestSize(wxSize(350, 200))); // Now load the layout wxString perspective; settings->Read(wxT("frmQuery/Perspective-") + wxString(FRMQUERY_PERSPECTIVE_VER), &perspective, FRMQUERY_DEFAULT_PERSPECTIVE); manager.LoadPerspective(perspective, true); outputPaneInfo = manager.SavePerspective(); // and reset the captions for the current language manager.GetPane(wxT("toolBar")).Caption(_("Tool bar")); manager.GetPane(wxT("databaseBar")).BestSize(w1); manager.GetPane(wxT("toolBar")).BestSize(toolw); manager.GetPane(wxT("databaseBar")).Caption(_("Connection bar")); manager.GetPane(wxT("sqlQuery")).Caption(_("SQL query")); manager.GetPane(wxT("outputPane")).Caption(_("Output pane")); manager.GetPane(wxT("scratchPad")).Caption(_("Scratch pad")); // Sync the View menu options viewMenu->Check(MNU_DATABASEBAR, manager.GetPane(wxT("databaseBar")).IsShown()); viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown()); viewMenu->Check(MNU_OUTPUTPANE, manager.GetPane(wxT("outputPane")).IsShown()); viewMenu->Check(MNU_SCRATCHPAD, manager.GetPane(wxT("scratchPad")).IsShown()); wxAuiPaneInfo &pn = manager.GetPane(wxT("outputPane")); if (!pn.HasMaximizeButton()) { pn.MaximizeButton(true); } // tell the manager to "commit" all the changes just made manager.Update(); bool bVal; // Auto-Select bVal = settings->GetAutoSelectQuery(); queryMenu->Check(MNU_AUTOSELECTQUERY, bVal); // Auto-rollback bVal = settings->GetAutoRollback(); queryMenu->Check(MNU_AUTOROLLBACK, bVal); // Auto-commit bVal = settings->GetAutoCommit(); queryMenu->Check(MNU_AUTOCOMMIT, bVal); // Auto indent settings->Read(wxT("frmQuery/AutoIndent"), &bVal, true); editMenu->Check(MNU_AUTOINDENT, bVal); // Word wrap settings->Read(wxT("frmQuery/WordWrap"), &bVal, false); viewMenu->Check(MNU_WORDWRAP, bVal); // Indent Guides settings->Read(wxT("frmQuery/ShowIndentGuides"), &bVal, false); viewMenu->Check(MNU_SHOWINDENTGUIDES, bVal); // Whitespace settings->Read(wxT("frmQuery/ShowWhitespace"), &bVal, false); viewMenu->Check(MNU_SHOWWHITESPACE, bVal); // Line ends settings->Read(wxT("frmQuery/ShowLineEnds"), &bVal, false); viewMenu->Check(MNU_SHOWLINEENDS, bVal); // Line number settings->Read(wxT("frmQuery/ShowLineNumber"), &bVal, false); viewMenu->Check(MNU_SHOWLINENUMBER, bVal); // Create the SQL box. After this, sqlQuery variable can be used. if (!file.IsEmpty() && wxFileName::FileExists(file)) { wxString t = wxEmptyString; SqlBookAddPage(t); wxFileName fn = file; lastFilename = fn.GetFullName(); lastDir = fn.GetPath(); lastPath = fn.GetFullPath(); OpenLastFile(); sqlQuery->Colourise(0, sqlQuery->GetLength()); } else if (!query.IsNull()) { wxString t = wxEmptyString; SqlBookAddPage(t); sqlQuery->SetText(query); SetLineEndingStyle(); sqlQuery->Colourise(0, sqlQuery->GetLength()); wxSafeYield(); // needed to process sqlQuery modify event sqlQuery->SetChanged(false); sqlQuery->SetOrigin(ORIGIN_INITIAL); /* _title if not empty should contain displayName of base object for the query. It's pretty good for a proposed filename if the user chooses to Save As. */ lastFilename = _title; setExtendedTitle(); SqlBookUpdatePageTitle(); } else { // load temp file wxString str; wxString filename; tempDir = dataDir; if (!wxDirExists(tempDir)) { wxMkdir(tempDir); } tempDir=tempDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); if (!wxDirExists(tempDir)) { wxMkdir(tempDir); } wxString pref=_conn->GetDbname(); bool modeUnicode = settings->GetUnicodeFile(); wxArrayString activePage; wxString f = wxFindFirstFile(tempDir + wxT("*.a")); while (!f.empty()) { if (autoSave) { filename = f.AfterLast(sepPath).BeforeLast('.'); if (filename.BeforeFirst('.') == "_active") { activePage.Add(filename.AfterFirst('.')); wxLogInfo(wxT("frmQuery::_active file marker: name=[%s] pref=[%s]"), filename.AfterFirst('.'), pref); } } else { wxRemoveFile(f); } f = wxFindNextFile(); } f = wxFindFirstFile(tempDir+wxT("*.a")); while ( !f.empty() ) { filename=f.AfterLast(sepPath).BeforeLast('.'); if ((f.AfterLast(sepPath).StartsWith(pref+wxT("."))||(filename.BeforeLast('.').IsEmpty()))) { wxUtfFile file(f, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { file.Read(str); file.Close(); } if (!str.IsEmpty()) { wxString fline=str.BeforeFirst('@'); int l=fline.Length(); if (fline.Find('\n')>=0) l=0; long nl=0; if (l>0) fline.ToLong(&nl); if (l>0) { fline=str.Mid(l+1); str=fline; } SqlBookAddPage(filename); //SqlBookAddPage(true); sqlQuery->SetText(str); sqlQuery->Colourise(0, sqlQuery->GetLength()); sqlQuery->EmptyUndoBuffer(); sqlQuery->GotoPos(nl); //wxSafeYield(); // needed to process sqlQuery modify event sqlQuery->SetOrigin(ORIGIN_INITIAL); sqlQuery->SetChanged(false); setExtendedTitle(); SqlBookUpdatePageTitle(); SaveTempFile(); wxLogInfo(wxT("frmQuery::Create tab name=[%s]"), filename); } } f = wxFindNextFile(); } wxString t = wxEmptyString; if (sqlQueryCounter==0) SqlBookAddPage(t); if (!activePage.IsEmpty()) { //activePage //outputPane->GetPageText(curpage) == _("History"); int ii = -1; for (int i = 0; i < sqlQueryBook->GetPageCount(); i++) { wxString textpage = sqlQueryBook->GetPageText(i); if (wxNOT_FOUND !=activePage.Index(textpage)) { if (textpage.BeforeFirst('.') == pref) { ii = i; break; } else ii = i; //sqlQueryBook->ChangeSelection(i); //if (sqlQueryBook->GetSelection()!=i) sqlQueryBook->SetSelection(i); } } if (ii!=-1) sqlQueryBook->SetSelection(ii); //wxLogInfo(wxT("frmQuery::select tab: name=[%s] index=[%d]"), sqlQueryBook->GetPageText(ii), ii); } //for (int i=1;i<15;i++) //{ //filename=wxString::Format(_("Query %i"), i); //if (!wxFileName::FileExists(tempDir+filename)) continue; //wxUtfFile file(tempDir+filename, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); //if (file.IsOpened()) //{ file.Read(str); file.Close(); } ////QFile::remove(tempDir+wxT("\\")+filename); //wxRemoveFile(tempDir+filename); //if (!str.IsEmpty()) //{ // sqlQuery->SetText(str); // sqlQuery->Colourise(0, str.Length()); // sqlQuery->EmptyUndoBuffer(); // wxSafeYield(); // needed to process sqlQuery modify event // //sqlQuery->SetFilename(lastPath); // sqlQuery->SetChanged(true); // //sqlQuery->SetOrigin(ORIGIN_INITIAL); // setExtendedTitle(); // SqlBookUpdatePageTitle(); // //SetLineEndingStyle(); // SaveTempFile(); // SqlBookAddPage(); //} //// for end //} } //sqlQuery->SetAutoReplaceList(autoreplace); updateMenu(); queryMenu->Enable(MNU_SAVEHISTORY, false); queryMenu->Enable(MNU_CLEARHISTORY, false); setTools(false); lastFileFormat = settings->GetUnicodeFile(); // Load function name pgSet *functions; wxString def_f; wxString def_name; functions = conn->ExecuteSet(wxT("select pg_get_function_arguments(oid) def,proname,pronargs nargs from pg_proc where pronargs>=0 order by proname,pronargs")); if (functions) { //name_func.Init(true); while (!functions->Eof()) { def_f = functions->GetVal(wxT("def")); def_name = functions->GetVal(wxT("proname")); def_func.Add(def_f); name_func.Add(def_name); functions->MoveNext(); } name_func.Sort(); delete functions; } // Note that under GTK+, SetMaxLength() function may only be used with single line text controls. // (see http://docs.wxwidgets.org/2.8/wx_wxtextctrl.html#wxtextctrlsetmaxlength) #ifndef __WXGTK__ msgResult->SetMaxLength(0L); msgHistory->SetMaxLength(0L); #endif } frmQuery::~frmQuery() { closing = true; if (!name_func.IsEmpty()) name_func.Clear(); if (!def_func.IsEmpty()) def_func.Clear(); // Save frmQuery Perspective settings->Write(wxT("frmQuery/Perspective-") + wxString(FRMQUERY_PERSPECTIVE_VER), manager.SavePerspective()); // Uninitialize wxAUIManager manager.UnInit(); if(sqlNotebook) { delete sqlNotebook; sqlNotebook = NULL; } if(controller) { delete controller; controller = NULL; } if(model) { delete model; model = NULL; } if(adjustSizesTimer) { delete adjustSizesTimer; adjustSizesTimer = NULL; } while (cbConnection->GetCount() > 1) { delete (pgConn *)cbConnection->GetClientData(0); cbConnection->Delete(0); } if (favourites) { delete favourites; favourites = NULL; } if (pgsTimer) { delete pgsTimer; pgsTimer = NULL; } if (pgScript) { delete pgScript; pgScript = NULL; } if (mainForm) mainForm->RemoveFrame(this); if (macros) delete macros; if (autoreplace) delete autoreplace; } void frmQuery::OnExit(wxCommandEvent &event) { closing = true; Close(); } void frmQuery::OnEraseBackground(wxEraseEvent &event) { event.Skip(); } void frmQuery::OnSize(wxSizeEvent &event) { event.Skip(); } void frmQuery::OnToggleScratchPad(wxCommandEvent &event) { if (viewMenu->IsChecked(MNU_SCRATCHPAD)) manager.GetPane(wxT("scratchPad")).Show(true); else manager.GetPane(wxT("scratchPad")).Show(false); manager.Update(); } void frmQuery::OnToggleDatabaseBar(wxCommandEvent &event) { if (viewMenu->IsChecked(MNU_DATABASEBAR)) manager.GetPane(wxT("databaseBar")).Show(true); else manager.GetPane(wxT("databaseBar")).Show(false); manager.Update(); } void frmQuery::OnToggleToolBar(wxCommandEvent &event) { if (viewMenu->IsChecked(MNU_TOOLBAR)) manager.GetPane(wxT("toolBar")).Show(true); else manager.GetPane(wxT("toolBar")).Show(false); manager.Update(); } void frmQuery::OnToggleOutputPane(wxCommandEvent &event) { if (viewMenu->IsChecked(MNU_OUTPUTPANE)) { manager.GetPane(wxT("outputPane")).Show(true); manager.LoadPerspective(outputPaneInfo); } else { outputPaneInfo = manager.SavePerspective(); manager.GetPane(wxT("outputPane")).Show(false); } manager.Update(); adjustGQBSizes(); } void frmQuery::OnAuiUpdate(wxAuiManagerEvent &event) { if(event.pane->name == wxT("databaseBar")) { viewMenu->Check(MNU_DATABASEBAR, false); } else if(event.pane->name == wxT("toolBar")) { viewMenu->Check(MNU_TOOLBAR, false); } else if(event.pane->name == wxT("outputPane")) { viewMenu->Check(MNU_OUTPUTPANE, false); if(!adjustSizesTimer) adjustSizesTimer = new wxTimer(this, CTL_TIMERSIZES); adjustSizesTimer->Start(500); } else if(event.pane->name == wxT("scratchPad")) { viewMenu->Check(MNU_SCRATCHPAD, false); } event.Skip(); } void frmQuery::OnDefaultView(wxCommandEvent &event) { // Reset captions to whatever AuiManager expects in perspective BeginPerspectiveChange(); manager.LoadPerspective(FRMQUERY_DEFAULT_PERSPECTIVE, true); // Reset the captions for the current language manager.GetPane(wxT("toolBar")).Caption(_("Tool bar")); manager.GetPane(wxT("databaseBar")).Caption(_("Connection bar")); manager.GetPane(wxT("sqlQuery")).Caption(_("SQL query")); manager.GetPane(wxT("outputPane")).Caption(_("Output pane")); manager.GetPane(wxT("scratchPad")).Caption(_("Scratch pad")); EndPerspectiveChange(false); manager.Update(); // Sync the View menu options viewMenu->Check(MNU_DATABASEBAR, manager.GetPane(wxT("databaseBar")).IsShown()); viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown()); viewMenu->Check(MNU_OUTPUTPANE, manager.GetPane(wxT("outputPane")).IsShown()); viewMenu->Check(MNU_SCRATCHPAD, manager.GetPane(wxT("scratchPad")).IsShown()); } void frmQuery::OnAutoSelectQuery(wxCommandEvent &event) { queryMenu->Check(MNU_AUTOSELECTQUERY, event.IsChecked()); settings->WriteBool(wxT("frmQuery/AutoSelectQuery"), queryMenu->IsChecked(MNU_AUTOSELECTQUERY)); } void frmQuery::OnAutoRollback(wxCommandEvent &event) { queryMenu->Check(MNU_AUTOROLLBACK, event.IsChecked()); settings->WriteBool(wxT("frmQuery/AutoRollback"), queryMenu->IsChecked(MNU_AUTOROLLBACK)); } void frmQuery::OnAutoCommit(wxCommandEvent &event) { bool chk=queryMenu->IsChecked(MNU_AUTOCOMMIT); queryMenu->Check(MNU_AUTOCOMMIT, chk); if (chk) toolBar->SetToolNormalBitmap(MNU_MODE_TRANSACTION, mode_a.GetBitmap(wxDefaultSize)); else toolBar->SetToolNormalBitmap(MNU_MODE_TRANSACTION, mode_t.GetBitmap(wxDefaultSize)); toolBar->Realize(); if(chk && conn->GetTxStatus() != PQTRANS_IDLE) wxMessageBox( _("The current transaction is still in progess.\n\nIn order to take the effect of AUTOCOMMIT mode, please complete the transaction by executing COMMIT, or ROLLBACK statement."), _("Warning - Transaction in progress"), wxICON_INFORMATION | wxOK, this); settings->WriteBool(wxT("frmQuery/AutoCommit"), queryMenu->IsChecked(MNU_AUTOCOMMIT)); } void frmQuery::OnAutoIndent(wxCommandEvent &event) { editMenu->Check(MNU_AUTOINDENT, event.IsChecked()); settings->WriteBool(wxT("frmQuery/AutoIndent"), editMenu->IsChecked(MNU_AUTOINDENT)); SqlBookSetAutoIndent(event.IsChecked()); } void frmQuery::OnWordWrap(wxCommandEvent &event) { viewMenu->Check(MNU_WORDWRAP, event.IsChecked()); settings->WriteBool(wxT("frmQuery/WordWrap"), viewMenu->IsChecked(MNU_WORDWRAP)); SqlBookSetWrapMode(event.IsChecked()); } void frmQuery::OnShowIndentGuides(wxCommandEvent &event) { viewMenu->Check(MNU_SHOWINDENTGUIDES, event.IsChecked()); settings->WriteBool(wxT("frmQuery/ShowIndentGuides"), viewMenu->IsChecked(MNU_SHOWINDENTGUIDES)); SqlBookSetIndentGuides(event.IsChecked()); } void frmQuery::OnShowWhitespace(wxCommandEvent &event) { viewMenu->Check(MNU_SHOWWHITESPACE, event.IsChecked()); settings->WriteBool(wxT("frmQuery/ShowWhitespace"), viewMenu->IsChecked(MNU_SHOWWHITESPACE)); SqlBookSetViewWhiteSpace(event.IsChecked()); } void frmQuery::OnShowLineEnds(wxCommandEvent &event) { viewMenu->Check(MNU_SHOWLINEENDS, event.IsChecked()); settings->WriteBool(wxT("frmQuery/ShowLineEnds"), viewMenu->IsChecked(MNU_SHOWLINEENDS)); SqlBookSetViewEOL(event.IsChecked()); } void frmQuery::OnShowLineNumber(wxCommandEvent &event) { viewMenu->Check(MNU_SHOWLINENUMBER, event.IsChecked()); settings->WriteBool(wxT("frmQuery/ShowLineNumber"), viewMenu->IsChecked(MNU_SHOWLINENUMBER)); SqlBookSetViewLineNumbers(event.IsChecked()); } void frmQuery::OnActivate(wxActivateEvent &event) { if (event.GetActive()) updateMenu(); event.Skip(); } void frmQuery::OnExport(wxCommandEvent &ev) { sqlResult->Export(); } void frmQuery::Go() { cbConnection->SetSelection(0L); wxCommandEvent ev; OnChangeConnection(ev); Show(true); sqlQuery->SetFocus(); loading = false; } typedef struct __sqltokenhelp { const wxChar *token; const wxChar *page; int type; } SqlTokenHelp; SqlTokenHelp sqlTokenHelp[] = { { wxT("ABORT"), 0, 0}, { wxT("ALTER"), 0, 2}, { wxT("ANALYZE"), 0, 0}, { wxT("BEGIN"), 0, 0}, { wxT("CHECKPOINT"), 0, 0}, { wxT("CLOSE"), 0, 0}, { wxT("CLUSTER"), 0, 0}, { wxT("COMMENT"), 0, 0}, { wxT("COMMIT"), 0, 0}, { wxT("COPY"), 0, 0}, { wxT("CREATE"), 0, 1}, { wxT("DEALLOCATE"), 0, 0}, { wxT("DECLARE"), 0, 0}, { wxT("DELETE"), 0, 0}, { wxT("DROP"), 0, 1}, { wxT("END"), 0, 0}, { wxT("EXECUTE"), 0, 0}, { wxT("EXPLAIN"), 0, 0}, { wxT("FETCH"), 0, 0}, { wxT("GRANT"), 0, 0}, { wxT("INSERT"), 0, 0}, { wxT("LISTEN"), 0, 0}, { wxT("LOAD"), 0, 0}, { wxT("LOCK"), 0, 0}, { wxT("MOVE"), 0, 0}, { wxT("NOTIFY"), 0, 0}, { wxT("END"), 0, 0}, // { wxT("PREPARE"), 0, 0}, handled individually { wxT("REINDEX"), 0, 0}, { wxT("RELEASE"), wxT("pg/sql-release-savepoint"), 0}, { wxT("RESET"), 0, 0}, { wxT("REVOKE"), 0, 0}, // { wxT("ROLLBACK"), 0, 0}, handled individually { wxT("SAVEPOINT"), 0, 0}, { wxT("SELECT"), 0, 0}, { wxT("SET"), 0, 0}, { wxT("SHOW"), 0, 0}, { wxT("START"), wxT("pg/sql-start-transaction"), 0}, { wxT("TRUNCATE"), 0, 0}, { wxT("UNLISTEN"), 0, 0}, { wxT("UPDATE"), 0, 0}, { wxT("VACUUM"), 0, 0}, { wxT("AGGREGATE"), 0, 11}, { wxT("CAST"), 0, 11}, { wxT("CONSTRAINT"), 0, 11}, { wxT("CONVERSION"), 0, 11}, { wxT("DATABASE"), 0, 12}, { wxT("DOMAIN"), 0, 11}, { wxT("FUNCTION"), 0, 11}, { wxT("GROUP"), 0, 12}, { wxT("INDEX"), 0, 11}, { wxT("LANGUAGE"), 0, 11}, { wxT("OPERATOR"), 0, 11}, { wxT("ROLE"), 0, 11}, { wxT("RULE"), 0, 11}, { wxT("SCHEMA"), 0, 11}, { wxT("SEQUENCE"), 0, 11}, { wxT("TABLE"), 0, 12}, { wxT("TABLESPACE"), 0, 12}, { wxT("TRIGGER"), 0, 12}, { wxT("TYPE"), 0, 11}, { wxT("USER"), 0, 12}, { wxT("VIEW"), 0, 11}, { wxT("EXTTABLE"), 0, 12}, { 0, 0 } }; void frmQuery::OnContents(wxCommandEvent &event) { DisplayHelp(wxT("query"), HELP_PGADMIN); } void frmQuery::OnChangeConnection(wxCommandEvent &ev) { // On Solaris, this event seems to get fired when the form closes(!!) if(!IsVisible() && !loading) return; unsigned int sel = cbConnection->GetSelection(); if (sel == cbConnection->GetCount() - 1) { // new Connection dlgSelectConnection dlg(this, mainForm); int rc = dlg.Go(conn, cbConnection); if (rc == wxID_OK) { bool createdNewConn; wxString usr=wxEmptyString; wxGetEnv(wxT("USERNAME"),&usr); wxString applicationname = appearanceFactory->GetLongAppName() + wxT(" - query ")+usr; pgConn *newconn = dlg.CreateConn(applicationname, createdNewConn); if (newconn && createdNewConn) { cbConnection->Insert(newconn->GetName(), CreateBitmap(GetServerColour(newconn)), sel); cbConnection->SetClientData(sel, (void *)newconn); cbConnection->SetSelection(sel); OnChangeConnection(ev); } else rc = wxID_CANCEL; } if (rc != wxID_OK) { unsigned int i; for (i = 0 ; i < sel ; i++) { if (cbConnection->GetClientData(i) == conn) { cbConnection->SetSelection(i); break; } } } } else { conn = (pgConn *)cbConnection->GetClientData(sel); SqlBookSetDatabase(conn); int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]); for (int i=0;iSetConnection(conn); //sqlResult->SetConnection(conn); pgScript->SetConnection(conn); title = wxT("") + cbConnection->GetValue(); setExtendedTitle(); seticon(); //Refresh GQB Tree if used if(conn && !firstTime) { controller->getTablesBrowser()->refreshTables(conn); controller->getView()->Refresh(); } } } void frmQuery::OnHelp(wxCommandEvent &event) { wxString page; wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) query = sqlQuery->GetText(); query.Trim(false); if (!query.IsEmpty()) { wxStringTokenizer tokens(query); query = tokens.GetNextToken(); if (query.IsSameAs(wxT("PREPARE"), false)) { if (tokens.GetNextToken().IsSameAs(wxT("TRANSACTION"), false)) page = wxT("sql-prepare-transaction"); else page = wxT("sql-prepare"); } else if (query.IsSameAs(wxT("ROLLBACK"), false)) { if (tokens.GetNextToken().IsSameAs(wxT("PREPARED"), false)) page = wxT("sql-rollback-prepared"); else page = wxT("sql-rollback"); } else { SqlTokenHelp *sth = sqlTokenHelp; while (sth->token) { if (sth->type < 10 && query.IsSameAs(sth->token, false)) { if (sth->page) page = sth->page; else page = wxT("sql-") + query.Lower(); if (sth->type) { int type = sth->type + 10; query = tokens.GetNextToken(); sth = sqlTokenHelp; while (sth->token) { if (sth->type >= type && query.IsSameAs(sth->token, false)) { if (sth->page) page += sth->page; else page += query.Lower(); break; } sth++; } if (!sth->token) page = wxT("sql-commands"); } break; } sth++; } } } if (page.IsEmpty()) page = wxT("sql-commands"); if (conn->GetIsEdb()) DisplayHelp(page, HELP_ENTERPRISEDB); else if (conn->GetIsGreenplum()) DisplayHelp(page, HELP_GREENPLUM); else DisplayHelp(page, HELP_POSTGRESQL); } void frmQuery::OnSaveHistory(wxCommandEvent &event) { #ifdef __WXMSW__ wxFileDialog *dlg = new wxFileDialog(this, _("Save history"), lastDir, wxEmptyString, _("Log files (*.log)|*.log|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #else wxFileDialog *dlg = new wxFileDialog(this, _("Save history"), lastDir, wxEmptyString, _("Log files (*.log)|*.log|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #endif if (dlg->ShowModal() == wxID_OK) { if (!FileWrite(dlg->GetPath(), msgHistory->GetValue(), false)) { wxLogError(__("Could not write the file %s: Errcode=%d."), dlg->GetPath().c_str(), wxSysErrorCode()); } } delete dlg; } void frmQuery::OnChangeNotebookOutpane(wxAuiNotebookEvent &event) { if (outputPane->GetPageCount() > 0) { size_t curpage = outputPane->GetSelection(); if (wxDynamicCast(outputPane->GetPage(curpage), wxTextCtrl)) { wxTextCtrl *hist = wxDynamicCast(outputPane->GetPage(curpage), wxTextCtrl); //hist->SetInsertionPointEnd(); //outputPane->Get if (outputPane->GetPageText(curpage)==_("History")) { ///showMessage(hist->GetName()); hist->ShowPosition(99999999); } //showMessage(); } if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult)) { ctlSQLResult *c=wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult); int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]); for (int i=0;iCmdKeyExecute(wxSTC_CMD_TAB); } } void frmQuery::OnChangeNotebook(wxAuiNotebookEvent &event) { // A bug in wxGTK prevents us to show a modal dialog within a // EVT_AUINOTEBOOK_PAGE_CHANGED event // So, we need these three lines of code to work-around it wxWindow *win = wxWindow::GetCapture(); if (win) win->ReleaseMouse(); if(sqlNotebook && sqlNotebook->GetPageCount() >= 2) { if (event.GetSelection() == 0) { queryMenu->SetHelpString(MNU_EXECUTE, _("Execute query")); queryMenu->SetHelpString(MNU_EXECFILE, _("Execute query, write result to file")); toolBar->SetToolShortHelp(MNU_EXECUTE, _("Execute query")); toolBar->SetToolShortHelp(MNU_EXECFILE, _("Execute query, write result to file")); viewMenu->Enable(MNU_OUTPUTPANE, true); viewMenu->Enable(MNU_SCRATCHPAD, true); // Reset the panes if (viewMenu->IsChecked(MNU_OUTPUTPANE)) manager.GetPane(wxT("outputPane")).Show(true); if (viewMenu->IsChecked(MNU_SCRATCHPAD)) manager.GetPane(wxT("scratchPad")).Show(true); manager.Update(); updateFromGqb(false); } else { manager.GetPane(wxT("outputPane")).Show(false); manager.GetPane(wxT("scratchPad")).Show(false); manager.Update(); viewMenu->Enable(MNU_OUTPUTPANE, false); viewMenu->Enable(MNU_SCRATCHPAD, false); if(firstTime) //Things that should be done on first click on GQB { // Menu queryMenu->Append(MNU_EXECUTE, _("Generate SQL from Graphical Query Builder Model")); queryMenu->SetHelpString(MNU_EXECFILE, _("Generate SQL from Graphical Query Builder Model")); toolBar->SetToolShortHelp(MNU_EXECUTE, _("Generate SQL from Graphical Query Builder Model")); toolBar->SetToolShortHelp(MNU_EXECFILE, _("Generate SQL from Graphical Query Builder Model")); // Size, and pause to allow the window to draw adjustGQBSizes(); wxTheApp->Yield(true); // Database related Stuffs. // Create a server object and connect it. controller->getTablesBrowser()->refreshTables(conn); firstTime = false; } } } } void frmQuery::OnSetFocus(wxFocusEvent &event) { sqlQuery->SetFocus(); event.Skip(); } void frmQuery::OnClearHistory(wxCommandEvent &event) { queryMenu->Enable(MNU_SAVEHISTORY, false); queryMenu->Enable(MNU_CLEARHISTORY, false); msgHistory->Clear(); msgHistory->SetFont(settings->GetSQLFont()); } void frmQuery::OnFocus(wxFocusEvent &ev) { if (wxDynamicCast(this, wxFrame)) updateMenu(); else { frmQuery *wnd = (frmQuery *)GetParent(); if (wnd) wnd->OnFocus(ev); } ev.Skip(); } void frmQuery::OnCut(wxCommandEvent &ev) { if (currentControl() == sqlQuery) { sqlQuery->Cut(); updateMenu(); } } wxWindow *frmQuery::currentControl() { wxWindow *wnd = FindFocus(); if (wnd == outputPane) { wnd = sqlResult; switch (outputPane->GetSelection()) { case 0: wnd = sqlResult; break; case 1: wnd = explainCanvas; break; case 2: wnd = msgResult; break; case 3: wnd = msgHistory; break; } } return wnd; } void frmQuery::OnCopy(wxCommandEvent &ev) { wxWindow *wnd = currentControl(); if (wnd == sqlQuery) { sqlQuery->Copy(); SetStatusText("Select query copy.", STATUSPOS_MSGS); } else if (wnd == msgResult) { msgResult->Copy(); SetStatusText("select msgResult copy.", STATUSPOS_MSGS); } else if (wnd == msgHistory) msgHistory->Copy(); else if (wnd == scratchPad) scratchPad->Copy(); else { wxWindow *obj = wnd; while (obj != NULL) { if (obj == sqlResult) { sqlResult->Copy(0); SetStatusText("Result query copy.", STATUSPOS_MSGS); break; } obj = obj->GetParent(); } } updateMenu(); } void frmQuery::OnPaste(wxCommandEvent &ev) { if (currentControl() == sqlQuery) sqlQuery->Paste(); else if (currentControl() == scratchPad) scratchPad->Paste(); } void frmQuery::OnClear(wxCommandEvent &ev) { wxWindow *wnd = currentControl(); if (wnd == sqlQuery) sqlQuery->ClearAll(); else if (wnd == msgResult) { msgResult->Clear(); msgResult->SetFont(settings->GetSQLFont()); } else if (wnd == msgHistory) { msgHistory->Clear(); msgHistory->SetFont(settings->GetSQLFont()); } else if (wnd == scratchPad) scratchPad->Clear(); } void frmQuery::OnSelectAll(wxCommandEvent &ev) { wxWindow *wnd = currentControl(); if (wnd == sqlQuery) sqlQuery->SelectAll(); else if (wnd == msgResult) msgResult->SelectAll(); else if (wnd == msgHistory) msgHistory->SelectAll(); else if (wnd == sqlResult) sqlResult->SelectAll(); else if (wnd == scratchPad) scratchPad->SelectAll(); else if (wnd->GetParent() == sqlResult) sqlResult->SelectAll(); } void frmQuery::OnSearchReplace(wxCommandEvent &ev) { sqlQuery->OnSearchReplace(ev); } void frmQuery::OnTransformText(wxCommandEvent& ev) { sqlQuery->OnTransformText(ev); } void frmQuery::OnUndo(wxCommandEvent &ev) { sqlQuery->Undo(); } void frmQuery::OnRedo(wxCommandEvent &ev) { sqlQuery->Redo(); } void frmQuery::setExtendedTitle() { wxString chgStr; if (sqlQuery->IsChanged()) chgStr = wxT(" *"); wxString filename = sqlQuery->GetFilename(); if (filename.IsNull()) SetTitle(title + chgStr); else { SetTitle(title + wxT(" - [") + filename + wxT("]") + chgStr); } // Allow to save initial queries though they are not changed bool enableSave = sqlQuery->IsChanged() || (sqlQuery->GetOrigin() == ORIGIN_INITIAL); toolBar->EnableTool(MNU_SAVE, enableSave); fileMenu->Enable(MNU_SAVE, enableSave); } bool frmQuery::relatesToWindow(wxWindow *which, wxWindow *related) { while (which != NULL) { if (which == related) return true; else which = which->GetParent(); } return false; } void frmQuery::updateMenu(bool allowUpdateModelSize) { bool canCut = false; bool canCopy = false; bool canPaste = false; bool canUndo = false; bool canRedo = false; bool canClear = false; bool canFind = false; bool canAddFavourite = false; bool canManageFavourite = false; bool canSaveExplain = false; bool canSaveGQB = false; wxAuiFloatingFrame *fp = wxDynamicCastThis(wxAuiFloatingFrame); if (fp) return; if (closing) return; canSaveExplain = explainCanvas->GetDiagram()->GetCount() > 0; if (allowUpdateModelSize) { canSaveGQB = controller->getView() != NULL && controller->getView()->canSaveAsImage(); } saveasImageMenu->Enable(MNU_SAVEAS_IMAGE_GQB, canSaveGQB); saveasImageMenu->Enable(MNU_SAVEAS_IMAGE_EXPLAIN, canSaveExplain); wxWindow *wnd = currentControl(); if (wnd == NULL) return; if (relatesToWindow(wnd, sqlQuery) || relatesToWindow(wnd, sqlResult) || relatesToWindow(wnd, msgResult) || relatesToWindow(wnd, msgHistory) || relatesToWindow(wnd, scratchPad)) { if (relatesToWindow(wnd, sqlQuery)) { canUndo = sqlQuery->CanUndo(); canRedo = sqlQuery->CanRedo(); canPaste = sqlQuery->CanPaste(); canFind = true; canAddFavourite = (sqlQuery->GetLength() > 0) && (settings->GetFavouritesFile().Length() > 0); canManageFavourite = (settings->GetFavouritesFile().Length() > 0); } else if (relatesToWindow(wnd, scratchPad)) { canPaste = true; } canCopy = true; canCut = true; canClear = true; } toolBar->EnableTool(MNU_UNDO, canUndo); editMenu->Enable(MNU_UNDO, canUndo); toolBar->EnableTool(MNU_REDO, canRedo); editMenu->Enable(MNU_REDO, canRedo); toolBar->EnableTool(MNU_COPY, canCopy); editMenu->Enable(MNU_COPY, canCopy); toolBar->EnableTool(MNU_PASTE, canPaste); editMenu->Enable(MNU_PASTE, canPaste); toolBar->EnableTool(MNU_CUT, canCut); editMenu->Enable(MNU_CUT, canCut); toolBar->EnableTool(MNU_CLEAR, canClear); editMenu->Enable(MNU_CLEAR, canClear); toolBar->EnableTool(MNU_FIND, canFind); editMenu->Enable(MNU_FIND, canFind); favouritesMenu->Enable(MNU_FAVOURITES_ADD, canAddFavourite); favouritesMenu->Enable(MNU_FAVOURITES_INJECT, canAddFavourite); // these two use the same criteria favouritesMenu->Enable(MNU_FAVOURITES_MANAGE, canManageFavourite); } void frmQuery::UpdateFavouritesList() { if (IsVisible() && menuBar->FindMenu(_("Fav&ourites")) == wxNOT_FOUND) return; if (favourites) delete favourites; favourites = queryFavouriteFileProvider::LoadFavourites(true); while (favouritesMenu->GetMenuItemCount() > 4) // there are 3 static items + separator above { favouritesMenu->Destroy(favouritesMenu->GetMenuItems()[4]); } favourites->AppendAllToMenu(favouritesMenu, MNU_FAVOURITES_MANAGE + 1); } void frmQuery::UpdateMacrosList() { if (IsVisible() && menuBar->FindMenu(_("&Macros")) == wxNOT_FOUND) return; if (macros) delete macros; macros = queryMacroFileProvider::LoadMacros(true); while (macrosMenu->GetMenuItemCount() > 2) { macrosMenu->Destroy(macrosMenu->GetMenuItems()[2]); } macros->AppendAllToMenu(macrosMenu, MNU_MACROS_MANAGE + 1); } void frmQuery::OnAddFavourite(wxCommandEvent &event) { if (sqlQuery->GetText().Trim().IsEmpty()) return; int r = dlgAddFavourite(this, favourites).AddFavourite(sqlQuery->GetText()); if (r == 1) { // Added a favourite, so save queryFavouriteFileProvider::SaveFavourites(favourites); } if (r == 1 || r == -1) { // Changed something requiring rollback mainForm->UpdateAllFavouritesList(); } } void frmQuery::OnInjectFavourite(wxCommandEvent &event) { queryFavouriteItem *fav; bool selected = true; int startPos, endPos; wxString name = sqlQuery->GetSelectedText(); if (name.IsEmpty()) { // get the word under cursor: int curPos = sqlQuery->GetCurrentPos(); startPos = sqlQuery->WordStartPosition(curPos, true); endPos = sqlQuery->WordEndPosition(curPos, true); name = sqlQuery->GetTextRange(startPos, endPos); selected = false; } name.Trim(false).Trim(true); if (name.IsEmpty()) return; // search for favourite with this name fav = favourites->FindFavourite(name); if (!fav) return; // replace selection (or current word) with it's contents //wxLogInfo(wxT("frmQuery::OnReplaceFavourite(): name=[%s] contents=[%s]"), name, fav->GetContents()); sqlQuery->BeginUndoAction(); if (!selected) sqlQuery->SetSelection(startPos, endPos); sqlQuery->ReplaceSelection(fav->GetContents()); sqlQuery->EndUndoAction(); } void frmQuery::OnManageFavourites(wxCommandEvent &event) { int r = dlgManageFavourites(this, favourites).ManageFavourites(); if (r == 1) { // Changed something, so save queryFavouriteFileProvider::SaveFavourites(favourites); } if (r == 1 || r == -1) { // Changed something requiring rollback mainForm->UpdateAllFavouritesList(); } } void frmQuery::OnSelectFavourite(wxCommandEvent &event) { queryFavouriteItem *fav; fav = favourites->FindFavourite(event.GetId()); if (!fav) return; if (!sqlQuery->GetText().Trim().IsEmpty()) { int r = wxMessageDialog(this, _("Replace current query?"), _("Confirm replace"), wxYES_NO | wxCANCEL | wxICON_QUESTION).ShowModal(); if (r == wxID_CANCEL) return; else if (r == wxID_YES) sqlQuery->ClearAll(); else { if (sqlQuery->GetText().Last() != '\n') sqlQuery->AddText(wxT("\n")); // Add a newline after the last query } } sqlQuery->AddText(fav->GetContents()); } bool frmQuery::CheckChanged(bool canVeto) { if (sqlQuery->IsChanged() && settings->GetAskSaveConfirmation()) { wxString fn, filename; filename = sqlQuery->GetFilename(); if (!filename.IsNull()) fn = wxString::Format(_("The text in file %s has changed.\nDo you want to save changes?"), filename.c_str()); else fn = _("The text has changed.\nDo you want to save changes?"); wxMessageDialog msg(this, fn, _("Query"), wxYES_NO | wxICON_EXCLAMATION | (canVeto ? wxCANCEL : 0)); wxCommandEvent noEvent; switch (msg.ShowModal()) { case wxID_YES: if (filename.IsNull()) OnSaveAs(noEvent); else OnSave(noEvent); return sqlQuery->IsChanged(); case wxID_CANCEL: return true; } } return false; } void frmQuery::OnClose(wxCloseEvent &event) { if (queryMenu->IsEnabled(MNU_CANCEL)) { if (event.CanVeto()) { wxMessageDialog msg(this, _("A query is running. Do you wish to cancel it?"), _("Query"), wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); if (msg.ShowModal() != wxID_YES) { event.Veto(); return; } } wxCommandEvent ev; OnCancel(ev); } while (sqlResult->RunStatus() == CTLSQL_RUNNING) { wxLogInfo(wxT("SQL Query box: Waiting for query to abort")); wxSleep(1); } if (m_loadingfile && event.CanVeto()) { wxMessageBox(_("The query tool cannot be closed whilst a file is loading."), _("Warning"), wxICON_INFORMATION | wxOK); event.Veto(); return; } if (SqlBookClose(event.CanVeto()) && event.CanVeto()) { event.Veto(); return; } closing = true; // Reset the panes if (viewMenu->IsChecked(MNU_OUTPUTPANE)) manager.GetPane(wxT("outputPane")).Show(true); if (viewMenu->IsChecked(MNU_SCRATCHPAD)) manager.GetPane(wxT("scratchPad")).Show(true); manager.Update(); Hide(); int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]); for (int i=0;iDisconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); // sqlResult->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); msgResult->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); msgHistory->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); controller->nullView(); //to avoid bug on *nix when deleting controller settings->SetExplainVerbose(queryMenu->IsChecked(MNU_VERBOSE)); settings->SetExplainCosts(queryMenu->IsChecked(MNU_COSTS)); settings->SetExplainBuffers(queryMenu->IsChecked(MNU_BUFFERS)); settings->SetExplainTiming(queryMenu->IsChecked(MNU_TIMING)); for (int i=0;iAbort(); // sqlResult->Abort(); // to make sure conn is unused Destroy(); } void frmQuery::OnChangeStc(wxStyledTextEvent &event) { // The STC seems to fire this event even if it loses focus. Fortunately, // that seems to be m_modificationType == 512. // 0x4010 - SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER if ((event.m_modificationType != 512 && event.m_modificationType != 0x4010)&& // Sometimes there come events 20 and 520 AFTER the initial query was set by constructor. // Their occurrence is related to query's size and possibly international characters in it (??) // Filter them out to keep "initial" origin of query text. (sqlQuery->GetOrigin() != ORIGIN_INITIAL || (event.m_modificationType != 20 && event.m_modificationType != 520))) { // This is the default change origin. // In other cases the changer function will reset it after this event. sqlQuery->SetOrigin(ORIGIN_MANUAL); if (!sqlQuery->IsChanged()) { sqlQuery->SetChanged(true); setExtendedTitle(); //SqlBookUpdatePageTitle(); CallAfter(&frmQuery::SqlBookUpdatePageTitle); } } // do not allow update of model size of GQB on input (key press) of each // character of the query in Query Tool updateMenu(false); } void frmQuery::OnLabelRightClick(wxGridEvent &event) { wxMenu *xmenu = new wxMenu(); wxArrayInt rows = sqlResult->GetSelectedRows(); xmenu->Append(MNU_COPY, _("&Copy"), _("Copy selected cells to clipboard.")); xmenu->Append(MNU_PASTE, _("&Paste"), _("Paste data from the clipboard.")); xmenu->Append(MNU_DELETE, _("&Delete"), _("Delete selected rows.")); xmenu->AppendSeparator(); xmenu->Append(MNU_COPY_INSERT, _("Copy Insert format"), _("Copy Insert format.")); xmenu->Append(MNU_COPY_LISTCOLTYPE, _("List columns header"), _("Copy list columns header")); xmenu->Append(MNU_COPY_INLIST, _("IN list format copy"), _("Copy In list format.")); xmenu->Append(MNU_COPY_WHERELIST, _("WHERE list format copy"), _("Copy where list format.")); xmenu->Append(MNU_COPY_TABLEHTML, _("Copy table html format"), _("Copy table html format.")); if (body_template.Count()>0) { //MNU_GENERATE_TEMPLATE wxMenu *submenu = NULL; //wxString t="begin @obj_id@ end"; int cnt=0; for(int i=0;iGenerateTemplate(body_template[i],1); if (s=="OK") { if (submenu==NULL) submenu = new wxMenu(); cnt++; submenu->Append(MNU_GENERATESQL+cnt,title_template[i],body_template[i]); } else SetStatusText(s, STATUSPOS_MSGS); } if (cnt>0) xmenu->Append(MNU_GENERATESQL,"Generate",submenu); } xmenu->AppendSeparator(); xmenu->Append(MNU_AUTOCOLSPLOT, _("Draw plot LY(bar) or LXY or XYYY..."), _("Draw plot LY(bar) LXY or XYYY...")); xmenu->Append(MNU_SUMMARY_COL, _("Summary"), _("Summary selected cells.")); xmenu->Append(MNU_COMPARE_2CELL, _("Compare 2 Cells"), _("Compare 2 selected cells.")); xmenu->Append(MNU_CHECK_COLUMN_DATE, _("Check the sequence of dates"), _("Check the sequence of dates")); xmenu->Append(MNU_CLEAR_FILTER, _("Clear filter"), _("Clear filter")); bool selcol = sqlResult->GetSelectedCols().GetCount() > 0; xmenu->Enable(MNU_CHECK_COLUMN_DATE, selcol); xmenu->Enable(MNU_COPY_LISTCOLTYPE, selcol); xmenu->Enable(MNU_COPY_TABLEHTML, selcol|| rows.GetCount()>0); xmenu->Enable(MNU_AUTOCOLSPLOT, sqlResult->IsSelection()); xmenu->Enable(MNU_SUMMARY_COL, sqlResult->IsSelection()); xmenu->Enable(MNU_COMPARE_2CELL, sqlResult->IsSelection()); xmenu->Enable(MNU_COPY_INLIST, sqlResult->IsSelection()); xmenu->Enable(MNU_COPY_WHERELIST, sqlResult->IsSelection()); if ((rows.GetCount())) { xmenu->Enable(MNU_COPY, true); xmenu->Enable(MNU_DELETE, true); xmenu->Enable(MNU_PASTE, true); } else { xmenu->Enable(MNU_COPY, false); xmenu->Enable(MNU_DELETE, false); xmenu->Enable(MNU_PASTE, false); } xmenu->Enable(MNU_CLEAR_FILTER, isfilterresult); sqlResult->PopupMenu(xmenu); } void frmQuery::OnCopy_Insert(wxCommandEvent &ev) { // if (currentControl() == sqlResult) { wxString s=wxT("Insert into format copy buffer."); sqlResult->Copy(1); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnCopy_InList(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { wxString s = wxT("In list format copy buffer."); sqlResult->Copy(2); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnCopy_WhereList(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { wxString s = wxT("Where list format copy buffer."); sqlResult->Copy(3); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnGenerateInvoke(wxCommandEvent& ev) { // if (currentControl() == sqlResult) int id=ev.GetId()-MNU_GENERATESQL-1; wxString s = _("No template generate."); //wxMenu* mi = static_cast(ev.GetEventObject()); if (id>=0 && idGenerateTemplate(templ,0); SetStatusText(s.substr(0,200), STATUSPOS_MSGS); } } else SetStatusText(s, STATUSPOS_MSGS); } void frmQuery::OnCopy_TableToHtml(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { wxString s = wxT("Query and table HTML format copy."); bool press = wxGetKeyState(WXK_CONTROL); wxString q = sqlResult->sqlquerytext; wxString html; if (!press) { if (q.IsEmpty()) { SetStatusText("Problem: Query not found.", STATUSPOS_MSGS); return; } ctlSQLBox* box = new ctlSQLBox(sqlNotebook, CTL_SQLQUERY, wxDefaultPosition, wxSize(0, 0), wxTE_MULTILINE | wxTE_RICH2); box->SetText(q); box->Colourise(0, box->GetLength()); html = box->TextToHtml(0, box->GetLength()); delete box; } else { html = ""; s = wxT("ONLY table HTML format copy."); } sqlResult->CopyTableToHtml(html); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnCellLeftDClick(wxGridEvent &event) { int row=event.GetRow(); int col=event.GetCol(); bool reverse=event.AltDown(); wxString s=wxEmptyString; s.Printf("wait ...",row,col); SetStatusText(s, STATUSPOS_MSGS); s=sqlResult->SetFilter(row,col,reverse); isfilterresult=true; SetStatusText(s, STATUSPOS_MSGS); } void frmQuery::OnClear_Filter(wxCommandEvent &ev) { // if (currentControl() == sqlResult) { wxString s=wxT("Clear filter"); sqlResult->ClearFilter(); SetStatusText(s, STATUSPOS_MSGS); isfilterresult=false; } } void frmQuery::OnCopy_NameTypeCols(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { bool press=wxGetKeyState(WXK_CONTROL); wxString s = sqlResult->CopySelColumnNameType(press); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnCheck_Column_Date(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { wxString s = sqlResult->CheckSelColumnDate(); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnAutoColsPlot(wxCommandEvent& ev) { // if (currentControl() == sqlResult) { frmQuery* q = this; wxString s = sqlResult->AutoColsPlot(0, q); SetStatusText(s, STATUSPOS_MSGS); } } void frmQuery::OnCompare_2Cell(wxCommandEvent& ev) { wxString s = sqlResult->CompareSelectCells(); SetStatusText(s, STATUSPOS_MSGS); } void frmQuery::OnSummary_Column(wxCommandEvent &ev) { // if (currentControl() == sqlResult) { wxString s=sqlResult->SummaryColumn(); SetStatusText(s, STATUSPOS_POS); } } void frmQuery::DoUpdatePositionStc(const wxStyledTextEvent &event) { int selFrom, selTo, selCount; sqlQuery->GetSelection(&selFrom, &selTo); selCount = selTo - selFrom; editMenu->Enable(MNU_AUTOEDITOBJECT, selCount > 0); wxString pos; wxUniChar ch=0; int p = sqlQuery->GetCurrentPos(); wxString simbol; if (p < sqlQuery->GetLength()) { simbol = sqlQuery->GetTextRange(p, sqlQuery->PositionRelative(p, 1)); } if (!simbol.IsEmpty()) ch = simbol[0]; pos.Printf(_("Ln %d, Col %d, Ch %d"), sqlQuery->LineFromPosition(p) + 1, sqlQuery->GetColumn(p) + 1, ch); //pos.Printf(_("Ln %d, Col %d, Ch %d, st %d"), sqlQuery->LineFromPosition(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetColumn(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetCurrentPos() + 1,sqlQuery->GetStyleAt(sqlQuery->GetCurrentPos() - 1)); if (pos.length() > 24) { pos.Printf("L %d,C %d,Ch %d", sqlQuery->LineFromPosition(p) + 1, sqlQuery->GetColumn(p) + 1, ch); } SetStatusText(pos, STATUSPOS_POS); if (selCount < 1) pos = wxEmptyString; else pos.Printf(wxPLURAL("%d char", "%d chars", selCount), selCount); SetStatusText(pos, STATUSPOS_SEL); } void frmQuery::OnPositionStc(wxStyledTextEvent &event) { CallAfter(&frmQuery::DoUpdatePositionStc,event); } void frmQuery::OpenLastFile() { wxString str; bool modeUnicode = settings->GetUnicodeFile(); wxUtfFile file(lastPath, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); m_loadingfile = true; if (file.IsOpened()) file.Read(str); if (!str.IsEmpty()) { sqlQuery->SetText(str); sqlQuery->Colourise(0, sqlQuery->GetLength()); sqlQuery->EmptyUndoBuffer(); wxSafeYield(); // needed to process sqlQuery modify event sqlQuery->SetFilename(lastPath); sqlQuery->SetChanged(false); sqlQuery->SetOrigin(ORIGIN_FILE); setExtendedTitle(); SqlBookUpdatePageTitle(); SetLineEndingStyle(); UpdateRecentFiles(true); if(mainForm != NULL) { mainForm->UpdateAllRecentFiles(); } } sqlQuery->SetFocus(); m_loadingfile = false; } void frmQuery::UpdateAllRecentFiles() { mainForm->UpdateAllRecentFiles(); } void frmQuery::OnNew(wxCommandEvent &event) { frmQuery *fq = new frmQuery(mainForm, wxEmptyString, conn->Duplicate(), wxEmptyString); if (mainForm) mainForm->AddFrame(fq); fq->Go(); } void frmQuery::OnOpen(wxCommandEvent &event) { if (CheckChanged(true)) return; #ifdef __WXMSW__ wxFileDialog dlg(this, _("Open query file"), lastDir, wxT(""), _("Query files (*.sql)|*.sql|pgScript files (*.pgs)|*.pgs|All files (*.*)|*.*"), wxFD_OPEN); #else wxFileDialog dlg(this, _("Open query file"), lastDir, wxT(""), _("Query files (*.sql)|*.sql|pgScript files (*.pgs)|*.pgs|All files (*)|*"), wxFD_OPEN); #endif if (dlg.ShowModal() == wxID_OK) { lastFilename = dlg.GetFilename(); lastDir = dlg.GetDirectory(); lastPath = dlg.GetPath(); OpenLastFile(); } } void frmQuery::SaveTempFile() { bool modeUnicode = settings->GetUnicodeFile(); wxString filename = sqlQuery->GetFilename(); if (!filename.IsNull()) { return; } filename=sqlQuery->GetTitle(false); wxString pref=conn->GetDbname(); //if (filename.StartsWith(pref)) filename+=wxT(".a"); wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); if (autoSave) { wxUtfFile file(tempDir + filename, wxFile::write, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { int nl = sqlQuery->GetCurrentPos(); wxString strnl; strnl = wxString::Format(_("%i@"), nl); file.Write(strnl); if ((file.Write(sqlQuery->GetText()) == 0) && (!modeUnicode)) wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead.")); file.Close(); sqlQuery->SetChanged(false); SqlBookUpdatePageTitle(); } else { wxLogError(__("Could not write the file %s: Errcode=%d."), filename.c_str(), wxSysErrorCode()); } } } void frmQuery::OnSave(wxCommandEvent &event) { bool modeUnicode = settings->GetUnicodeFile(); wxString filename = sqlQuery->GetFilename(); if (filename.IsNull()) { OnSaveAs(event); return; } wxUtfFile file(filename, wxFile::write, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { if ((file.Write(sqlQuery->GetText()) == 0) && (!modeUnicode)) wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead.")); file.Close(); sqlQuery->SetChanged(false); setExtendedTitle(); UpdateRecentFiles(); SqlBookUpdatePageTitle(); sqlQuery->SetFilename(filename); } else { wxLogError(__("Could not write the file %s: Errcode=%d."), filename.c_str(), wxSysErrorCode()); } } // Set the line ending style based on the current document. void frmQuery::SetLineEndingStyle() { // Detect the file mode wxRegEx *reLF = new wxRegEx(wxT("[^\r]\n"), wxRE_NEWLINE); wxRegEx *reCRLF = new wxRegEx(wxT("\r\n"), wxRE_NEWLINE); wxRegEx *reCR = new wxRegEx(wxT("\r[^\n]"), wxRE_NEWLINE); bool haveLF = reLF->Matches(sqlQuery->GetText()); bool haveCRLF = reCRLF->Matches(sqlQuery->GetText()); bool haveCR = reCR->Matches(sqlQuery->GetText()); int mode = GetLineEndingStyle(); if ((haveLF && haveCR) || (haveLF && haveCRLF) || (haveCR && haveCRLF)) { wxMessageBox(_("This file contains mixed line endings. They will be converted to the current setting."), _("Warning"), wxICON_INFORMATION | wxOK); sqlQuery->ConvertEOLs(mode); sqlQuery->SetChanged(true); setExtendedTitle(); updateMenu(); } else { if (haveLF) mode = wxSTC_EOL_LF; else if (haveCRLF) mode = wxSTC_EOL_CRLF; else if (haveCR) mode = wxSTC_EOL_CR; } // Now set the status text, menu options, and the mode sqlQuery->SetEOLMode(mode); SetEOLModeDisplay(mode); delete reCRLF; delete reCR; delete reLF; } // Get the line ending style int frmQuery::GetLineEndingStyle() { if (lineEndMenu->IsChecked(MNU_LF)) return wxSTC_EOL_LF; else if (lineEndMenu->IsChecked(MNU_CRLF)) return wxSTC_EOL_CRLF; else if (lineEndMenu->IsChecked(MNU_CR)) return wxSTC_EOL_CR; else return sqlQuery->GetEOLMode(); } void frmQuery::OnAutoEditObject(wxCommandEvent &event) { if (!mainForm) return; //parent->SetCurrentNode(parent->GetBrowser()->GetRootItem(), path); pgObject *obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection()); if (!obj) return; pgFunction *fun=(pgFunction *)obj;//obj->Show //mainForm.propFactory->StartDialog(mainForm, obj); //showMessage(obj->GetTypeName()); //return; if (obj->GetTypeName()==wxT("Servers")||obj->GetTypeName()==wxT("Server")||obj->GetTypeName()==wxT("Databases") ||obj->GetTypeName()==wxT("Tablespaces")||obj->GetTypeName()==wxT("Group Roles") ||obj->GetTypeName()==wxT("Login Roles") ) return; wxString databasePath = mainForm->GetNodePath(obj->GetDatabase()->GetId()); //showMessage(databasePath); wxString selText = sqlQuery->GetSelectedText(); if (!selText.IsNull()) { databasePath =databasePath +wxT("/")+ _("Schemas"); if(!mainForm->SetCurrentNode(mainForm->GetBrowser()->GetRootItem(), databasePath)) { wxMessageBox(_("The specified object couldn't be found in the tree.") + databasePath); } //int n=mainForm->GetBrowser()->GetChildrenCount(mainForm->GetBrowser()->GetSelection(),false); wxTreeItemId matchItem = mainForm->GetBrowser()->FindItem(obj->GetId(),selText,true); if (matchItem.IsOk()) { wxString findtext= mainForm->GetBrowser()->GetItemText(matchItem); pgObject *o=mainForm->GetBrowser()->GetObject(matchItem); //mainForm->GetBrowser()->SelectItem(o->GetId()); //showMessage(o->GetName().Lower()); if (!o) return; if (o->GetName().Lower()==selText.Lower()) { //obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection()); mainForm->execSelChange(matchItem,false); //obj=o; obj = mainForm->GetBrowser()->GetObject(matchItem); if (!dlgProperty::EditObjectDialog(mainForm, 0, obj)) mainForm->CheckAlive(); } } } } // User-set the current EOL mode for the form void frmQuery::OnSetEOLMode(wxCommandEvent &event) { int mode = GetLineEndingStyle(); sqlQuery->ConvertEOLs(mode); sqlQuery->SetEOLMode(mode); settings->SetLineEndingType(mode); SetEOLModeDisplay(mode); if (!sqlQuery->IsChanged()) { sqlQuery->SetChanged(true); setExtendedTitle(); } setExtendedTitle(); // TODO: Figure out why this is here? pgScript->SetConnection(conn); } // Display the EOL mode settings on the form void frmQuery::SetEOLModeDisplay(int mode) { switch(mode) { case wxSTC_EOL_LF: lineEndMenu->Check(MNU_LF, true); SetStatusText(_("Unix"), STATUSPOS_FORMAT); break; case wxSTC_EOL_CRLF: lineEndMenu->Check(MNU_CRLF, true); SetStatusText(_("DOS"), STATUSPOS_FORMAT); break; case wxSTC_EOL_CR: lineEndMenu->Check(MNU_CR, true); SetStatusText(_("Mac"), STATUSPOS_FORMAT); break; default: wxLogError(wxT("Someone created a new line ending style! Run, run for your lives!!")); } } void frmQuery::OnSaveAs(wxCommandEvent &event) { wxString filename; filename = sqlQuery->GetFilename(); if (filename.IsNull()) filename = lastFilename; #ifdef __WXMSW__ wxFileDialog *dlg = new wxFileDialog(this, _("Save query file as"), lastDir, filename, /*lastFilename,*/ _("Query files (*.sql)|*.sql|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #else wxFileDialog *dlg = new wxFileDialog(this, _("Save query file as"), lastDir, filename, /*lastFilename,*/ _("Query files (*.sql)|*.sql|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #endif if (dlg->ShowModal() == wxID_OK) { lastFilename = dlg->GetFilename(); lastDir = dlg->GetDirectory(); lastPath = dlg->GetPath(); switch (dlg->GetFilterIndex()) { case 0: #ifdef __WXMAC__ if (!lastPath.Contains(wxT("."))) lastPath += wxT(".sql"); #endif break; case 1: #ifdef __WXMAC__ if (!lastPath.Contains(wxT("."))) lastPath += wxT(".sql"); #endif break; default: break; } lastFileFormat = settings->GetUnicodeFile(); wxUtfFile file(lastPath, wxFile::write, lastFileFormat ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT); if (file.IsOpened()) { if ((file.Write(sqlQuery->GetText()) == 0) && (!lastFileFormat)) wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead.")); file.Close(); sqlQuery->SetChanged(false); sqlQuery->SetFilename(lastPath); // Forget about Initial origin thus making "Save" button behave as usual // (be enabled/disabled according to dirty flag only). if (sqlQuery->GetOrigin() == ORIGIN_INITIAL) sqlQuery->SetOrigin(ORIGIN_FILE); setExtendedTitle(); SqlBookUpdatePageTitle(); SetOutputPaneCaption(true); UpdateRecentFiles(); fileMenu->Enable(MNU_RECENT, (recentFileMenu->GetMenuItemCount() > 0)); } else { wxLogError(__("Could not write the file %s: Errcode=%d."), lastPath.c_str(), wxSysErrorCode()); } } delete dlg; } void frmQuery::OnQuickReport(wxCommandEvent &event) { wxDateTime now = wxDateTime::Now(); frmReport *rep = new frmReport(this); rep->XmlAddHeaderValue(wxT("generated"), now.Format(wxT("%c"))); rep->XmlAddHeaderValue(wxT("database"), conn->GetName()); rep->SetReportTitle(_("Quick report")); int section = rep->XmlCreateSection(_("Query results")); rep->XmlAddSectionTableFromGrid(section, sqlResult); wxString stats; stats.Printf(wxT("%ld rows with %d columns retrieved."), sqlResult->NumRows(), sqlResult->GetNumberCols()); rep->XmlSetSectionTableInfo(section, stats); wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) query = sqlQuery->GetText(); rep->XmlSetSectionSql(section, query); rep->ShowModal(); } void frmQuery::OnCancel(wxCommandEvent &event) { toolBar->EnableTool(MNU_CANCEL, false); queryMenu->Enable(MNU_CANCEL, false); SetStatusText(_("Cancelling."), STATUSPOS_MSGS); if (sqlResult->RunStatus() == CTLSQL_RUNNING) sqlResult->Abort(); else if (pgScript->IsRunning()) pgScript->Terminate(); QueryExecInfo *qi = (QueryExecInfo *)event.GetClientData(); if (qi) delete qi; aborted = true; } void frmQuery::OnExplain(wxCommandEvent &event) { if(sqlNotebook->GetSelection() == 1) { if (!updateFromGqb(true)) return; } wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) { if (queryMenu->IsChecked(MNU_AUTOSELECTQUERY)) { // Auto-select SelectQuery(); query = sqlQuery->GetSelectedText(); } else query = sqlQuery->GetText(); } if (query.IsNull()) return; wxString sql; int resultToRetrieve = 1; bool verbose = queryMenu->IsChecked(MNU_VERBOSE); bool analyze = event.GetId() == MNU_EXPLAINANALYZE; if (analyze) { sql += wxT("\nBEGIN;\n"); resultToRetrieve++; } sql += wxT("EXPLAIN "); if (conn->BackendMinimumVersion(9, 0)) { bool costs = queryMenu->IsChecked(MNU_COSTS); bool buffers = queryMenu->IsChecked(MNU_BUFFERS) && analyze; bool timing = queryMenu->IsChecked(MNU_TIMING) && analyze; sql += wxT("("); if (analyze) sql += wxT("ANALYZE on, "); else sql += wxT("ANALYZE off, "); if (verbose) sql += wxT("VERBOSE on, "); else sql += wxT("VERBOSE off, "); if (costs) sql += wxT("COSTS on, "); else sql += wxT("COSTS off, "); if (conn->BackendMinimumVersion(13, 0)) { sql += wxT("SUMMARY on, "); } if (buffers) sql += wxT("BUFFERS on"); else sql += wxT("BUFFERS off"); if (conn->BackendMinimumVersion(9, 2)) { if (timing) sql += wxT(", TIMING on "); else sql += wxT(", TIMING off "); } sql += wxT(")"); } else { if (analyze) sql += wxT("ANALYZE "); if (verbose) sql += wxT("VERBOSE "); } int offset = sql.Length(); sql += query; if (analyze) { // Bizarre bug fix - if we append a rollback directly after -- it'll crash!! // Add a \n first. sql += wxT("\n;\nROLLBACK;"); } sqlQuery->MarkerDeleteAll(1); execQuery(sql, resultToRetrieve, true, offset, false, true, verbose); } void frmQuery::OnCommit(wxCommandEvent &event) { execQuery(wxT("COMMIT;")); } void frmQuery::OnRollback(wxCommandEvent &event) { execQuery(wxT("ROLLBACK;")); } // Update the main SQL query from the GQB if desired bool frmQuery::updateFromGqb(bool executing) { if (closing) return false; // Make sure this doesn't get call recursively through an event if (gqbUpdateRunning) return false; updateMenu(); gqbUpdateRunning = true; // Execute Generation of SQL sentence from GQB bool canGenerate = false; wxString newQuery = controller->generateSQL(); // If the new query is empty, don't do anything if (newQuery.IsEmpty()) { if (controller->getTableCount() > 0) { wxMessageBox(_("No SQL query was generated."), _("Graphical Query Builder"), wxICON_INFORMATION | wxOK); } gqbUpdateRunning = false; return false; } // Only prompt the user if the dirty flag is set, and last modification wasn't from GQB, // and the textbox is not empty, and the new query is different. if (sqlQuery->IsChanged() && sqlQuery->GetOrigin() != ORIGIN_GQB && !sqlQuery->GetText().Trim().IsEmpty() && sqlQuery->GetText() != newQuery + wxT("\n")) { wxString fn; if (executing) fn = _("The generated SQL query has changed.\nDo you want to update it and execute the query?"); else fn = _("The generated SQL query has changed.\nDo you want to update it?"); wxMessageDialog msg(this, fn, _("Query"), wxYES_NO | wxICON_EXCLAMATION); if(msg.ShowModal() == wxID_YES && sqlQuery->IsChanged()) { canGenerate = true; } else { gqbUpdateRunning = false; } } else { canGenerate = true; } if(canGenerate) { sqlQuery->SetText(newQuery + wxT("\n")); sqlQuery->Colourise(0, sqlQuery->GetLength()); wxSafeYield(); // needed to process sqlQuery modify event sqlNotebook->SetSelection(0); sqlQuery->SetChanged(true); sqlQuery->SetOrigin(ORIGIN_GQB); setExtendedTitle(); gqbUpdateRunning = false; return true; } return false; } void frmQuery::SelectQuery() { long p; bool selected = false; //sqlQuery->GetSelection(); wxString name = sqlQuery->GetSelectedText(); int s,e,i=0; if (!name.IsEmpty()) { // never execute //name = sqlQuery->GetTextRange(startPos, endPos); //selected = false; } else { int curPos = sqlQuery->GetCurrentPos(); auto [s,e] = sqlQuery->SelectQuery(curPos); // группы серверов/Серверы/serverN/Datebases/dbname sqlQuery->SetSelection(s,e); } } void frmQuery::OnExecuteShift(wxCommandEvent &event) { //add new page outpane int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]); wxString titlename; for (int i=0;iAddPage(sqlResult, titlename); sqlResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); indexResult=i; ctlSQL[i]=sqlResult; ctlSBox[i]=sqlQuery; break; }; OnExecute(event); } void frmQuery::OnExecute(wxCommandEvent &event) { if(sqlNotebook->GetSelection() == 1) { if (!updateFromGqb(true)) return; } CheckModificationFile(); SaveTempFile(); wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) { if (queryMenu->IsChecked(MNU_AUTOSELECTQUERY)) { // Auto-select SelectQuery(); query = sqlQuery->GetSelectedText(); } else query = sqlQuery->GetText(); } if (query.IsNull()) return; // set marker sqlQueryExec->MarkerAdd(line, 0); // wxSTC_MARK_CIRCLE int en=sqlQuery->GetSelectionEnd(); int st=-1; if (sqlQueryExecLast==sqlQuery) sqlQuery->MarkerDeleteAll(1); if (en>=0) { st=sqlQuery->GetSelectionStart(); int hline=sqlQuery->LineFromPosition(st); int eline=sqlQuery->LineFromPosition(en); for (int i=hline;i<=eline;i++) { sqlQuery->MarkerAdd(i,1); } //sqlResult->SetRangeLineExecuteSQL(hline,eline); } if (settings->GetReplaceVars()) { //check replace parameters FSQL::FormatterSQL f(query); FSQL::view_item v; bool isddm = false; std::vector v_list; body_template.Clear(); title_template.Clear(); while (f.GetNextPositionSqlParse() < query.length() && f.ParseSql(0) >= 0) { // many querys int i = 0; int n_check = 0; while (f.GetItem(i++, v)) { if (n_check == 0 && v.type == FSQL::type_item::keyword) { wxString kw = v.txt.Upper(); if (kw == "WITH" || kw == "SELECT" || kw == "UPDATE" || kw == "INSERT" || kw == "DELETE") { isddm = true; } n_check++; } if (v.type == FSQL::type_item::comment) { wxString kw = v.txt; if (kw.Find("@gen:")>0) { wxString t=kw.AfterFirst(':'); body_template.Add(t.AfterFirst(':')); title_template.Add(t.BeforeFirst(':')); } } // check bindarg if (n_check == 1 && v.type == FSQL::type_item::bindarg) { if (!isddm) break; v_list.push_back({ v.srcpos,v.txt,"" }); } } if (isddm && v_list.size() > 0 && f.GetNextPositionSqlParse() >= query.length()) { dlgVariable* m_dlgVar = new dlgVariable(sqlQuery, query, v_list); int rez = m_dlgVar->ShowModal(); if (rez == wxID_OK) { query = m_dlgVar->GetQuery(); } else if (rez == wxID_IGNORE) { } else { } m_dlgVar->Destroy(); if (rez == wxID_CANCEL) { return; } break; } } } execQuery(query); sqlQuery->SetFocus(); } void frmQuery::OnExecScript(wxCommandEvent &event) { // Get the script wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) query = sqlQuery->GetText(); if (query.IsNull()) return; // Make sure pgScript is not already running // Required because the pgScript parser isn't currently thread-safe :-( if (frmQuery::ms_pgScriptRunning == true) { wxMessageBox(_("pgScript already running."), _("Concurrent execution of pgScripts is not supported at this time."), wxICON_WARNING | wxOK); return; } frmQuery::ms_pgScriptRunning = true; // Clear markers and indicators sqlQuery->MarkerDeleteAll(0); sqlQuery->StartStyling(0); sqlQuery->SetStyling(sqlQuery->GetText().Length(), 0); // Menu stuff to initialize setTools(true); queryMenu->Enable(MNU_SAVEHISTORY, true); queryMenu->Enable(MNU_CLEARHISTORY, true); // Window stuff explainCanvas->Clear(); msgResult->Clear(); msgResult->SetFont(settings->GetSQLFont()); outputPane->SetSelection(2); // Status text SetStatusText(wxT(""), STATUSPOS_SECS); SetStatusText(_("pgScript is running."), STATUSPOS_MSGS); SetStatusText(wxT(""), STATUSPOS_ROWS); // History msgHistory->AppendText(_("-- Executing pgScript\n")); Update(); wxTheApp->Yield(true); // Timer startTimeQuery = wxGetLocalTimeMillis(); timer.Start(10); // Delete previous variables pgScript->ClearSymbols(); // Parse script. Note that we add \n so the parse can correctly identify // a comment on the last line of the query. pgScript->ParseString(query + wxT("\n"), pgsOutput); pgsTimer->Start(20); aborted = false; } void frmQuery::OnExecFile(wxCommandEvent &event) { if(sqlNotebook->GetSelection() == 1) { if (!updateFromGqb(true)) return; } wxString query = sqlQuery->GetSelectedText(); if (query.IsNull()) query = sqlQuery->GetText(); if (query.IsNull()) return; execQuery(query, 0, false, 0, true); sqlQuery->SetFocus(); } void frmQuery::OnAutoReplaceManage(wxCommandEvent &event) { //if (autoreplace) delete //macros = queryMacroFileProvider::LoadMacros(true); int r = dlgManageMacros(this, mainForm, autoreplace).ManageMacros(); if (r == 1) { // Changed something, so save queryMacroFileProvider::SaveAutoReplace(autoreplace); } } void frmQuery::OnMacroManage(wxCommandEvent &event) { int r = dlgManageMacros(this, mainForm, macros).ManageMacros(); if (r == 1) { // Changed something, so save queryMacroFileProvider::SaveMacros(macros); } if (r == -1 || r == 1) { // Changed something requiring rollback mainForm->UpdateAllMacrosList(); } } void frmQuery::OnMacroInvoke(wxCommandEvent &event) { queryMacroItem *mac; mac = macros->FindMacro(event.GetId()); if (!mac) return; wxString query = mac->GetQuery(); if (query.IsEmpty()) return; // do not execute empty query if (query.Find(wxT("$SELECTION$")) != wxNOT_FOUND) { wxString selection = sqlQuery->GetSelectedText(); if (selection.IsEmpty()) { wxMessageBox(_("This macro includes a text substitution. Please select some text in the SQL pane and re-run the macro."), _("Execute macro"), wxICON_EXCLAMATION | wxOK); return; } query.Replace(wxT("$SELECTION$"), selection); } execQuery(query); sqlQuery->SetFocus(); } void frmQuery::setTools(const bool running) { bool canEndTransaction = (!running && conn->GetTxStatus() != PQTRANS_IDLE); toolBar->EnableTool(MNU_EXECUTE, !running); toolBar->EnableTool(MNU_EXECUTE_2, !running); toolBar->EnableTool(MNU_EXECPGS, !running); toolBar->EnableTool(MNU_EXECFILE, !running); toolBar->EnableTool(MNU_EXPLAIN, !running); toolBar->EnableTool(MNU_CANCEL, running); toolBar->EnableTool(MNU_DOCOMMIT, canEndTransaction); toolBar->EnableTool(MNU_DOROLLBACK, canEndTransaction); queryMenu->Enable(MNU_EXECUTE, !running); queryMenu->Enable(MNU_EXECUTE_2, !running); queryMenu->Enable(MNU_EXECPGS, !running); queryMenu->Enable(MNU_EXECFILE, !running); queryMenu->Enable(MNU_EXPLAIN, !running); queryMenu->Enable(MNU_EXPLAINANALYZE, !running); queryMenu->Enable(MNU_CANCEL, running); queryMenu->Enable(MNU_DOCOMMIT, canEndTransaction); queryMenu->Enable(MNU_DOROLLBACK, canEndTransaction); fileMenu->Enable(MNU_EXPORT, sqlResult->CanExport()); fileMenu->Enable(MNU_QUICKREPORT, sqlResult->CanExport()); fileMenu->Enable(MNU_RECENT, (recentFileMenu->GetMenuItemCount() > 0)); sqlQuery->EnableAutoComp(running); sqlQuery->SetSQLBoxColourBackground(canEndTransaction); } void frmQuery::showMessage(const wxString &msg, const wxString &msgShort) { msgResult->AppendText(msg + wxT("\n")); msgHistory->AppendText(msg + wxT("\n")); wxString str; if (msgShort.IsNull()) str = msg; else str = msgShort; str.Replace(wxT("\n"), wxT(" ")); SetStatusText(str, STATUSPOS_MSGS); } void frmQuery::execQuery(const wxString &query, int resultToRetrieve, bool singleResult, const int queryOffset, bool toFile, bool explain, bool verbose) { setTools(true); queryMenu->Enable(MNU_SAVEHISTORY, true); queryMenu->Enable(MNU_CLEARHISTORY, true); explainCanvas->Clear(); // Clear markers and indicators sqlQuery->MarkerDeleteAll(0); //sqlQuery->StartStyling(0); //sqlQuery->SetStyling(sqlQuery->GetText().Length(), 0); int i=sqlQueryBook->GetSelection(); sqlQueryBook->SetPageBitmap(i,CreateBitmap(wxColour(255,0,0))); if (!sqlQuery->IsChanged()) setExtendedTitle(); aborted = false; isfilterresult=false; sqlResult=ctlSQL[indexResult]; sqlResult->ClearFilter(); ctlSBox[indexResult]=sqlQuery; // int idx=outputPane->GetPageIndex(sqlResult); outputPane->SetPageBitmap(idx,CreateBitmap(wxNullColour)); QueryExecInfo *qi = new QueryExecInfo(); qi->queryOffset = queryOffset; qi->toFileExportForm = NULL; qi->singleResult = singleResult; qi->explain = explain; qi->verbose = verbose; if (toFile) { qi->toFileExportForm = new frmExport(this); if (qi->toFileExportForm->ShowModal() != wxID_OK) { delete qi; setTools(false); aborted = true; return; } } // Remember the tab from which execute was called. By the time query completes, SQL tab selection may change. sqlQueryExec = sqlQuery; // Because the output pane is clear during query execution, we clear the result source title on Output Pane. sqlQueryExecLast = NULL; SetOutputPaneCaption(true); // We must do this lot before the query starts, otherwise // it might not happen once the main thread gets busy with // other stuff. SetStatusText(wxT(""), STATUSPOS_SECS); SetStatusText(_("Query is running."), STATUSPOS_MSGS); SetStatusText(wxT(""), STATUSPOS_ROWS); msgResult->Clear(); msgResult->SetFont(settings->GetSQLFont()); msgHistory->AppendText(wxString::Format(_("-- Executing query [%s]:\n"), sqlQueryExec->GetTitle(false).c_str())); msgHistory->AppendText(query); msgHistory->AppendText(wxT("\n")); Update(); wxTheApp->Yield(true); startTimeQuery = wxGetLocalTimeMillis(); timer.Start(10); if (!queryMenu->IsChecked(MNU_AUTOCOMMIT) && conn->GetTxStatus() == PQTRANS_IDLE && !isBeginNotRequired(query)) conn->ExecuteVoid(wxT("BEGIN;")); if (sqlResult->Execute(query, resultToRetrieve, this, QUERY_COMPLETE, qi) >= 0) { // Return and wait for the result return; } completeQuery(false, false, false); } bool frmQuery::isBeginNotRequired(wxString query) { int wordlen = 0; query = query.Trim(false); size_t queryLen = query.Len(); /* * Check word length (since "beginx" is not "begin"). */ while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; /* * Transaction control commands. These should include every keyword that * gives rise to a TransactionStmt in the backend grammar, except for the * savepoint-related commands. * * (We assume that START must be START TRANSACTION, since there is * presently no other "START foo" command.) */ wxString keyword = query.SubString(0, wordlen - 1); if (wordlen == 5 && keyword.CmpNoCase(wxT("abort")) == 0) return true; if (wordlen == 5 && keyword.CmpNoCase(wxT("begin")) == 0) return true; if (wordlen == 5 && keyword.CmpNoCase(wxT("start")) == 0) return true; if (wordlen == 6 && keyword.CmpNoCase(wxT("commit")) == 0) return true; if (wordlen == 3 && keyword.CmpNoCase(wxT("end")) == 0) return true; if (wordlen == 8 && keyword.CmpNoCase(wxT("rollback")) == 0) return true; if (wordlen == 7 && keyword.CmpNoCase(wxT("prepare")) == 0) { /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */ query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); if (wordlen == 11 && keyword.CmpNoCase(wxT("transaction")) == 0) return true; return false; } /* * Commands not allowed within transactions. The statements checked for * here should be exactly those that call PreventTransactionChain() in the * backend. */ if (wordlen == 6 && keyword.CmpNoCase(wxT("vacuum")) == 0) return true; if (wordlen == 7 && keyword.CmpNoCase(wxT("cluster")) == 0) { /* CLUSTER with any arguments is allowed in transactions */ query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); if(wxIsalpha(((wxChar)query.at(0)))) return false; /* has additional words */ return true; /* it's CLUSTER without arguments */ } if (wordlen == 6 && keyword.CmpNoCase(wxT("create")) == 0) { query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); if (wordlen == 8 && keyword.CmpNoCase(wxT("database")) == 0) return true; if (wordlen == 10 && keyword.CmpNoCase(wxT("tablespace")) == 0) return true; /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */ if (wordlen == 6 && keyword.CmpNoCase(wxT("cluster")) == 0) { query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); } if (wordlen == 5 && keyword.CmpNoCase(wxT("index")) == 0) { query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); if (wordlen == 12 && keyword.CmpNoCase(wxT("concurrently")) == 0) return true; } return false; } if (wordlen == 5 && keyword.CmpNoCase(wxT("alter")) == 0) { query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); /* ALTER SYSTEM isn't allowed in xacts */ if (wordlen == 6 && keyword.CmpNoCase(wxT("system")) == 0) return true; return false; } /* * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which * aren't really valid commands so we don't care much. The other four * possible matches are correct. */ if ((wordlen == 4 && keyword.CmpNoCase(wxT("drop")) == 0) || (wordlen == 7 && keyword.CmpNoCase(wxT("reindex")) == 0)) { query = query.SubString(wordlen , queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); if (wordlen == 8 && keyword.CmpNoCase(wxT("database")) == 0) return true; if (wordlen == 6 && keyword.CmpNoCase(wxT("system")) == 0) return true; if (wordlen == 10 && keyword.CmpNoCase(wxT("tablespace")) == 0) return true; return false; } /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */ if (wordlen == 7 && keyword.CmpNoCase(wxT("discard")) == 0) { query = query.SubString(wordlen, queryLen - 1); query = query.Trim(false); queryLen = query.Len(); wordlen = 0; while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen))) wordlen++; keyword = query.SubString(0, wordlen - 1); if (wordlen == 3 && keyword.CmpNoCase(wxT("all")) == 0) return true; return false; } return false; } // When the query completes, it raises an event which we process here. void frmQuery::OnQueryComplete(pgQueryResultEvent &ev) { QueryExecInfo *qi = (QueryExecInfo *)ev.GetClientData(); bool done = false; while (sqlResult->RunStatus() == CTLSQL_RUNNING) { wxTheApp->Yield(true); } while (pgScript->IsRunning()) { wxLogInfo(wxT("SQL Query box: Waiting for script to abort")); wxSleep(1); } timer.Stop(); wxString str; str = sqlResult->GetMessagesAndClear(); //if (!str.IsEmpty()) //{ // wxString msg; // msgHistory->AppendText(str + wxT("\n")); // wxRegEx multilf(wxT("(CONTEXT:.*$)")); // multilf.ReplaceAll(&str, wxT("")); // //} msgResult->AppendText(str); msgHistory->AppendText(str); elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery; SetStatusText(ElapsedTimeToStr(elapsedQuery), STATUSPOS_SECS); if (sqlResult->RunStatus() != PGRES_TUPLES_OK) { outputPane->SetSelection(2); if (sqlResult->RunStatus() == PGRES_COMMAND_OK) { done = true; int insertedCount = sqlResult->InsertedCount(); OID insertedOid = sqlResult->InsertedOid(); if (insertedCount < 0) { showMessage( wxString::Format( _("Query returned successfully with no result in %s."), ElapsedTimeToStr(elapsedQuery).c_str() ), _("OK.") ); } else if (insertedCount == 1) { if (insertedOid) { showMessage( wxString::Format( _("Query returned successfully: one row with OID %ld inserted, %s execution time."), (long)insertedOid, ElapsedTimeToStr(elapsedQuery).c_str()), wxString::Format( _("One row with OID %ld inserted."), (long)insertedOid ) ); } else { showMessage( wxString::Format( _("Query returned successfully: one row affected, %s execution time."), ElapsedTimeToStr(elapsedQuery).c_str()), wxString::Format(_("One row affected.")) ); } } else { showMessage( wxString::Format( _("Query returned successfully: %d rows affected, %s execution time."), insertedCount, ElapsedTimeToStr(elapsedQuery).c_str() ), wxString::Format( _("%d rows affected."), insertedCount ) ); } } else if (sqlResult->RunStatus() == PGRES_EMPTY_QUERY) { showMessage(_("Empty query, no results.")); } else if (ev.GetInt() == pgQueryResultEvent::PGQ_EXECUTION_CANCELLED) { showMessage(_("Execution Cancelled!")); } else { wxString errMsg, errMsg2; long errPos; pgError err = sqlResult->GetResultError(); errMsg = err.formatted_msg; wxLogQuietError(wxT("%s"), conn->GetLastError().Trim().c_str()); err.statement_pos.ToLong(&errPos); if (err.sql_state.IsEmpty()) { if (wxMessageBox(_("Do you want to attempt to reconnect to the database?"), wxString::Format(_("Connection to database %s lost."), conn->GetDbname().c_str()), wxICON_EXCLAMATION | wxYES_NO) == wxYES) { conn->Reset(); errMsg2 = _("Connection reset."); } } showMessage(wxString::Format(wxT("********** %s **********\n"), _("Error"))); showMessage(errMsg); if (!errMsg2.IsEmpty()) showMessage(errMsg2); if (errPos > 0 && sqlQueryExec != NULL) { int selStart = sqlQueryExec->GetSelectionStart(), selEnd = sqlQueryExec->GetSelectionEnd(); if (selStart == selEnd) selStart = 0; errPos -= qi->queryOffset; // do not count EXPLAIN or similar // if exists UNICODE correct errPos errPos = sqlQueryExec->PositionRelative(selStart, errPos - 1); //if () errPos // Set an indicator on the error word (break on any kind of bracket, a space or full stop) int sPos = errPos, wEnd = 1; //sqlQueryExec->StartStyling(sPos, wxSTC_INDICS_MASK); int c = sqlQueryExec->GetCharAt(sPos + wEnd); size_t len = sqlQueryExec->GetLength(); while(c != ' ' && c != '(' && c != '{' && c != '[' && c != '.' && (unsigned int)(sPos + wEnd) < len) { wEnd++; c = sqlQueryExec->GetCharAt(sPos + wEnd); } //sqlQueryExec->SetStyling(wEnd, wxSTC_INDIC0_MASK); int line = 0, maxLine = sqlQueryExec->GetLineCount(); while (line < maxLine && sqlQueryExec->GetLineEndPosition(line) < errPos + 1) line++; if (line < maxLine) { sqlQueryExec->GotoPos(sPos); // wxSTC_MARK_ARROW = 2 sqlQueryExec->MarkerAdd(line, 0); // wxSTC_MARK_CIRCLE if (!sqlQueryExec->IsChanged()) setExtendedTitle(); sqlQueryExec->EnsureVisible(line); } } } } else { done = true; for(int i=0;iGetPageCount();i++) { if (wxDynamicCast(outputPane->GetPage(i), ctlSQLResult)==sqlResult) { outputPane->SetSelection(i); } } long rowsTotal = sqlResult->NumRows(); if (qi->toFileExportForm) { SetStatusText(wxString::Format(wxPLURAL("%d row.", "%d rows.", rowsTotal), rowsTotal), STATUSPOS_ROWS); if (rowsTotal) { SetStatusText(_("Writing data."), STATUSPOS_MSGS); toolBar->EnableTool(MNU_CANCEL, false); queryMenu->Enable(MNU_CANCEL, false); SetCursor(*wxHOURGLASS_CURSOR); if (sqlResult->ToFile(qi->toFileExportForm)) SetStatusText(_("Data written to file."), STATUSPOS_MSGS); else SetStatusText(_("Data export aborted."), STATUSPOS_MSGS); SetCursor(wxNullCursor); } else SetStatusText(_("No data to export."), STATUSPOS_MSGS); } else { if (qi->singleResult) { sqlResult->DisplayData(true); showMessage(wxString::Format( wxPLURAL("%ld row retrieved.", "%ld rows retrieved.", sqlResult->NumRows()), sqlResult->NumRows()), _("OK.")); } else { SetStatusText( wxString::Format( wxPLURAL( "Retrieving data: %d row.", "Retrieving data: %d rows.", (int)rowsTotal), (int)rowsTotal), STATUSPOS_MSGS); wxTheApp->Yield(true); sqlResult->DisplayData(); SetStatusText( ElapsedTimeToStr(elapsedQuery), STATUSPOS_SECS ); str = wxString::Format( _("Total query runtime: %s\n"), ElapsedTimeToStr(elapsedQuery).c_str() ); msgResult->AppendText(str); msgHistory->AppendText(str); showMessage( wxString::Format( wxPLURAL( "%d row retrieved.", "%d rows retrieved.", (int)sqlResult->NumRows() ), (int)sqlResult->NumRows() ), _("OK.") ); } SetStatusText( wxString::Format( wxPLURAL( "%ld row.", "%ld rows.", rowsTotal ), rowsTotal ), STATUSPOS_ROWS ); } } if (sqlResult->RunStatus() == PGRES_TUPLES_OK || sqlResult->RunStatus() == PGRES_COMMAND_OK) { // Get the executed query wxString executedQuery = sqlQueryExec->GetSelectedText(); if (executedQuery.IsNull()) executedQuery = sqlQueryExec->GetText(); // Same query, but without return feeds and carriage returns wxString executedQueryWithoutReturns = executedQuery; executedQueryWithoutReturns.Replace(wxT("\n"), wxT(" ")); executedQueryWithoutReturns.Replace(wxT("\r"), wxT(" ")); executedQueryWithoutReturns = executedQueryWithoutReturns.Trim(); if (executedQuery.Len() < (unsigned int)settings->GetHistoryMaxQuerySize()) { // We put in the combo box the query without returns... sqlQueries->Append(executedQueryWithoutReturns); // .. but we save the query with returns in the array // (so that we have the real query in the file) histoQueries.Add(executedQuery); // Finally, we save the queries SaveQueries(); } // Search a matching old query unsigned int index = 0; bool found = false; while (!found && index < sqlQueries->GetCount()) { found = sqlQueries->GetString(index) == executedQueryWithoutReturns; if (!found) index++; } // If we found one, delete it from the combobox and the array if (found && index < (unsigned int)sqlQueries->GetCount() - 1) { histoQueries.RemoveAt(index); sqlQueries->Delete(index); } } // Make sure only the maximum query number is enforced while (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries()) { histoQueries.RemoveAt(0); sqlQueries->Delete(0); } SaveQueries(); completeQuery(done, qi->explain, qi->verbose); delete qi; } void frmQuery::OnScriptComplete(wxCommandEvent &ev) { // Stop timers timer.Stop(); pgsTimer->Stop(); // Write output writeScriptOutput(); // Reset tools setTools(false); // Unlock our pseudo-mutex thingy frmQuery::ms_pgScriptRunning = false; // Manage timer elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery; wxString fmtExecTime = ElapsedTimeToStr(elapsedQuery); SetStatusText(fmtExecTime, STATUSPOS_SECS); SetStatusText(_("pgScript completed."), STATUSPOS_MSGS); msgHistory->AppendText( wxString::Format( _("Total pgScript runtime: %s\n\n"), fmtExecTime.c_str() ) ); // Check whether there was an error/exception if (pgScript->errorOccurred() && pgScript->errorLine() >= 1) { // Find out what the line number is int selStart = sqlQuery->GetSelectionStart(), selEnd = sqlQuery->GetSelectionEnd(); if (selStart == selEnd) selStart = 0; int line = 0, maxLine = sqlQuery->GetLineCount(); while (line < maxLine && sqlQuery->GetLineEndPosition(line) < selStart) line++; line += pgScript->errorLine() - 1; // Mark the line where the error occurred sqlQuery->MarkerAdd(line, 0); // Go to that line sqlQuery->GotoPos(sqlQuery->GetLineEndPosition(line)); } } void frmQuery::writeScriptOutput() { pgScript->LockOutput(); wxString output(pgsOutputString); pgsOutputString.Clear(); msgResult->AppendText(output); pgScript->UnlockOutput(); } // Complete the processing of a query void frmQuery::completeQuery(bool done, bool explain, bool verbose) { // Display async notifications pgNotification *notify; int notifies = 0; notify = conn->GetNotification(); while (notify) { wxString notifyStr; notifies++; if (notify->data.IsEmpty()) notifyStr.Printf(_("\nAsynchronous notification of '%s' received from backend pid %d"), notify->name.c_str(), notify->pid); else notifyStr.Printf(_("\nAsynchronous notification of '%s' received from backend pid %d\n Data: %s"), notify->name.c_str(), notify->pid, notify->data.c_str()); msgResult->AppendText(notifyStr); msgHistory->AppendText(notifyStr); notify = conn->GetNotification(); } if (notifies) { wxString statusMsg = statusBar->GetStatusText(STATUSPOS_MSGS); if (statusMsg.Last() == '.') statusMsg = statusMsg.Left(statusMsg.Length() - 1); SetStatusText(wxString::Format( wxPLURAL("%s (%d asynchronous notification received).", "%s (%d asynchronous notifications received).", notifies), statusMsg.c_str(), notifies), STATUSPOS_MSGS); } msgResult->AppendText(wxT("\n")); msgResult->ShowPosition(0); msgHistory->AppendText(wxT("\n")); msgHistory->ShowPosition(0); // If the transaction aborted for some reason, issue a rollback to cleanup. if (queryMenu->IsChecked(MNU_AUTOROLLBACK) && conn->GetTxStatus() == PGCONN_TXSTATUS_INERROR) conn->ExecuteVoid(wxT("ROLLBACK;")); setTools(false); fileMenu->Enable(MNU_EXPORT, sqlResult->CanExport()); if ((!IsActive() || IsIconized())|| (elapsedQuery>120*1000)) RequestUserAttention(); if (!viewMenu->IsChecked(MNU_OUTPUTPANE)) { viewMenu->Check(MNU_OUTPUTPANE, true); manager.GetPane(wxT("outputPane")).Show(true); manager.Update(); } // If this was an EXPLAIN query, process the results if (done && explain) { if (!verbose || conn->BackendMinimumVersion(8, 4)) { int i; wxString str; if (sqlResult->NumRows() == 1) { // Avoid shared storage issues with strings str.Append(sqlResult->OnGetItemText(0, 0).c_str()); } else { for (i = 0 ; i < sqlResult->NumRows() ; i++) { if (i) str.Append(wxT("\n")); str.Append(sqlResult->OnGetItemText(i, 0)); } } explainCanvas->SetExplainString(str); outputPane->SetSelection(1); } updateMenu(); } // Change the output pane caption so the user knows which tab the result came from sqlQueryExecLast = sqlQueryExec; SetOutputPaneCaption(true); for (int i=0;iGetPageCount();i++) if ((sqlQueryBook->GetPageBitmap(i)).IsOk()) sqlQueryBook->SetPageBitmap(i,wxNullBitmap); //int i=sqlQueryBook->GetPageCount()-1; //sqlQueryBook->SetPageBitmap(i,CreateBitmap(wxNullColour)); //int i=sqlQueryBook->GetSelection() if (); sqlQueryExec = NULL; sqlQuery->SetFocus(); } void frmQuery::OnTimer(wxTimerEvent &event) { elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery; SetStatusText(ElapsedTimeToStr(elapsedQuery), STATUSPOS_SECS); wxString str = sqlResult->GetMessagesAndClear(); if (!str.IsEmpty()) { // wxString msg; // msgHistory->AppendText(str + wxT("\n")); // wxRegEx multilf(wxT("(CONTEXT:.*$)")); // multilf.ReplaceAll(&str, wxT("")); // msgResult->AppendText(str + wxT("\n")); // msgHistory->AppendText(str + wxT("\n")); msgResult->AppendText(str + wxT("\n")); } // Increase the granularity for longer running queries if (timer.IsRunning()) { // Set timer to fire every 100 ms if >200 ms elapsed if (elapsedQuery > 200 && timer.GetInterval() < 100) { timer.Stop(); timer.Start(100); } // Set timer to fire every 1000 ms if >60 seconds elapsed else if (elapsedQuery > 60 * 1000 && timer.GetInterval() < 1000) { timer.Stop(); timer.Start(1000); } } } // Adjust sizes of GQB components, Located here because need to // avoid some issues when implementing inside controller/view Classes void frmQuery::adjustGQBSizes() { // Get Size (only height) from main Tab with GQB and SQL Editor and adjust the width // to desiree, then set [Sash of tablesBrowser | GQB_Canvas] manager.Update(); sqlNotebook->Refresh(); wxSize s = sqlNotebook->GetSize(); s.SetWidth(200); s.SetHeight(s.GetHeight() - 180); //re-adjust weight eliminating Horz Sash Position controller->getTablesBrowser()->SetSize(s); controller->setSashVertPosition(controller->getTablesBrowser()->GetSize().GetWidth()); // Now Adjust Sash Horizontal s = sqlNotebook->GetSize(); controller->setSashHorizPosition(s.GetHeight() - 150); // Adjust GQB grids internal columns sizes controller->calcGridColsSizes(); } // Adjust sizes of GQB components after vertical sash adjustment, // Located here because need to avoid some issues when implementing // inside controller/view Classes void frmQuery::OnResizeHorizontally(wxSplitterEvent &event) { int y = event.GetSashPosition(); wxSize s = controller->getTablesBrowser()->GetSize(); s.SetHeight(y); // re-adjust weight eliminating Horz Sash Position controller->getTablesBrowser()->SetSize(s); } // This function adjust the GQB Components after an event on the wxAui // event, it's a workaround because need event finish to work properly void frmQuery::OnAdjustSizesTimer(wxTimerEvent &event) { adjustGQBSizes(); adjustSizesTimer->Stop(); } void frmQuery::OnBlockIndent(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->CmdKeyExecute(wxSTC_CMD_TAB); else if (FindFocus()->GetId() == CTL_SCRATCHPAD) scratchPad->WriteText(wxT("\t")); } void frmQuery::OnBlockOutDent(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->CmdKeyExecute(wxSTC_CMD_BACKTAB); } void frmQuery::OnChangeToUpperCase(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->UpperCase(); } void frmQuery::OnChangeToLowerCase(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->LowerCase(); } void frmQuery::OnCommentText(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->BlockComment(false); } void frmQuery::OnUncommentText(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->BlockComment(true); } void frmQuery::OnDoubleText(wxCommandEvent& event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->BlockDouble(false); } void frmQuery::OnUnDoubleText(wxCommandEvent& event) { if (FindFocus()->GetId() == CTL_SQLQUERY) sqlQuery->BlockDouble(true); } void frmQuery::OnExternalFormat(wxCommandEvent &event) { if (FindFocus()->GetId() == CTL_SQLQUERY) { wxBusyCursor wait; SetStatusText(_("Running formatting command..."), STATUSPOS_MSGS); SetStatusText(sqlQuery->ExternalFormat(), STATUSPOS_MSGS); sqlQuery->SetFocus(); // could loose focus after running formatting process } } void frmQuery::OnExternalAlign(wxCommandEvent& event) { if (FindFocus()->GetId() == CTL_SQLQUERY) { wxBusyCursor wait; SetStatusText(_("Running aligning command..."), STATUSPOS_MSGS); SetStatusText(sqlQuery->ExternalFormat(1), STATUSPOS_MSGS); sqlQuery->SetFocus(); // could loose focus after running formatting process } } wxBitmap frmQuery::CreateBitmap(const wxColour &colour) { const int w = 10, h = 10; wxMemoryDC dc; wxBitmap bmp(w, h); dc.SelectObject(bmp); if (colour == wxNullColour) dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW))); else dc.SetBrush(wxBrush(colour)); dc.DrawRectangle(0, 0, w, h); return bmp; } wxColour frmQuery::GetServerColour(pgConn *connection) { wxColour tmp = wxNullColour; if (mainForm != NULL) { ctlTree *browser = mainForm->GetBrowser(); wxTreeItemIdValue foldercookie, servercookie; wxTreeItemId folderitem, serveritem; pgObject *object; pgServer *server; folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie); while (folderitem) { if (browser->ItemHasChildren(folderitem)) { serveritem = browser->GetFirstChild(folderitem, servercookie); while (serveritem) { object = browser->GetObject(serveritem); if (object && object->IsCreatedBy(serverFactory)) { server = (pgServer *)object; if (server->GetConnected() && server->GetConnection()->GetHost() == connection->GetHost() && server->GetConnection()->GetPort() == connection->GetPort()) { tmp = wxColour(server->GetColour()); } } serveritem = browser->GetNextChild(folderitem, servercookie); } } folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie); } } return tmp; } void frmQuery::LoadQueries() { xmlDocPtr doc; xmlNodePtr cur; xmlChar *key; if (!wxFile::Access(settings->GetHistoryFile(), wxFile::read)) return; doc = xmlParseFile((const char *)settings->GetHistoryFile().mb_str(wxConvUTF8)); if (doc == NULL) { wxMessageBox(_("Failed to load the history file!")); ::wxRemoveFile(settings->GetHistoryFile()); return; } cur = xmlDocGetRootElement(doc); if (cur == NULL) { xmlFreeDoc(doc); return; } if (xmlStrcmp(cur->name, (const xmlChar *) "histoqueries")) { wxMessageBox(_("Failed to load the history file!")); xmlFreeDoc(doc); ::wxRemoveFile(settings->GetHistoryFile()); return; } cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"histoquery"))) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if (key) { if (WXSTRING_FROM_XML(key) != wxT("")) { wxString query = WXSTRING_FROM_XML(key); wxString tmp = query; tmp.Replace(wxT("\n"), wxT(" ")); tmp.Replace(wxT("\r"), wxT(" ")); sqlQueries->Append(tmp); histoQueries.Add(query); } xmlFree(key); } } cur = cur->next; } xmlFreeDoc(doc); // Make sure only the maximum query number is enforced if (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries()) { while (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries()) { histoQueries.RemoveAt(0); sqlQueries->Delete(0); } SaveQueries(); } return; } void frmQuery::SaveQueries() { size_t i; xmlTextWriterPtr writer; writer = xmlNewTextWriterFilename((const char *)settings->GetHistoryFile().mb_str(wxConvUTF8), 0); if (!writer) { wxMessageBox(_("Failed to write to history file!")); return; } xmlTextWriterSetIndent(writer, 1); if ((xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) || (xmlTextWriterStartElement(writer, XML_STR("histoqueries")) < 0)) { wxMessageBox(_("Failed to write to history file!")); xmlFreeTextWriter(writer); return; } for (i = 0; i < histoQueries.GetCount(); i++) { xmlTextWriterStartElement(writer, XML_STR("histoquery")); xmlTextWriterWriteString(writer, XML_FROM_WXSTRING(histoQueries.Item(i))); xmlTextWriterEndElement(writer); } if (xmlTextWriterEndDocument(writer) < 0) { wxMessageBox(_("Failed to write to history file!")); } xmlFreeTextWriter(writer); } void frmQuery::OnChangeQuery(wxCommandEvent &event) { wxString query = histoQueries.Item(sqlQueries->GetSelection()); if (query.Length() > 0) { sqlQuery->SetText(query); sqlQuery->Colourise(0, sqlQuery->GetLength()); wxSafeYield(); // needed to process sqlQuery modify event sqlQuery->SetChanged(true); sqlQuery->SetOrigin(ORIGIN_HISTORY); setExtendedTitle(); SetLineEndingStyle(); btnDeleteCurrent->Enable(true); } btnDeleteAll->Enable(sqlQueries->GetCount() > 0); } void frmQuery::OnDeleteCurrent(wxCommandEvent &event) { if ( wxMessageDialog(this, _("Delete current query from history?"), _("Confirm deletion"), wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION).ShowModal() == wxID_YES ) { histoQueries.RemoveAt(sqlQueries->GetSelection()); sqlQueries->Delete(sqlQueries->GetSelection()); sqlQueries->SetValue(wxT("")); btnDeleteCurrent->Enable(false); btnDeleteAll->Enable(sqlQueries->GetCount() > 0); SaveQueries(); } } void frmQuery::OnModeTransaction(wxCommandEvent &event) { queryMenu->Check(MNU_AUTOCOMMIT, !queryMenu->IsChecked(MNU_AUTOCOMMIT)); OnAutoCommit(event); } void frmQuery::OnDeleteAll(wxCommandEvent &event) { if ( wxMessageDialog(this, _("Delete all queries from history?"), _("Confirm deletion"), wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION).ShowModal() == wxID_YES ) { histoQueries.Clear(); sqlQueries->Clear(); sqlQueries->SetValue(wxT("")); btnDeleteCurrent->Enable(false); btnDeleteAll->Enable(false); SaveQueries(); } } void frmQuery::BeginPerspectiveChange() { manager.GetPane(_("outputPane")).Caption(_("Output pane")); } void frmQuery::EndPerspectiveChange(bool update) { SetOutputPaneCaption(update); } void frmQuery::SetOutputPaneCaption(bool update) { wxString caption; wxString title; if (sqlQueryExecLast == NULL) caption = _("Output pane"); else { // We don't want to make it look like Output Pane has been changed, // so request the title without the change indicator title = sqlQueryExecLast->GetTitle(false); caption = wxString::Format(_("Output pane [%s]"), title.c_str()); } manager.GetPane(wxT("outputPane")).Caption(caption); if (update) manager.Update(); } // Methods related to SQL tabs // void frmQuery::fileMarkerActive(bool addOrRemove, const wxString &sqlTabName) { wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); wxString tabname = sqlTabName; if (sqlTabName.Find("*")>=0) tabname = sqlTabName.BeforeLast('*'); wxString fn = tempDir + wxT("_active.") + tabname + ".a"; //if (sqlTabName.Right(1)=='*' ) tabname= if (addOrRemove && autoSave) { //wxUtfFile file(fn, wxFile::write, wxFONTENCODING_UTF8); wxFile file(fn, wxFile::write); // remove any ohher files for (int i = 0; i < sqlQueryBook->GetPageCount(); i++) { wxString textpage = sqlQueryBook->GetPageText(i); if (tabname != textpage) { textpage = tempDir + "_active." + textpage + ".a"; if (wxFileName::FileExists(textpage)) wxRemoveFile(textpage); } } } else if (wxFileName::FileExists(fn)) wxRemoveFile(fn); } void frmQuery::CheckModificationFile() { if (sqlQuery!=NULL && sqlQuery->IsFileModification()) { if (wxMessageBox("File " + sqlQuery->GetFilename() + " has been changed.\nReload file?", "Reload sql file", wxICON_EXCLAMATION | wxYES_NO) == wxYES) OpenLastFile(); } } void frmQuery::OnSqlBookPageChanged(wxAuiNotebookEvent &event) { // Try to always keep sqlQuery variable pointing to the currently selected SQLBox. // When closing and removing all tabs, page count may be zero. if (sqlQueryBook->GetPageCount() > 0) { size_t curpage = sqlQueryBook->GetSelection(); sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox); if (sqlQuery != NULL) { // Update UI with chosen query's info SetEOLModeDisplay(sqlQuery->GetEOLMode()); setExtendedTitle(); curpage = outputPane->GetSelection(); ctlSQLResult *r; r=NULL; if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult)) { ctlSQLResult *r = wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult); } int pos=-1; //if (r!=NULL) for (int i=0;iGetPageIndex(ctlSQL[i]); if (ctlSBox[i]==sqlQuery) { outputPane->SetPageBitmap(idx,CreateBitmap(wxNullColour)); pos=i; } else { outputPane->SetPageBitmap(idx,wxNullBitmap); } } } sqlQuery->SetFocus(); if (sqlQueryBook->GetPageCount() > 1) fileMarkerActive(true, sqlQueryBook->GetPageText(sqlQueryBook->GetSelection())); //wxMessageBox(wxT("OnSqlBookPageChanged ")); CheckModificationFile(); updateMenu(false); wxTheApp->Yield(true); } } else { // This should help us find bugs (such as using sqlQuery after closing all tabs) much faster. sqlQuery = NULL; } } void frmQuery::OnSqlBookPageChanging(wxAuiNotebookEvent& event) { // Veto event while page change is prohibited. if (!SqlBookCanChangePage()) { event.Veto(); wxMessageBox(_("Cannot change to selected SQL tab now. Try again a bit later.")); } if (sqlQueryBook->GetPageCount() > 1) { int curpage = sqlQueryBook->GetSelection(); if (curpage!=wxNOT_FOUND) { sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox); if (sqlQuery != NULL) { //wxString activePage = sqlNotebook->GetPageText(curpage); wxString activePage = sqlQuery->GetTitle(false); fileMarkerActive(false, activePage); } } } } void frmQuery::OnSqlBookAddPage(wxCommandEvent &event) { if (SqlBookCanChangePage()) { wxString t = wxEmptyString; SqlBookAddPage(t); } else wxMessageBox(_("Cannot add a new SQL tab now. Try again a bit later.")); } void frmQuery::OnSqlBookPageClosed(wxAuiNotebookEvent &event) { //OnSqlBookPageChanged(event); //wxSleep(5); // wxMessageBox(wxT("OnSqlBookPageClosed end")); } void frmQuery::OnNotebookOutpaneTabRDown(wxAuiNotebookEvent &event) { //ctlSQL size_t curpage = outputPane->GetSelection(); if ( event.GetSelection()!=curpage) return; wxBitmap b=outputPane->GetPageBitmap(curpage); if (b.IsOk()) { if (sqlQuery!=NULL) { wxString sql=sqlResult->sqlquerytext; if (sql.StartsWith("EXPLAIN")) sql=sql.AfterFirst(')'); if (sql.StartsWith("\nBEGIN;\nEXPLAIN")) { sql=sql.AfterFirst(')'); //"\n;\nROLLBACK;" sql=sql.Mid(0,sql.Length()-12); } if (!sqlQuery->Find(sql,false,false,false,true,false,true)) { wxString t=sqlQuery->GetText(); if (t.Find(sql)>-1) { SetStatusText("Found",1); } } } } else { if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult)) { ctlSQLResult* c = wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult); int len = MAX_RESULT_COUNT; for (int i = 0; i < len; i++) if (ctlSQL[i] != NULL && c == ctlSQL[i]) { ctlSQLResult *sqlRes = ctlSQL[i]; ctlSQLBox *box= ctlSBox[i]; int querypage= sqlQueryBook->GetPageIndex(box); if (querypage >= 0) { sqlQueryBook->SetSelection(querypage); } break; } } } } void frmQuery::OnSqlBookTabRDown (wxAuiNotebookEvent &event) { size_t curpage = sqlQueryBook->GetSelection(); ctlSQLBox *sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox); wxString pref=conn->GetDbname()+wxT(".nametab"); wxTextEntryDialog dialog(this, wxT("Please enter name string with prefix dbname\n") , wxT("Name autosave tab window."), pref, wxOK | wxCANCEL); //setName( dlg.GetValue().wc_str() ); if (dialog.ShowModal() == wxID_OK) { wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); wxString filename=sqlQuery->GetTitle(false); wxString tf=tempDir+filename+".a"; if (wxFileName::FileExists(tf)) wxRemoveFile(tf); tf=tempDir + "_active."+filename + ".a"; if (wxFileName::FileExists(tf)) wxRemoveFile(tf); wxString nt=dialog.GetValue(); sqlQuery->SetTitle(nt); SqlBookUpdatePageTitle(); fileMarkerActive(true, nt); //sqlQueryBook->GetPage(curpage)-> SaveTempFile(); } } void frmQuery::OnSqlBookPageClose(wxAuiNotebookEvent &event) { // Don't allow removal of the last SQL box via user generated event size_t pagecnt = sqlQueryBook->GetPageCount(); if (pagecnt == 1) { event.Veto(); wxMessageBox(_("Cannot remove the last SQL tab")); return; } // Prevent removing the page that is currently being executed if (sqlQueryExec != NULL && sqlQueryExec == sqlQuery) { event.Veto(); wxMessageBox(_("The query on this SQL tab is still running.\nWait for it to finish or cancel it before closing the tab.")); return; } if (CheckChanged(true)) { event.Veto(); return; } // If removing the tab for which results are displayed, reset the output pane's caption if (sqlQuery == sqlQueryExecLast) { sqlQueryExecLast = NULL; SetOutputPaneCaption(true); } SqlBookDisconnectPage(); //drop temp file wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); wxString filename=sqlQuery->GetTitle(false)+wxT(".a"); if (wxFileName::FileExists(tempDir+filename)) wxRemoveFile(tempDir+filename); fileMarkerActive(false, sqlQuery->GetTitle(false)); } bool frmQuery::SqlBookCanChangePage() { return !(m_loadingfile || ms_pgScriptRunning); } void frmQuery::SqlBookAddPage(wxString& title) { ctlSQLBox *box; wxString caption; bool bVal; // All SQL boxes use the same wxID, CTL_SQLQUERY. // This should probably be changed, but it works for now and has minimal impact on existing code. box = new ctlSQLBox(sqlQueryBook, CTL_SQLQUERY, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSIMPLE_BORDER | wxTE_RICH2); box->SetDatabase(conn); box->SetMarginWidth(1, 16); box->SetDropTarget(new DnDFile(this)); box->SetChanged(false); box->SetOrigin(ORIGIN_MANUAL); box->SetQueryBook(sqlQueryBook); bVal = editMenu->IsChecked(MNU_AUTOINDENT); box->SetAutoIndent(bVal); bVal = viewMenu->IsChecked(MNU_WORDWRAP); box->SetWrapMode(bVal ? wxSTC_WRAP_WORD : wxSTC_WRAP_NONE); bVal = viewMenu->IsChecked(MNU_SHOWINDENTGUIDES); box->SetIndentationGuides(bVal); bVal = viewMenu->IsChecked(MNU_SHOWWHITESPACE); box->SetViewWhiteSpace(bVal ? wxSTC_WS_VISIBLEALWAYS : wxSTC_WS_INVISIBLE); bVal = viewMenu->IsChecked(MNU_SHOWLINEENDS); box->SetViewEOL(bVal ? 1 : 0); box->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); box->Connect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); if (title.BeforeFirst(' ')=="Query") { wxString np = title.AfterFirst(' '); long nl = 0; if (np.ToLong(&nl)) { if (sqlQueryCounter < nl) sqlQueryCounter = nl; } } if (title.IsEmpty()) sqlQueryCounter ++; int ll = sqlQueryCounter; caption = wxString::Format(_("Query %d"), ll); bool select = title.IsEmpty(); if (!select) caption = title; select = true; box->SetTitle(caption); sqlQueryBook->AddPage(box, caption, select); // Probably not needed, as the line above should trigger the PageChange event sqlQuery = box; sqlQuery->SetAutoReplaceList(autoreplace); sqlQuery->SetDefFunction(name_func, def_func); } void frmQuery::SqlBookDisconnectPage(ctlSQLBox *box) { if (box == NULL) box = sqlQuery; if (box != NULL) { box->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); box->Disconnect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(frmQuery::OnFocus)); for (int k=0;kGetPageCount() > 0) { // If removing the tab for which results are displayed, reset the output pane's caption if (sqlQuery == sqlQueryExecLast) { sqlQueryExecLast = NULL; SetOutputPaneCaption(true); } SqlBookDisconnectPage(); pageidx = sqlQueryBook->GetSelection(); wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator(); ctlSQLBox *box; box = wxDynamicCast(sqlQueryBook->GetPage(pageidx), ctlSQLBox); wxString filename=box->GetTitle(false); wxRemoveFile(tempDir+filename+wxT(".a")); return sqlQueryBook->DeletePage(pageidx); } return false; } void frmQuery::SqlBookSetAutoIndent(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetAutoIndent(b); } } void frmQuery::SqlBookSetWrapMode(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetWrapMode(b ? wxSTC_WRAP_WORD : wxSTC_WRAP_NONE); } } void frmQuery::SqlBookSetIndentGuides(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetIndentationGuides(b); } } void frmQuery::SqlBookSetViewWhiteSpace(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetViewWhiteSpace(b ? wxSTC_WS_VISIBLEALWAYS : wxSTC_WS_INVISIBLE); } } void frmQuery::SqlBookSetViewEOL(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetViewEOL(b ? 1 : 0); } } void frmQuery::SqlBookSetViewLineNumbers(bool b) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->UpdateLineNumber(); } } void frmQuery::SqlBookSetDatabase(pgConn *con) { size_t i, cnt; ctlSQLBox *box; for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) box->SetDatabase(con); } } void frmQuery::SqlBookUpdatePageTitle() { size_t index; wxString title; if (sqlQueryBook->GetPageCount() > 0 && sqlQuery != NULL) { index = sqlQueryBook->GetPageIndex(sqlQuery); if (index == wxNOT_FOUND) return; title = sqlQuery->GetTitle(); if (sqlQueryBook->GetPageText(index) != title) sqlQueryBook->SetPageText(index, title); } } // Returns true if any SQL tab attempts to veto the closing, false otherwise. bool frmQuery::SqlBookClose(bool canVeto) { size_t i = 0; size_t cnt = sqlQueryBook->GetPageCount(); ctlSQLBox *box; // See if we have any unsaved changes and prompt to save them for (i = 0; i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL && box->IsChanged()) { sqlQueryBook->SetSelection(i); if (CheckChanged(canVeto)) return true; } } // If we got here, the window will be closed for (i = 0; i < cnt; ++i) { box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox); if (box != NULL) SqlBookDisconnectPage(box); } return false; } /////////////////////////////////////////////////////// wxWindow *queryToolBaseFactory::StartDialogSql(frmMain *form, pgObject *obj, const wxString &sql) { pgDatabase *db = obj->GetDatabase(); wxString usr=wxEmptyString; wxGetEnv(wxT("USERNAME"),&usr); wxString applicationname = appearanceFactory->GetLongAppName() + wxT(" - query ")+usr; pgConn *conn = db->CreateConn(applicationname); if (conn) { frmQuery *fq = new frmQuery(form, obj->GetDisplayName(), conn, sql); fq->Go(); return fq; } return 0; } bool queryToolBaseFactory::CheckEnable(pgObject *obj) { return obj && obj->GetDatabase() && obj->GetDatabase()->GetConnected(); } bool queryToolDataFactory::CheckEnable(pgObject *obj) { return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() && (obj->IsCreatedBy(tableFactory) || obj->IsCreatedBy(pg_partitionFactory) || obj->IsCreatedBy(viewFactory)); } queryToolFactory::queryToolFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolBaseFactory(list) { mnu->Append(id, _("&Query tool\tCtrl-E"), _("Execute arbitrary SQL queries.")); toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "sql_32.svg", wxSize(32, 32)), _("Execute arbitrary SQL queries."), wxITEM_NORMAL); //toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "plugins.svg", wxSize(32, 32)), _("Execute arbitrary SQL queries."), wxITEM_NORMAL); } wxWindow *queryToolFactory::StartDialog(frmMain *form, pgObject *obj) { wxString qry; if (settings->GetStickySql()) qry = obj->GetSql(form->GetBrowser()); return StartDialogSql(form, obj, qry); } queryToolSqlFactory::queryToolSqlFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolBaseFactory(list) { mnu->Append(id, _("CREATE Script"), _("Start Query tool with CREATE script.")); if (toolbar) toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "sql_32.svg", wxSize(32, 32)), _("Start query tool with CREATE script."), wxITEM_NORMAL); } wxWindow *queryToolSqlFactory::StartDialog(frmMain *form, pgObject *obj) { return StartDialogSql(form, obj, obj->GetSql(form->GetBrowser())); } bool queryToolSqlFactory::CheckEnable(pgObject *obj) { return queryToolBaseFactory::CheckEnable(obj) && obj->CanCreate() && !obj->IsCollection(); } queryToolSelectFactory::queryToolSelectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("SELECT Script"), _("Start query tool with SELECT script.")); } bool queryToolSelectFactory::CheckEnable(pgObject *obj) { return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() && (obj->IsCreatedBy(tableFactory) || obj->IsCreatedBy(foreignTableFactory) || obj->IsCreatedBy(viewFactory) || obj->IsCreatedBy(functionFactory) || obj->IsCreatedBy(pg_partitionFactory)); } wxWindow *queryToolSelectFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(tableFactory)||(obj->IsCreatedBy(pg_partitionFactory))) { pgTable *table = (pgTable *)obj; return StartDialogSql(form, obj, table->GetSelectSql(form->GetBrowser())); } else if (obj->IsCreatedBy(viewFactory)) { pgView *view = (pgView *)obj; return StartDialogSql(form, obj, view->GetSelectSql(form->GetBrowser())); } else if (obj->IsCreatedBy(extTableFactory)) { gpExtTable *exttable = (gpExtTable *)obj; return StartDialogSql(form, obj, exttable->GetSelectSql(form->GetBrowser())); } else if (obj->IsCreatedBy(functionFactory)) { pgFunction *function = (pgFunction *)obj; return StartDialogSql(form, obj, function->GetSelectSql(form->GetBrowser())); } else if (obj->IsCreatedBy(foreignTableFactory)) { pgForeignTable *foreigntable = (pgForeignTable *)obj; return StartDialogSql(form, obj, foreigntable->GetSelectSql(form->GetBrowser())); } return 0; } queryToolExecFactory::queryToolExecFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("EXEC Script"), _("Start query tool with EXEC script.")); } bool queryToolExecFactory::CheckEnable(pgObject *obj) { return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() && obj->IsCreatedBy(procedureFactory); } wxWindow *queryToolExecFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(procedureFactory)) { pgProcedure *procedure = (pgProcedure *)obj; return StartDialogSql(form, obj, procedure->GetExecSql(form->GetBrowser())); } return 0; } queryToolDeleteFactory::queryToolDeleteFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("DELETE Script"), _("Start query tool with DELETE script.")); } bool queryToolDeleteFactory::CheckEnable(pgObject *obj) { if (!queryToolDataFactory::CheckEnable(obj)) return false; if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) return true; return false; } wxWindow *queryToolDeleteFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(tableFactory)) { pgTable *table = (pgTable *)obj; return StartDialogSql(form, obj, table->GetDeleteSql(form->GetBrowser())); } return 0; } queryToolCreateCascadeFactory::queryToolCreateCascadeFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("Script Recreate Cascade"), _("Start query tool with recreate cascade script.")); } //wxArrayString queryToolCreateCascadeFactory::GetArrayList(wxString *strobj) //{ // wxString *databasePath=new wxString(strobj); // pgSet *set; // set = connection->ExecuteSet( // wxT("SELECT relname FROM pg_class, pg_index WHERE pg_class.oid=indexrelid AND indrelid=") + table->GetOidStr()); // if (set) // { // while (!set->Eof()) // { // cbIndex->Append(set->GetVal(0)); // set->MoveNext(); // } // delete set; // } // // wxStringTokenizer tkz(databasePath, wxT("/")); // while(tkz.HasMoreTokens()) // { // wxString token = tkz.GetNextToken(); // if(token == _("Databases")) // break; // //ItemPath += token + wxT("/"); // } // // return 0; //} wxWindow *queryToolCreateCascadeFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) { pgTable *table = (pgTable *)obj; return StartDialogSql(form, obj, table->GetSqlReCreate(form,obj)); } else if (obj->IsCreatedBy(viewFactory)) { pgView *view = (pgView *)obj; return StartDialogSql(form, obj, view->GetSqlReCreate(form,obj)); } return 0; } bool queryToolCreateCascadeFactory::CheckEnable(pgObject *obj) { if (!queryToolDataFactory::CheckEnable(obj)) return false; if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) return true; pgView *view = (pgView *)obj; return true; } queryToolUpdateFactory::queryToolUpdateFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("UPDATE Script"), _("Start query tool with UPDATE script.")); } wxWindow *queryToolUpdateFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) { pgTable *table = (pgTable *)obj; return StartDialogSql(form, obj, table->GetUpdateSql(form->GetBrowser())); } else if (obj->IsCreatedBy(viewFactory)) { pgView *view = (pgView *)obj; return StartDialogSql(form, obj, view->GetUpdateSql(form->GetBrowser())); } return 0; } bool queryToolUpdateFactory::CheckEnable(pgObject *obj) { if (!queryToolDataFactory::CheckEnable(obj)) return false; if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) return true; pgView *view = (pgView *)obj; return view->HasUpdateRule(); } queryToolInsertFactory::queryToolInsertFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list) { mnu->Append(id, _("INSERT Script"), _("Start query tool with INSERT script.")); } wxWindow *queryToolInsertFactory::StartDialog(frmMain *form, pgObject *obj) { if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) { pgTable *table = (pgTable *)obj; return StartDialogSql(form, obj, table->GetInsertSql(form->GetBrowser())); } else if (obj->IsCreatedBy(viewFactory)) { pgView *view = (pgView *)obj; return StartDialogSql(form, obj, view->GetInsertSql(form->GetBrowser())); } return 0; } bool queryToolInsertFactory::CheckEnable(pgObject *obj) { if (!queryToolDataFactory::CheckEnable(obj)) return false; if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory)) return true; pgView *view = (pgView *)obj; return view->HasInsertRule(); } void frmQuery::SaveExplainAsImage(wxCommandEvent &ev) { wxFileDialog *dlg = new wxFileDialog(this, _("Save Explain As image file"), lastDir, lastFilename, wxT("Bitmap files (*.bmp)|*.bmp|JPEG files (*.jpeg)|*.jpeg|PNG files (*.png)|*.png"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg->ShowModal() == wxID_OK) { lastFilename = dlg->GetFilename(); lastDir = dlg->GetDirectory(); lastPath = dlg->GetPath(); int index = dlg->GetFilterIndex(); wxString strType; wxBitmapType imgType; switch (index) { // bmp case 0: strType = wxT(".bmp"); imgType = wxBITMAP_TYPE_BMP; break; // jpeg case 1: strType = wxT(".jpeg"); imgType = wxBITMAP_TYPE_JPEG; break; // default (png) default: // png case 2: strType = wxT(".png"); imgType = wxBITMAP_TYPE_PNG; break; } if (!lastPath.Contains(wxT("."))) lastPath += strType; if (ev.GetId() == MNU_SAVEAS_IMAGE_GQB) controller->getView()->SaveAsImage(lastPath, imgType); else if (ev.GetId() == MNU_SAVEAS_IMAGE_EXPLAIN) explainCanvas->SaveAsImage(lastPath, imgType); } } /////////////////////////////////////////////////////// pgScriptTimer::pgScriptTimer(frmQuery *parent) : m_parent(parent) { } void pgScriptTimer::Notify() { // Write script output m_parent->writeScriptOutput(); }