Example #1
0
class DataFrame(SqlFrame):
  def __init__(self, parentWin, connectionPool, name, server):
    self.tableSpecs=TableSpecs(connectionPool, name)
    self.connectionPool=connectionPool
    self.worker=None
    self.output=None
    self.server=server
    querypreset_table=self.server.info.get('querypreset_table')
    if self.server.adminspace and querypreset_table:
      self.querypreset_table="%s.%s" % (quoteIdent(self.server.adminspace), quoteIdent(querypreset_table))
    else:
      self.querypreset_table=None
      
          
    title=xlt("%(appTitle)s Data Tool - %(tableName)s") % {
                'appTitle': adm.appTitle, 'tableName': name}
    SqlFrame.__init__(self, parentWin, title, "SqlData")

    toolbar=self.GetToolBar()

    toolbar.Add(self.OnRefresh, xlt("Refresh"), "data_refresh")
    toolbar.Add(self.OnCancelRefresh, xlt("Cancel refresh"), "query_cancel")
    toolbar.Add(self.OnSave, xlt("Save data"), "data_save")
    toolbar.Add(self.OnToggleFilter, xlt("Show filter window"), "filter")
    toolbar.AddSeparator()
    toolbar.Add(self.OnCopy, xlt("Copy"), "clip_copy")
    toolbar.Add(self.OnCut, xlt("Cut"), "clip_cut")
    toolbar.Add(self.OnPaste, xlt("Paste"), "clip_paste")
    toolbar.Add(self.OnUndo, xlt("Undo"), "edit_undo")
    toolbar.AddSeparator()
    toolbar.Add(self.OnDelete, xlt("Delete"), "delete")

    menubar=wx.MenuBar()
    
    self.filemenu=menu=Menu(self)
    menu.Add(self.OnClose, xlt("Quit tool"), xlt("Quit data tool"))

    menubar.Append(menu, xlt("&File"))
    
    self.datamenu=menu=Menu(self)
    menu.Add(self.OnRefresh, xlt("Refresh"), xlt("Refresh data"))
    menu.Add(self.OnCancelRefresh, xlt("Cancel"), xlt("Cancel refresh"))
    menu.Add(self.OnSave, xlt("Save"), xlt("Save data"))
    menu.Add(self.OnDelete, xlt("Delete"), xlt("Delete row(s)"))
    menubar.Append(menu, xlt("&Data"))

    self.viewmenu=menu=Menu(self)
    menu.AddCheck(self.OnToggleFilter, xlt("Filter"), xlt("Show or hide filter window"))
    self.registerToggles(True, True)
    menubar.Append(menu, xlt("&View"))
    
    self.editmenu=menu=Menu(self)
    menu.Add(self.OnCut, xlt("Cu&t"), xlt("Cut selected data to clipboard"))
    menu.Add(self.OnCopy, xlt("&Copy"), xlt("Copy selected data to clipboard"))
    menu.Add(self.OnPaste, xlt("&Paste"), xlt("Paste data from clipboard"))
    menu.Add(self.OnUndo, xlt("&Undo"), xlt("discard last editing"))
    menubar.Append(menu, xlt("&Edit"))

    self.helpmenu=menu=Menu(self)
    menu.Add(self.OnHelp, xlt("Help"), xlt("Show help"), wx.ID_HELP)
    menubar.Append(menu, xlt("&Help"))

    self.EnableMenu(self.datamenu, self.OnCancelRefresh, False)
    self.SetMenuBar(menubar)

    toolbar.Realize()

    ah=AcceleratorHelper(self)
    ah.Add(wx.ACCEL_CTRL, 'X', self.OnCut)
    ah.Add(wx.ACCEL_CTRL, 'C', self.OnCopy)
    ah.Add(wx.ACCEL_CTRL, 'V', self.OnPaste)
    ah.Add(wx.ACCEL_CTRL, 'S', self.OnSave)
    ah.Add(wx.ACCEL_NORMAL,wx.WXK_F5, self.OnRefresh)
    ah.Add(wx.ACCEL_ALT,wx.WXK_PAUSE, self.OnCancelRefresh)
    ah.Realize()
    
    self.notebook=wx.Notebook(self)
    self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnCheck)
    self.filter=FilterPanel(self, self.notebook)
    self.notebook.AddPage(self.filter, xlt("Filter, Order, Limit"))
    self.editor=SqlEditor(self.notebook)
    self.editor.SetAcceleratorTable(ah.GetTable())
    self.notebook.AddPage(self.editor, xlt("Manual SQL"))
    
    self.manager.AddPane(self.notebook, wx.aui.AuiPaneInfo().Top().PaneBorder().Resizable().MinSize((200,200)).BestSize((400,200)).CloseButton(True) \
                          .Name("filter").Caption(xlt("SQL query parameter")).Hide())


    self.output = SqlEditGrid(self, self.tableSpecs)
    self.manager.AddPane(self.output, wx.aui.AuiPaneInfo().Center().MinSize((200,100)).BestSize((400,200)).CloseButton(False) \
                          .Name("Edit Data").Caption(xlt("Edit Data")).CaptionVisible(False))

    self.restorePerspective()
    self.manager.GetPane("Edit data").Show()
    self.manager.Update()

    self.manager.Bind(wx.aui.EVT_AUI_PANE_CLOSE, self.OnAuiCloseEvent)
    self.viewmenu.Check(self.OnToggleFilter, self.manager.GetPane("filter").IsShown())
    self.OnToggleToolBar()
    self.OnToggleStatusBar()

    self.updateMenu()
    self.filter.Go(self.tableSpecs)

    if not self.editor.GetText():    # otherwise set from default preset
      self.editor.SetText("/*\n%s\n*/\n\n%s" % (xlt(
                "Caution: Don't mess with table and column names!\nYou may experience unwanted behaviour or data loss."), 
                                              self.filter.GetQuery()))

  def OnHelp(self, evt):
    wx.LaunchDefaultBrowser("http://www.admin4.org/docs/pgsql/datatool")
    
  def OnAuiCloseEvent(self, evt):
    if evt.GetPane().name == "filter":
      self.datamenu.Check(self.OnToggleFilter, False)

  def OnToggleFilter(self, evt):
    paneInfo=self.manager.GetPane("filter")
    how=self.viewmenu.IsChecked(self.OnToggleFilter)
    if isinstance(evt.EventObject, wx.ToolBar):
      how=not how
      self.viewmenu.Check(self.OnToggleFilter, how)
    paneInfo.Show(how)
    self.manager.Update()    
    

  def OnCheck(self, evt):
    if evt.GetSelection():
      self.editor.Show()
    self.updateMenu(evt.GetSelection())
      
  def updateMenu(self, sel=None):
    if sel == None:
      sel=self.notebook.GetSelection()
    if sel:
      queryOk=True
    else:
      queryOk=self.filter.valid

    if self.output:
      if self.output.table:
        canSave=self.output.dirty
        canUndo=(self.output.table.currentRow!=None)
      else:
        canSave=canUndo=False
    
      self.EnableMenu(self.editmenu, self.OnUndo, canUndo)        
      self.EnableMenu(self.datamenu, self.OnRefresh, queryOk)
      self.EnableMenu(self.datamenu, self.OnSave, canSave)
    
  def OnDelete(self, evt):
    self.output.OnDeleteRows(evt)

  def executeQuery(self, sql):
    self.output.SetEmpty()
    self.worker=None
    
    self.EnableMenu(self.datamenu, self.OnRefresh, False)
    self.EnableMenu(self.datamenu, self.OnCancelRefresh, True)
    
    self.startTime=localTimeMillis();
    self.worker=worker=self.tableSpecs.GetCursor().ExecuteAsync(sql)
    worker.start()
    
    self.SetStatus(xlt("Refreshing data..."));
    self.SetStatusText("", self.STATUSPOS_ROWS)

    self.pollWorker()

    self.EnableMenu(self.datamenu, self.OnCancelRefresh, False)
    self.EnableMenu(self.datamenu, self.OnRefresh, True)
  
    txt=xlt("%d rows") % worker.GetRowcount()
    if not self.notebook.GetSelection() and self.filter.LimitCheck and self.filter.LimitValue == worker.GetRowcount():
      txt += " LIMIT"
    self.SetStatusText(txt, self.STATUSPOS_ROWS)

    if worker.cancelled:
      self.SetStatus(xlt("Cancelled."));
      self.output.SetData(worker.GetResult())
    elif worker.error:
      errlines=worker.error.error.splitlines()
      self.output.SetEmpty()
      self.SetStatus(errlines[0]);
    else:
      self.SetStatus(xlt("OK."));
      
      self.output.SetData(worker.GetResult())
      

  def OnSave(self, evt):
    self.output.DoCommit()
    self.output.Refresh()
    
    
  def OnRefresh(self, evt=None):
    if self.notebook.GetSelection():
      sql=self.editor.GetSelectedText()
      if not sql:
        sql=self.editor.GetText()
      if not sql.strip():
        return
    else:
      sql=self.filter.GetQuery()
    self.executeQuery(sql)
  
  def OnCancelRefresh(self, evt):
    self.EnableMenu(self.datamenu, self.OnCancelRefresh, False)
    if self.worker:
      self.worker.Cancel()
  
  def OnUndo(self, evt):
    self.output.RevertEdit()
    

  def OnClose(self, evt):
    self.OnCancelRefresh(None)
    if self.output.table and self.output.table.currentRow:
      dlg=wx.MessageDialog(self, xlt("Data is changed but not written.\nSave now?"), xlt("Unsaved data"), 
                           wx.YES_NO|wx.CANCEL|wx.CANCEL_DEFAULT|wx.ICON_EXCLAMATION)
      rc=dlg.ShowModal()
      if rc == wx.ID_CANCEL:
        return 
      elif rc == wx.ID_YES:
        self.output.table.Commit()
        
    self.worker = None
    self.connectionPool.Disconnect()
    super(DataFrame, self).OnClose(evt)
    self.Destroy()
