pgadmin3/frm/frmQuery.cpp
levinsv 759214fe03 add global find
Query form add find all tabs
2019-06-02 23:01:31 +05:00

4568 lines
130 KiB
C++
Raw Blame History

//////////////////////////////////////////////////////////////////////////
//
// 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 <wx/wx.h>
#include <wx/busyinfo.h>
#include <wx/clipbrd.h>
#include <wx/dcbuffer.h>
#include <wx/dnd.h>
#include <wx/filename.h>
#include <wx/regex.h>
#include <wx/textctrl.h>
#include <wx/timer.h>
#include <wx/aui/aui.h>
#include <wx/bmpcbox.h>
#include <wx/filefn.h>
#include <wx/stdpaths.h>
// 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"
// 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/help.pngc"
#include "images/gqbJoin.pngc"
#define CTRLID_CONNECTION 4200
#define CTRLID_DATABASELABEL 4201
#define CTL_SQLQUERYBOOK 4202
#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)
// 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_COPY_INSERT, frmQuery::OnCopy_Insert)
EVT_MENU(MNU_FIND, frmQuery::OnSearchReplace)
EVT_MENU(MNU_UNDO, frmQuery::OnUndo)
EVT_MENU(MNU_REDO, frmQuery::OnRedo)
EVT_MENU(MNU_EXECUTE, frmQuery::OnExecute)
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_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_EXTERNALFORMAT, frmQuery::OnExternalFormat)
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_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_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_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)
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;
};
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;
loading = true;
closing = false;
dlgName = wxT("frmQuery");
recentKey = wxT("RecentFiles");
RestorePosition(100, 100, 600, 500, 450, 300);
explainCanvas = NULL;
// notify wxAUI which frame to use
manager.SetManagedWindow(this);
manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG);
SetMinSize(wxSize(450, 300));
SetIcon(*sql_32_png_ico);
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..."), _("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->AppendSeparator();
formatMenu->Append(MNU_EXTERNALFORMAT, _("External Format\tCtrl-Shift-F"), _("Call external formatting 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"));
autoreplace = queryMacroFileProvider::LoadAutoReplace(true);
menuBar->Append(editMenu, _("&Edit"));
queryMenu = new wxMenu();
queryMenu->Append(MNU_EXECUTE, _("&Execute\tF8"), _("Execute query"));
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();
wxAcceleratorEntry entries[16];
entries[0].Set(wxACCEL_CTRL, (int)'E', MNU_EXECUTE);
entries[1].Set(wxACCEL_CTRL, (int)'O', MNU_OPEN);
entries[2].Set(wxACCEL_CTRL, (int)'S', MNU_SAVE);
entries[3].Set(wxACCEL_CMD, (int)'S', MNU_SAVE);
entries[4].Set(wxACCEL_CTRL, (int)'F', MNU_FIND);
entries[5].Set(wxACCEL_CTRL, (int)'R', MNU_REPLACE);
entries[6].Set(wxACCEL_NORMAL, WXK_F8, MNU_EXECUTE);
entries[7].Set(wxACCEL_NORMAL, WXK_F7, MNU_EXPLAIN);
entries[8].Set(wxACCEL_ALT, WXK_PAUSE, MNU_CANCEL);
entries[9].Set(wxACCEL_CTRL, (int)'A', MNU_SELECTALL);
entries[10].Set(wxACCEL_CMD, (int)'A', MNU_SELECTALL);
entries[11].Set(wxACCEL_NORMAL, WXK_F1, MNU_HELP);
entries[12].Set(wxACCEL_CTRL, (int)'N', MNU_NEW);
entries[13].Set(wxACCEL_NORMAL, WXK_F6, MNU_EXECPGS);
entries[14].Set(wxACCEL_NORMAL, WXK_F5, MNU_EXECFILE);
entries[15].Set(wxACCEL_CTRL, (int)'T', MNU_NEWSQLTAB);
wxAcceleratorTable accel(16, entries);
SetAcceleratorTable(accel);
queryMenu->Enable(MNU_CANCEL, false);
int iWidths[7] = {0, -1, 40, 200, 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);
toolBar->SetToolBitmapSize(wxSize(16, 16));
toolBar->AddTool(MNU_NEWSQLTAB, wxEmptyString, *file_new_png_bmp, _("New SQL tab"), wxITEM_NORMAL);
toolBar->AddTool(MNU_OPEN, wxEmptyString, *file_open_png_bmp, _("Open file"), wxITEM_NORMAL);
toolBar->AddTool(MNU_SAVE, wxEmptyString, *file_save_png_bmp, _("Save file"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_CUT, wxEmptyString, *clip_cut_png_bmp, _("Cut selected text to clipboard"), wxITEM_NORMAL);
toolBar->AddTool(MNU_COPY, wxEmptyString, *clip_copy_png_bmp, _("Copy selected text to clipboard"), wxITEM_NORMAL);
toolBar->AddTool(MNU_PASTE, wxEmptyString, *clip_paste_png_bmp, _("Paste selected text from clipboard"), wxITEM_NORMAL);
toolBar->AddTool(MNU_CLEAR, wxEmptyString, *edit_clear_png_bmp, _("Clear edit window"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_UNDO, wxEmptyString, *edit_undo_png_bmp, _("Undo last action"), wxITEM_NORMAL);
toolBar->AddTool(MNU_REDO, wxEmptyString, *edit_redo_png_bmp, _("Redo last action"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_FIND, wxEmptyString, *edit_find_png_bmp, _("Find and replace text"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_EXECUTE, wxEmptyString, *query_execute_png_bmp, _("Execute query"), wxITEM_NORMAL);
toolBar->AddTool(MNU_EXECPGS, wxEmptyString, *query_pgscript_png_bmp, _("Execute pgScript"), wxITEM_NORMAL);
toolBar->AddTool(MNU_EXECFILE, wxEmptyString, *query_execfile_png_bmp, _("Execute query, write result to file"), wxITEM_NORMAL);
toolBar->AddTool(MNU_EXPLAIN, wxEmptyString, *query_explain_png_bmp, _("Explain query"), wxITEM_NORMAL);
toolBar->AddTool(MNU_CANCEL, wxEmptyString, *query_cancel_png_bmp, _("Cancel query"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_DOCOMMIT, wxEmptyString, *query_commit_png_bmp, _("Commit"), wxITEM_NORMAL);
toolBar->AddTool(MNU_DOROLLBACK, wxEmptyString, *query_rollback_png_bmp, _("Rollback"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_HELP, wxEmptyString, *help_png_bmp, _("Display help on SQL commands."), wxITEM_NORMAL);
toolBar->Realize();
// 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(_("<new connection>"), 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 | wxALIGN_CENTER_VERTICAL, 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);
// 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);
ctlSQL[0] = sqlResult;
explainCanvas = new ExplainCanvas(outputPane);
msgResult = new wxTextCtrl(outputPane, CTL_MSGRESULT, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
msgResult->SetFont(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);
// 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);
// and 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"));
// 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());
// 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.
SqlBookAddPage();
if (!file.IsEmpty() && wxFileName::FileExists(file))
{
wxFileName fn = file;
lastFilename = fn.GetFullName();
lastDir = fn.GetPath();
lastPath = fn.GetFullPath();
OpenLastFile();
sqlQuery->Colourise(0, query.Length());
}
else if (!query.IsNull())
{
sqlQuery->SetText(query);
SetLineEndingStyle();
sqlQuery->Colourise(0, query.Length());
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;
wxString tempDir=wxStandardPaths::Get().GetUserConfigDir()+wxT("\\postgresql\\recovery\\");
if (!wxDirExists(tempDir)) {
wxFileName dn = tempDir;
dn.Mkdir();
}
wxString pref=_conn->GetDbname();
bool modeUnicode = settings->GetUnicodeFile();
wxString f = wxFindFirstFile(tempDir+wxT("*.a"));
while ( !f.empty() )
{
filename=f.AfterLast('\\').BeforeLast('.');
if ((f.AfterLast('\\').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())
{
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);
//filename=f.AfterLast('\\').BeforeLast('.');
sqlQuery->SetTitle(filename);
setExtendedTitle();
SqlBookUpdatePageTitle();
//SetLineEndingStyle();
SaveTempFile();
SqlBookAddPage();
}
}
f = wxFindNextFile();
}
//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);
}
else
{
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)
{
queryMenu->Check(MNU_AUTOCOMMIT, event.IsChecked());
if(event.IsChecked() && 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);
sqlResult->SetConnection(conn);
pgScript->SetConnection(conn);
title = wxT("Query - ") + cbConnection->GetValue();
setExtendedTitle();
//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();
}
//hist->CmdKeyExecute(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)
{
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();
else if (wnd == msgResult)
msgResult->Copy();
else if (wnd == msgHistory)
msgHistory->Copy();
else if (wnd == scratchPad)
scratchPad->Copy();
else
{
wxWindow *obj = wnd;
while (obj != NULL)
{
if (obj == sqlResult)
{
sqlResult->Copy(false);
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::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();
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));
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();
}
}
// 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->Append(MNU_SUMMARY_COL, _("Summary"), _("Summary selected cells."));
xmenu->Append(MNU_COPY_INSERT, _("Copy Insert format"), _("Copy Insert format."));
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);
}
sqlResult->PopupMenu(xmenu);
}
void frmQuery::OnCopy_Insert(wxCommandEvent &ev)
{
// if (currentControl() == sqlResult)
{
wxString s=wxT("Insert into format copy buffer.");
sqlResult->Copy(true);
SetStatusText(s, STATUSPOS_POS);
}
}
void frmQuery::OnSummary_Column(wxCommandEvent &ev)
{
// if (currentControl() == sqlResult)
{
wxString s=sqlResult->SummaryColumn();
SetStatusText(s, STATUSPOS_POS);
}
}
void frmQuery::OnPositionStc(wxStyledTextEvent &event)
{
int selFrom, selTo, selCount;
sqlQuery->GetSelection(&selFrom, &selTo);
selCount = selTo - selFrom;
editMenu->Enable(MNU_AUTOEDITOBJECT, selCount > 0);
wxString pos;
pos.Printf(_("Ln %d, Col %d, Ch %d"), sqlQuery->LineFromPosition(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetColumn(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetCurrentPos() + 1);
//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));
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::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, str.Length());
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=wxStandardPaths::Get().GetUserConfigDir()+wxT("\\postgresql\\recovery");
wxUtfFile file(tempDir+wxT("\\")+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);
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();
}
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)
{
//parent->SetCurrentNode(parent->GetBrowser()->GetRootItem(), path);
pgObject *obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection());
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->GetName().Lower()==selText.Lower()) {
//obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection());
mainForm->execSelChange(matchItem,false);
obj=o;
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 (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;");
}
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->GetText().Length());
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();
wxString *q=new wxString[30];
int s,e,i=0;
if (!name.IsEmpty())
{
// get the word under cursor:
int endDoc = sqlQuery->GetLength();
int endPos = sqlQuery->GetSelectionEnd();
int startPos = sqlQuery->GetSelectionStart();
while(endPos<startPos)
{
p=sqlQuery->SelectQuery(startPos);
s=p>>16;
e=p & 65535;
q[i++]=sqlQuery->GetTextRange(s, e);
startPos=e+1;
}
querys=new wxString[i];
for (int j = 0; j < i; j++) {
querys[j]=q[j];
}
//name = sqlQuery->GetTextRange(startPos, endPos);
//selected = false;
} else {
int curPos = sqlQuery->GetCurrentPos();
p=sqlQuery->SelectQuery(curPos);
s=p>>16;
e=p & 65535;
querys=new wxString[1];
querys[0]=sqlQuery->GetTextRange(s, e);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
sqlQuery->SetSelection(s,e);
}
delete [] q;
}
void frmQuery::OnExecute(wxCommandEvent &event)
{
if(sqlNotebook->GetSelection() == 1)
{
if (!updateFromGqb(true))
return;
}
SaveTempFile();
wxString query = sqlQuery->GetSelectedText();
if (query.IsNull())
if (queryMenu->IsChecked(MNU_AUTOSELECTQUERY)) {
// Auto-select
SelectQuery();
//query = sqlQuery->GetSelectedText();
query = querys[0];
} else query = sqlQuery->GetText();
if (query.IsNull())
return;
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, wxSTC_INDICS_MASK);
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_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_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, wxSTC_INDICS_MASK);
sqlQuery->SetStyling(sqlQuery->GetText().Length(), 0);
if (!sqlQuery->IsChanged())
setExtendedTitle();
aborted = false;
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
// Set an indicator on the error word (break on any kind of bracket, a space or full stop)
int sPos = errPos + selStart - 1, wEnd = 1;
sqlQueryExec->StartStyling(sPos, wxSTC_INDICS_MASK);
int c = sqlQueryExec->GetCharAt(sPos + wEnd);
size_t len = sqlQueryExec->GetText().Length();
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 + selStart + 1)
line++;
if (line < maxLine)
{
sqlQueryExec->GotoPos(sPos);
sqlQueryExec->MarkerAdd(line, 0);
if (!sqlQueryExec->IsChanged())
setExtendedTitle();
sqlQueryExec->EnsureVisible(line);
}
}
}
}
else
{
done = true;
outputPane->SetSelection(0);
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);
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::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
}
}
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, query.Length());
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::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::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();
sqlQuery->SetFocus();
//wxMessageBox(wxT("OnSqlBookPageChanged "));
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."));
}
}
void frmQuery::OnSqlBookAddPage(wxCommandEvent &event)
{
if (SqlBookCanChangePage())
SqlBookAddPage();
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::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=wxStandardPaths::Get().GetUserConfigDir()+wxT("\\postgresql\\recovery\\");
wxString filename=sqlQuery->GetTitle(false);
wxRemoveFile(tempDir+filename+wxT(".a"));
wxString nt=dialog.GetValue();
sqlQuery->SetTitle(nt);
SqlBookUpdatePageTitle();
//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=wxStandardPaths::Get().GetUserConfigDir()+wxT("\\postgresql\\recovery\\");
wxString filename=sqlQuery->GetTitle(false)+wxT(".a");
if (wxFileName::FileExists(tempDir+filename)) wxRemoveFile(tempDir+filename);
}
bool frmQuery::SqlBookCanChangePage()
{
return !(m_loadingfile || ms_pgScriptRunning);
}
void frmQuery::SqlBookAddPage()
{
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));
sqlQueryCounter ++;
caption = wxString::Format(_("Query %i"), sqlQueryCounter);
box->SetTitle(caption);
sqlQueryBook->AddPage(box, caption, true);
// 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));
}
}
bool frmQuery::SqlBookRemovePage()
{
size_t pageidx;
if (sqlQueryBook->GetPageCount() > 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=wxStandardPaths::Get().GetUserConfigDir()+wxT("\\postgresql\\recovery\\");
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, *sql_32_png_bmp, _("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, *sql_32_png_bmp, _("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();
}