Example #2
0
class QueryFrame(SqlFrame):
  def __init__(self, parentWin, node, params={}):
    SqlFrame.__init__(self, parentWin, xlt("Query Tool"), "SqlQuery")

    self.server=node.GetServer()
    self.application="%s Query Tool" % adm.appTitle
    
    snippet_table=self.server.info.get('snippet_table')
    if self.server.adminspace and snippet_table:
      self.snippet_table="%s.%s" % (quoteIdent(self.server.adminspace), quoteIdent(snippet_table))
    else:
      self.snippet_table=None

    dbName=params.get('dbname')
    if not dbName:
      if hasattr(node, "GetDatabase"):
        dbName=node.GetDatabase().name
      else:
        dbName=self.server.maintDb
    self.worker=None
    self.sqlChanged=False
    self.previousCols=[]

    self.fileManager=FileManager(self, adm.config)

    toolbar=self.toolbar
    toolbar.Add(self.OnFileOpen, xlt("Load from file"),"file_open")
    toolbar.Add(self.OnFileSave, xlt("Save to file"), "file_save")
    toolbar.Add(self.OnToggleSnippets, xlt("Show snippets browser"), "snippets")
    
    toolbar.AddSeparator()
    toolbar.Add(self.OnCopy, xlt("Copy"), "clip_copy")
    toolbar.Add(self.OnCut, xlt("Cut"), "clip_cut")
    toolbar.Add(self.OnPaste, xlt("Paste"), "clip_paste")
    toolbar.Add(self.OnClear, xlt("Clear"), "edit_clear")
    toolbar.AddSeparator()
    toolbar.Add(self.OnUndo, xlt("Undo"), "edit_undo")
    toolbar.Add(self.OnRedo, xlt("Redo"), "edit_redo")
#    toolbar.Add((self.OnFind, xlt("Find"), "edit_find")
    toolbar.AddSeparator()
    
    cbClass=xmlres.getControlClass("whComboBox")
    allDbs=self.server.GetConnectableDbs()
    size=max(map(lambda db: toolbar.GetTextExtent(db)[0], allDbs))
    
    BUTTONOFFS=30
    self.databases=cbClass(toolbar, size=(size+BUTTONOFFS, -1))
    self.databases.Append(allDbs)
    self.databases.Append(xlt("Connect..."))

    self.databases.SetStringSelection(dbName)
    self.OnChangeDatabase()
    self.databases.Bind(wx.EVT_COMBOBOX, self.OnChangeDatabase)

    toolbar.Add(self.OnExecuteQuery, xlt("Execute Query"), "query_execute")
    toolbar.Add(self.OnExplainQuery, xlt("Explain Query"), "query_explain")
    toolbar.Add(self.OnCancelQuery, xlt("Execute Query"), "query_cancel")
    toolbar.AddControl(self.databases)
    toolbar.AddSeparator()
    toolbar.Add(self.OnAddSnippet, xlt("Add snippet"), "snippet_add")
    toolbar.Add(self.OnReplaceSnippet, xlt("Replace snippet"), "snippet_replace")
    toolbar.Realize()

    menubar=wx.MenuBar()
    self.filemenu=menu=Menu(self)

    menu.Add(self.OnFileOpen, xlt("&Open"), xlt("Open query file"))
    menu.AppendMenu(-1, xlt("Open recent..."), self.fileManager.GetRecentFilesMenu())
    menu.Add(self.OnFileInsert, xlt("&Insert"), xlt("Insert query file"))
    menu.Add(self.OnFileSave, xlt("&Save"), xlt("Save current file"))
    menu.Add(self.OnFileSaveAs, xlt("Save &as.."), xlt("Save file under new name"))
    menu.AppendSeparator()
    
#    menu.Add(xlt("Preferences"), xlt("Preferences"), self.OnPreferences)
    menu.Add(self.OnClose, xlt("Quit SQL"), xlt("Quit Sql"))

    menubar.Append(menu, xlt("&File"))
    
    self.viewmenu=menu=Menu(self)
    menu.AddCheck(self.OnToggleSnippets, xlt("Snippets"), xlt("Show or hide snippet browser"))
    self.registerToggles(True, True)
    menubar.Append(self.viewmenu, xlt("&View"))
    
    self.editmenu=menu=Menu(self)
    menu.Add(self.OnUndo, xlt("&Undo"), xlt("Undo last action"))
    menu.Add(self.OnRedo, xlt("&Redo"), xlt("Redo last action"))
#    menu.Add(xlt("&Find"), xlt("Find string"), self.OnFind)
    menu.AppendSeparator()
    menu.Add(self.OnCut, xlt("Cu&t"), xlt("Cut selected text to clipboard"))
    menu.Add(self.OnCopy, xlt("&Copy"), xlt("Copy selected text to clipboard"))
    menu.Add(self.OnPaste, xlt("&Paste"), xlt("Paste text from clipboard"))
    menu.Add(self.OnClear, xlt("C&lear"), xlt("Clear editor"))
    menu.AppendSeparator()
    menu.Add(self.OnAddSnippet, xlt("Add snippet"), xlt("Add selected text to snippets"))
    menu.Add(self.OnReplaceSnippet, xlt("Modify snippet"), xlt("Replace snippet with selected text"))
    menubar.Append(menu, xlt("&Edit"))
    
    self.querymenu=menu=Menu(self)
    menu.Add(self.OnExecuteQuery, xlt("Execute"), xlt("Execute query"))
    menu.Add(self.OnExplainQuery, xlt("Explain"), xlt("Explain query"))
    menu.Add(self.OnCancelQuery, xlt("Cancel"), xlt("Cancel query execution"))
    menubar.Append(menu, xlt("&Query"))
    
    self.helpmenu=menu=Menu(self)
    menu.Add(self.OnHelp, xlt("Help"), xlt("Show help"), wx.ID_HELP)
    menubar.Append(menu, xlt("&Help"))
        
    self.EnableMenu(self.querymenu, self.OnCancelQuery, False)
    self.SetMenuBar(menubar)
    
    ah=AcceleratorHelper(self)
    ah.Add(wx.ACCEL_CTRL, 'X', self.OnCut)
    ah.Add(wx.ACCEL_CTRL, 'C', self.OnCopy)
    ah.Add(wx.ACCEL_CTRL, 'V', self.OnPaste)
    ah.Add(wx.ACCEL_NORMAL,wx.WXK_F5, self.OnExecuteQuery)
    ah.Add(wx.ACCEL_NORMAL,wx.WXK_F7, self.OnExplainQuery)
    ah.Add(wx.ACCEL_ALT,wx.WXK_PAUSE, self.OnCancelQuery)
    ah.Realize()

    self.editor=SqlEditor(self)
    self.editor.SetAcceleratorTable(ah.GetTable())
    
    self.editor.BindProcs(self.OnChangeStc, self.OnStatusPos)
    self.manager.AddPane(self.editor, wx.aui.AuiPaneInfo().Top().PaneBorder().Resizable().MinSize((200,100)).BestSize((400,200)).CloseButton(False) \
                          .Name("sqlQuery").Caption(xlt("SQL Query")))
    
    
    self.snippets=SnippetTree(self, self.server, self.editor)
    self.manager.AddPane(self.snippets, wx.aui.AuiPaneInfo().Left().Top().PaneBorder().Resizable().MinSize((100,100)).BestSize((100,100)).CloseButton(True) \
                          .Name("snippets").Caption(xlt("SQL Snippets")))

    if not self.snippet_table:
      self.manager.GetPane("snippets").Show(False)

    
    self.output=wx.Notebook(self)
    self.result=SqlResultGrid(self.output)
    self.explain = ExplainCanvas(self.output)
    self.explain.Hide()
    
    font=self.editor.GetFont()
    self.messages=wx.TextCtrl(self.output, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP)
    self.msgHistory=wx.TextCtrl(self.output, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP)
    self.messages.SetFont(font)
    self.msgHistory.SetFont(font)

    self.output.AddPage(self.result, xlt("Output"))
    self.output.AddPage(self.messages, xlt("Messages"))
    self.output.AddPage(self.msgHistory, xlt("History"))
        
    self.manager.AddPane(self.output, wx.aui.AuiPaneInfo().Center().MinSize((200,100)).BestSize((400,200)).CloseButton(False) \
                          .Name("Result").Caption(xlt("Result")).CaptionVisible(False))

    self.manager.Bind(wx.aui.EVT_AUI_PANE_CLOSE, self.OnAuiCloseEvent)

    self.SetStatus(xlt("ready"))
    self.restorePerspective()
    self.manager.GetPane("Result").Show()
    self.manager.Update()
    
    self.viewmenu.Check(self.OnToggleSnippets, self.manager.GetPane("snippets").IsShown())
    self.OnToggleToolBar()
    self.OnToggleStatusBar()
    self.updateMenu()
    query=params.get('query')
    if query:
      self.editor.SetText(query)
      pos=params.get('errline', -1)
      if pos:
        line=self.editor.LineFromPosition(int(pos))
        self.editor.MarkerSet(line)
      msg=params.get('message')
      if msg:
        self.messages.AppendText(msg)
        hint=params.get('hint')
        if hint:
          self.messages.AppendText("\n\nHINT:\n")
          self.messages.AppendText(hint)
        self.output.SetSelection(1)
    self.Show()
    self.editor.SetFocus()


  def SetTitle(self, dbName):
    title=xlt("PostGreSQL Query Tool - Database \"%(dbname)s\" on Server \"%(server)s\""  % { 'dbname': dbName, 'server': self.server.name})
    adm.Frame.SetTitle(self, title)


  def OnHelp(self, evt):
    wx.LaunchDefaultBrowser("http://www.admin4.org/docs/pgsql/querytool")
    
    
  def OnClose(self, evt):
    self.OnCancelQuery(None)
    for i in range(self.databases.GetCount()):
      conn=self.databases.GetClientData(i)
      if conn:
        conn.disconnect()
    super(QueryFrame, self).OnClose(evt)
    self.Destroy()
      
    
  def OnChangeDatabase(self, evt=None):
    i=self.databases.GetSelection()
    if i == self.databases.GetCount()-1:
      class ConnectDlg(adm.CheckedDialog):
        def __init__(self, frame):
          adm.CheckedDialog.__init__(self, frame)
          self.frame=frame
        
        def Go(self):
          self['Database'].AppendItems(self.frame.server.GetConnectableDbs())
          self['Database'].SetStringSelection(self.frame.server.maintDb)
        
        def Execute(self):
          user=dlg.User
          if user:  dbName="%s@%s" % (user, self.Database)
          else:     dbName=self.Database
          if self.frame.databases.FindString(dbName) < 0:
            try:
              conn = pgConnection(self.frame.server.GetDsn(self.Database, self.frame.application, user, self.password))
              self.frame.lastDatabaseSelection=self.frame.databases.GetCount()-1
              self.frame.databases.Insert(dbName, self.frame.lastDatabaseSelection, conn)
            except Exception as e:
              self.SetStatus(str(e))
              return False
            
          return True
          
      dlg=ConnectDlg(self)
      dlg.GoModal()
      self.databases.SetSelection(self.lastDatabaseSelection)
      return
    elif i >= 0:
      dbName=self.databases.GetString(i)
      self.conn = self.databases.GetClientData(i)
      if not self.conn:
        try:
          self.conn = pgConnection(self.server.GetDsn(dbName, self.application))
          self.databases.SetClientData(i, self.conn)
        except Exception as e:
          print str(e)
      self.SetTitle(dbName)
    self.lastDatabaseSelection=i
        

  def updateMenu(self, ctl=None):
    if not self.GetToolBar():
      return
    canCut=canPaste=canUndo=canRedo=False
    if not ctl or ctl == self.editor:
      canUndo=self.editor.CanUndo();
      canRedo=self.editor.CanRedo();
      canPaste=self.editor.CanPaste();
      canCut = True;
    a,e=self.editor.GetSelection()
    canQuery = not self.worker and ( a!=e or self.editor.GetLineCount() >1 or self.getSql() )


    self.EnableMenu(self.editmenu, self.OnAddSnippet, self.snippet_table)
    self.EnableMenu(self.editmenu, self.OnReplaceSnippet, self.snippets.CanReplace())
    self.EnableMenu(self.editmenu, self.OnCut, canCut)
    self.EnableMenu(self.editmenu, self.OnPaste, canPaste)
    self.EnableMenu(self.editmenu, self.OnUndo, canUndo)
    self.EnableMenu(self.editmenu, self.OnRedo, canRedo)
    self.EnableMenu(self.editmenu, self.OnClear, canQuery)
#    self.EnableMenu(self.editmenu, self.OnFind, canQuery)
    
    self.EnableMenu(self.filemenu, self.OnFileSave, self.sqlChanged)
    
    self.EnableMenu(self.querymenu, self.OnExecuteQuery, canQuery)
    self.EnableMenu(self.querymenu, self.OnExplainQuery, canQuery)
      
    
  def executeSql(self, targetPage, sql, _queryOffset=0, resultToMsg=False):
    self.EnableMenu(self.querymenu, self.OnCancelQuery, True)
    self.EnableMenu(self.querymenu, self.OnExecuteQuery, False)
    self.EnableMenu(self.querymenu, self.OnExplainQuery, False)
    
    wx.YieldIfNeeded()
    self.startTime=localTimeMillis();
    self.worker=worker=self.conn.GetCursor().ExecuteAsync(sql)
    rowcount=0
    rowset=None
    worker.start()
    
    self.SetStatus(xlt("Query is running."));
    self.SetStatusText("", self.STATUSPOS_SECS);
    self.SetStatusText("", self.STATUSPOS_ROWS);     
    self.msgHistory.AppendText(xlt("-- Executing query:\n"));
    self.msgHistory.AppendText(sql);
    self.msgHistory.AppendText("\n");
    self.editor.MarkerDelete()   
    self.messages.Clear()
    
    durationTxt=self.pollWorker()

    self.worker=None
    self.EnableMenu(self.querymenu, self.OnCancelQuery, False)
    self.EnableMenu(self.querymenu, self.OnExecuteQuery, True)
    self.EnableMenu(self.querymenu, self.OnExplainQuery, True)

    if worker.error:
      errmsg=worker.error.error
      errlines=errmsg.splitlines()

      self.messages.SetValue(errmsg)
      self.msgHistory.AppendText(errmsg)
      for i in range(1, len(errlines)):
        if errlines[i].startswith("LINE "):
          lineinfo=errlines[i].split(':')[0][5:]
          colinfo=errlines[i+1].find('^')
          dummy=colinfo
          self.editor.MarkerSet(int(lineinfo)-1 + self.editor.GetSelectOffset())
          break

    if worker.cancelled:
      self.SetStatus(xlt("Cancelled."));
    elif worker.error:
      self.SetStatus(errlines[0]);
    else:
      self.SetStatus(xlt("OK."));
      
      rowcount=worker.GetRowcount()
      rowset=worker.GetResult()


    if worker.error:
      self.SetStatusText("", self.STATUSPOS_ROWS)
    else:
      if rowcount == 1:
        rowsMsg=xlt("1 row affected")
      elif rowcount < 0:
        rowsMsg=xlt("Executed")
      else:
        rowsMsg= xlt("%d rows affected") % rowcount
      self.SetStatusText(rowsMsg, self.STATUSPOS_ROWS)
      self.msgHistory.AppendText("-- %s\n" % rowsMsg)
    
      rowsMsg += xlt("; %s execution time.") % durationTxt 
      
    self.msgHistory.AppendText("\n")
    currentPage=self.output.GetPage(0)
    if currentPage != targetPage:
      self.output.RemovePage(0)
      currentPage.Hide()
      targetPage.Show()
      self.output.InsertPage(0, targetPage, xlt("Data output"), True)

    if rowset and rowset.colNames:
      self.output.SetSelection(0)
      targetPage.SetData(rowset)
    else:
      self.output.SetSelection(1)
      targetPage.SetEmpty()

    for notice in self.conn.conn.notices:
      self.messages.AppendText(notice);
      self.messages.AppendText("\n")

    if not worker.error:
      if resultToMsg:
        self.messages.SetValue("\n".join(targetPage.GetResult()))
      else:
        self.messages.SetValue(rowsMsg)

    self.editor.SetFocus()

 
  def getSql(self):  
    sql=self.editor.GetSelectedText()
    if not sql:
      sql=self.editor.GetText()
    return sql.strip()
  
  
  def OnAuiCloseEvent(self, evt):
    if evt.GetPane().name == "snippets":
      self.filemenu.Check(self.OnToggleSnippets, False)

  
  def OnToggleSnippets(self, evt):
    paneInfo=self.manager.GetPane("snippets")
    how=self.viewmenu.IsChecked(self.OnToggleSnippets)
    if isinstance(evt.EventObject, wx.ToolBar):
      how=not how
      self.viewmenu.Check(self.OnToggleSnippets, how)
    paneInfo.Show(how)
    self.manager.Update()    
  
  def OnAddSnippet(self, evt):
    sql=self.getSql()
    if sql:
      dlg=wx.TextEntryDialog(self, xlt("Snippet name"), xlt("Add snippet"))
      if dlg.ShowModal() == wx.ID_OK:
        name=dlg.GetValue()
        self.snippets.AppendSnippet(name, sql)
        self.SetStatus(xlt("Snipped stored."))
    
  def OnReplaceSnippet(self, evt):
    sql=self.getSql()
    if sql:
      self.snippets.ReplaceSnippet(sql)


  def OnCancelQuery(self, evt):
    self.EnableMenu(self.querymenu, self.OnCancelQuery, False)
    if self.worker:
      self.worker.Cancel()

  def OnExecuteQuery(self, evt):
    sql=self.getSql()
    if not sql.strip():
      return
    self.executeSql(self.result, sql)

  def OnExplainQuery(self, evt):
    sql=self.getSql()
    if not sql:
      return
    self.executeSql(self.explain, "EXPLAIN %s" % sql, 8, True)

  
  def readFile(self, message, filename=None):
    if not filename:
      filename=self.fileManager.OpenFile(self, self.filePatterns, message)
    if filename:
      try:
        f=open(filename, 'r')
        sql=f.read()
        f.close()
        return sql
      except:
        self.SetStatus(xlt("Failed to read %s") % filename)
        return None
        
  def fileOpen(self, header, filename=None):
    sql=self.readFile(header, filename)
    if sql:
      self.editor.ClearAll()
      self.editor.ReplaceSelection(sql)
      self.SetStatus(xlt("%d characters read from %s") % (len(sql), self.fileManager.currentFile))
      self.updateMenu()

  def OnRecentFileOpened(self, filename):
    self.fileOpen(None, filename)
    
  def OnFileOpen(self, evt):
    self.fileOpen(xlt("Open SQL file"))
      
  
  def OnFileInsert(self, evt):
    sql=self.readFile(xlt("Insert SQL from file"))
    if sql:
      self.editor.ReplaceSelection(sql)
      self.SetStatus(xlt("%d characters inserted from %s") % (len(sql), self.fileManager.currentFile))
      self.updateMenu()
  
  
  def saveFile(self, proc):    
    try:
      ok=proc(self, self.editor.GetText(), self.filePatterns, xlt("Save SQL Query"))
      if ok:
        self.SetStatus(xlt("Saved SQL query to %s") % self.fileManager.filename)
        self.sqlChanged=False
        self.updateMenu() 
      else:
        self.StatusText(xlt("Nothing saved"))
    except:
      self.SetStatus(xlt("Failed to save to %s") % self.fileManager.filename)
      
  def OnFileSave(self, evt):
    self.saveFile(self.fileManager.SaveFile)
    
  def OnFileSaveAs(self, evt):
    self.saveFile(self.fileManager.SaveFileAs)
  
  
  def OnUndo(self, evt):
    self.editor.Undo()
  
  def OnClear(self, evt):
    self.editor.ClearAll()
    self.updateMenu()
    
  def OnFind(self, evt):
    pass
  
  def OnRedo(self, evt):
    self.editor.Redo()
  
  def OnChangeStc(self, evt):
    self.sqlChanged=True
    self.updateMenu()
    
  def OnStatusPos(self, evt):
    row=self.editor.LineFromPosition(self.editor.GetCurrentPos())+1
    col=self.editor.GetColumn(self.editor.GetCurrentPos())+1
    self.SetStatusText(xlt("Ln %d Col %d") % (row, col), self.STATUSPOS_POS)
Example #3
0
class FilterPanel(adm.NotebookPanel):
  def __init__(self, dlg, notebook):
    adm.NotebookPanel.__init__(self, dlg, notebook)
    self.Bind("LimitCheck", self.OnLimitCheck)
    self.Bind("FilterCheck", self.OnFilterCheck)
    self.Bind("FilterValidate", self.OnFilterValidate)
    self.FilterValue.BindProcs(self.OnFilterValueChanged, None)
    self.Bind("FilterPreset", wx.EVT_COMBOBOX, self.OnPresetSelect)
    self.Bind("FilterPreset", wx.EVT_TEXT, self.OnPresetChange)
    self.Bind("FilterSave", self.OnFilterSave)
    self['SortCols'].Bind(wx.EVT_LISTBOX_DCLICK, self.OnDclickSort)
    # TODO unfortunately we need 3.x here
    if True: # wx.Platform == "__WXMAC__" and wx.VERSION < (3,0):
      event=wx.EVT_LEFT_DOWN
    else:
      event=wx.EVT_MOTION
    self['DisplayCols'].Bind(event, self.OnBeginDrag)
    self['SortCols'].Bind(event, self.OnBeginDrag)
    self['DisplayCols'].Bind(wx.EVT_CHECKLISTBOX, self.OnClickCol)
    self.OnLimitCheck()
    self.OnFilterCheck()
    self.valid=True
    self.dialog=dlg
    self.EnableControls("FilterPreset", dlg.querypreset_table)
    self.EnableControls("FilterSave", False)

  def AddExtraControls(self, res):
    self.FilterValue=SqlEditor(self)
    res.AttachUnknownControl("FilterValuePlaceholder", self.FilterValue)
    self.FilterValue.SetMarginWidth(1, 0)

  def OnPresetSelect(self, evt):
    preset=self.FilterPreset.strip()
    if not preset:
      return
    query=pgQuery(self.dialog.querypreset_table, self.dialog.server.GetCursor())
    query.AddCol('querylimit')
    query.AddCol('filter')
    query.AddCol('sort')
    query.AddCol('display')
    query.AddCol('sql')
    query.AddWhere('dbname', self.tableSpecs.dbName)
    query.AddWhere('tabname', self.tableSpecs.tabName)
    query.AddWhere('presetname', preset)
    
    res=query.Select()
    for row in res:
      limit=row['querylimit']
      filter=row['filter']
      sort=evalAsPython(row['sort'])
      display=evalAsPython(row['display'])
      sql=row['sql']
      if limit:
        self.LimitCheck=True
        self.OnLimitCheck()
        self.LimitValue=limit
      else:
        self.LimitCheck=False
      if sql:
        self.dialog.editor.SetText(sql)
      
      if sort:
        sc=self['SortCols']
        sc.Clear()
        cols=self.tableSpecs.colNames[:]
        for col in sort:
          if col.endswith(' DESC'): colpure=col[:-5]
          else:                     colpure=col
          if colpure in cols:
            id=sc.Append(col)
            sc.Check(id, True)
            cols.remove(colpure)
        sc.AppendItems(cols)
      if display:
        dc=self['DisplayCols']
        dc.Clear()
        cols=self.tableSpecs.colNames[:]
        for col in display:
          if col in cols:
            id=dc.Append(col)
            dc.Check(id, True)
            cols.remove(col)
        dc.AppendItems(cols)
          
      if filter:
        self.FilterCheck=True
        self.OnFilterCheck()
        self.FilterValue.SetText(filter)
        self.OnFilterValidate(evt)
      else:
        self.FilterCheck=False

      break # only one row, hopefully
    
    self.OnPresetChange(evt)
    
  def OnPresetChange(self, evt):
    self.EnableControls("FilterSave", self.FilterPreset)
    
  def OnClickCol(self, evt):
    if evt.String in self.dialog.tableSpecs.keyCols:
      # don't un-display key colums; we need them
      evt.EventObject.Check(evt.Selection, True)
    pass
  
  def OnBeginDrag(self, evt):
    if evt.GetPosition().x < 30 or not evt.LeftDown():
      evt.Skip()
      return
    
    lb=evt.EventObject
    i=lb.HitTest(evt.GetPosition())
    if i >= 0:
      lb.SetDropTarget(TextDropTarget(lb))
      data=wx.PyTextDataObject(str(i))
      ds=wx.DropSource(lb)
      ds.SetData(data)
      ds.DoDragDrop(False)
      lb.SetDropTarget(None)
    
  def OnDclickSort(self, evt):
    colname=self['SortCols'].GetString(evt.Selection)
    if colname.endswith(" DESC"):
      colname=colname[:-5]
    else:
      colname = colname+" DESC"
    self['SortCols'].SetString(evt.Selection, colname)
  
  
  def OnFilterSave(self, evt):
    preset=self.FilterPreset
    if self.LimitCheck:   limit=self.LimitValue
    else:                 limit=None
    if self.FilterCheck:  filter=self.FilterValue.GetText()
    else:                 filter=None
    sort=self['SortCols'].GetCheckedStrings()
    display=self['DisplayCols'].GetCheckedStrings()
    sql=self.dialog.editor.GetText()
    
    query=pgQuery(self.dialog.querypreset_table, self.dialog.server.GetCursor())
    query.AddColVal('querylimit', limit)
    query.AddColVal('filter', filter)
    query.AddColVal('sort', unicode(sort))
    query.AddColVal('display', unicode(display))
    query.AddColVal('sql', sql)
    
    fp=self['FilterPreset']
    if fp.FindString(preset) < 0:
      query.AddColVal('dbname', self.tableSpecs.dbName)
      query.AddColVal('tabname', self.tableSpecs.tabName)
      query.AddColVal('presetname', preset)
      query.Insert()
      fp.Append(preset)
    else:
      query.AddWhere('dbname', self.tableSpecs.dbName)
      query.AddWhere('tabname', self.tableSpecs.tabName)
      query.AddWhere('presetname', preset)
      query.Update()
    
  def OnLimitCheck(self, evt=None):
    self.EnableControls("LimitValue", self.LimitCheck)

  def OnFilterCheck(self, evt=None):
    self.EnableControls("FilterValidate", self.FilterCheck)
    self.FilterValue.Enable(self.FilterCheck)
    self.OnFilterValueChanged(evt)

  def OnFilterValueChanged(self, evt):
    self.valid=not self.FilterCheck
    self.dialog.updateMenu()
  
  def OnFilterValidate(self, evt):
    self.valid=False
    
    sql="EXPLAIN " + self.GetQuery()
    cursor=self.tableSpecs.GetCursor()
    cursor.ExecuteSet(sql)  # will throw and show exception if invalid

    self.dialog.SetStatus(xlt("Filter expression valid"))
    self.valid=True
    self.dialog.updateMenu()

  def Go(self, tableSpecs):
    self.tableSpecs=tableSpecs
    dc=self['DisplayCols']
    sc=self['SortCols']
    
    for colName in self.tableSpecs.colNames:
      i=dc.Append(colName)
      dc.Check(i, True)
      i=sc.Append(colName)
      if colName in self.tableSpecs.keyCols:
        sc.Check(i, True)
    if self.dialog.querypreset_table:
      query=pgQuery(self.dialog.querypreset_table, self.dialog.server.GetCursor())
      query.AddCol('presetname')
      query.AddWhere('dbname', self.tableSpecs.dbName)
      query.AddWhere('tabname', self.tableSpecs.tabName)
      query.AddOrder('presetname')
      res=query.Select()
      fp=self['FilterPreset']
      for row in res:
        fp.Append(row[0])
      
      default=fp.FindString('default')
      if id >= 0:
        fp.SetSelection(default)
        self.OnPresetSelect(None)
        
  def GetQuery(self):
    query=pgQuery(self.tableSpecs.tabName)
    for colName in self['DisplayCols'].GetCheckedStrings():
      query.AddCol(colName, True)
    for colName in self['SortCols'].GetCheckedStrings():
      if colName.endswith(' DESC'):
        query.AddOrder(query.quoteIdent(colName[:-5]) + " DESC", False)
      else:
        query.AddOrder(colName, True)
    if self.FilterCheck:
      filter=self.FilterValue.GetText().strip()
      query.AddWhere(filter)
    
    sql= query.SelectQueryString()
    if self.LimitCheck:
      sql += "\n LIMIT %d" % self.LimitValue
    return sql