I've write a simple script to manage MySQL database, you can see it at http://docs.google.com/Doc?id=dhr2c3jq_8g3vv2t
below is from that link, but not valid for write rules
#!/usr/bin/env python
"""
for my lovely parent
MySQL Simple Query Browser
"""
__scriptname__ = "MySQL Simple Query Browser"
__author__ = "Triyadhi Surahman"
__email__ = "<triyadhi.surahman@gmail.com> <justrelay@yahoo.com>"
__date__ = "20051224 04:57:29 PM"
__version__ = "0.1.10"
import wx
import wx.grid as gridlib
import wx.lib.dialogs as dlg
import MySQLdb
import string
# Constant
# Menu File
ID_FILE_QUIT = 10001
# Menu Database
ID_DATABASE_CONNECT = 10201
ID_DATABASE_DISCONNECT = 10202
ID_DATABASE_CREATE = 10203
ID_DATABASE_DROP = 10204
ID_DATABASE_REFRESH = 10205
# Menu Table
ID_TABLE_CREATE = 10301
ID_TABLE_DROP = 10302
# Menu Query
ID_QUERY_EXECUTE = 10401
# Menu Help
ID_HELP_MANUAL = 10501
ID_HELP_ABOUT = 10502
# Misc
ID_BUTTON_ADD_TABLE_NAME_TYPE = 20001
ID_BUTTON_ADD_CREATE_TABLE = 20002
ID_COMBOBOX_DATABASE = 20003
ID_COMBOBOX_TABLE = 20004
ERROR_MESSAGE = True
# Tested MySQL command, 1st word only
has_result = ['ANALYZE', 'BACKUP', 'CHECK', 'CHECKSUM', 'DESCRIBE', 'OPTIMIZE', 'REPAIR', 'RESTORE', 'SELECT', 'SHOW']
no_result = ['ALTER', 'CREATE', 'DELETE', 'DROP', 'GRANT', 'INSERT', 'SET', 'RENAME', 'REVOKE', 'TRUNCATE', 'UPDATE', 'USE']
class DatabaseConnectDialog(wx.Dialog):
def __init__(self, parent, id, title):
wx.Dialog.__init__(self, parent, id, title)
self.boxvertical = wx.BoxSizer(wx.VERTICAL)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Connect To MySQL Server")
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
statictext.SetFont(font)
statictext.SetSize(statictext.GetBestSize())
boxhorizontal.Add(statictext, 0, wx.ALIGN_CENTER|wx.ALL, 5)
self.boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
gridsizer = wx.GridSizer(3, 2, 5, 5)
statictexthost = wx.StaticText(self, -1, "Host")
self.textctrlhost = wx.TextCtrl(self, -1, value="localhost")
statictextusername = wx.StaticText(self, -1, "Username")
#self.textctrlusername = wx.TextCtrl(self, -1)
self.textctrlusername = wx.TextCtrl(self, -1, value="root")
self.textctrlusername.SetFocus()
statictextpassword = wx.StaticText(self, -1, "Password")
self.textctrlpassword = wx.TextCtrl(self, -1, style=wx.TE_PASSWORD)
gridsizer.AddMany([
(statictexthost, 0, wx.EXPAND),
(self.textctrlhost, 0, wx.EXPAND),
(statictextusername, 0, wx.EXPAND),
(self.textctrlusername, 0, wx.EXPAND),
(statictextpassword, 0, wx.EXPAND),
(self.textctrlpassword, 0, wx.EXPAND)
])
self.boxvertical.Add(gridsizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
self.checkbox = wx.CheckBox(self, -1, "&Use Default Port (3306)")
self.checkbox.SetValue(True)
self.Bind(wx.EVT_CHECKBOX, self.CheckBoxChangePort, self.checkbox)
boxhorizontal.Add(self.checkbox, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
self.boxvertical.Add(boxhorizontal, 0, wx.ALIGN_LEFT | wx.ALL, 5)
self.gridsizerport = wx.GridSizer(1, 2, 5, 5)
statictextport = wx.StaticText(self, -1, "Port")
self.textctrlport = wx.TextCtrl(self, -1)
self.gridsizerport.AddMany([
(statictextport, 0, wx.EXPAND),
(self.textctrlport, 0, wx.EXPAND)
])
self.boxhorizontalport = wx.BoxSizer(wx.HORIZONTAL)
self.boxhorizontalport.Add(self.gridsizerport, 0, wx.ALIGN_CENTER | wx.ALL, 0)
self.boxhorizontalport.Show(self.gridsizerport, 0)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
cancel = wx.Button(self, wx.ID_CANCEL, " &Cancel ")
boxhorizontal.Add(cancel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
self.boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(self.boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
self.boxvertical.Fit(self)
def CheckBoxChangePort(self, event):
"""
If you want to use another port instead the default port
Alt+U or click on *Use Default Port* checkbox
"""
if event.IsChecked() == 0:
self.boxvertical.Insert(3, self.boxhorizontalport, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.boxvertical.Show(self.boxhorizontalport)
elif event.IsChecked() == 1:
self.boxvertical.Detach(self.gridsizerport)
# hidding the box
self.boxvertical.Show(self.boxhorizontalport, 0)
self.boxvertical.RecalcSizes()
self.boxvertical.Fit(self)
class DatabaseCreateDialog(wx.Dialog) :
def __init__(self, parent, id, title) :
wx.Dialog.__init__(self, parent, id, title)
boxvertical = wx.BoxSizer(wx.VERTICAL)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Create Database")
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
statictext.SetFont(font)
statictext.SetSize(statictext.GetBestSize())
boxhorizontal.Add(statictext, 0, wx.ALIGN_CENTER|wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
gridsizer = wx.GridSizer(1, 2, 5, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Database Name")
self.textctrl = wx.TextCtrl(self, -1)
gridsizer.AddMany([
(statictext, 0, wx.ALIGN_LEFT),
(self.textctrl, 0, wx.ALIGN_LEFT)
])
boxvertical.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
cancel = wx.Button(self, wx.ID_CANCEL, " &Cancel ")
boxhorizontal.Add(cancel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
boxvertical.Fit(self)
class DatabaseDropDialog(wx.Dialog) :
def __init__(self, parent, id, title, databases) :
wx.Dialog.__init__(self, parent, id, title)
boxvertical = wx.BoxSizer(wx.VERTICAL)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Drop Database")
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
statictext.SetFont(font)
statictext.SetSize(statictext.GetBestSize())
boxhorizontal.Add(statictext, 0, wx.ALIGN_CENTER|wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
gridsizer = wx.GridSizer(1, 2, 5, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Database Name")
self.combobox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
dbnamelist = databases
for d in dbnamelist :
self.combobox.Append(d)
gridsizer.AddMany([
(statictext, 0, wx.ALIGN_LEFT),
(self.combobox, 0, wx.ALIGN_LEFT)
])
boxvertical.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
cancel = wx.Button(self, wx.ID_CANCEL, " &Cancel ")
boxhorizontal.Add(cancel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
boxvertical.Fit(self)
class TableCreateDialog(wx.Dialog) :
def __init__(self, parent, id, title, databases) :
wx.Dialog.__init__(self, parent, id, title)
boxvertical = wx.BoxSizer(wx.VERTICAL)
notebook = wx.Notebook(self, -1)
paneltablename = wx.Panel(notebook, -1)
paneladd = wx.Panel(notebook, -1)
panelsyntax = wx.Panel(notebook, -1)
notebook.AddPage(paneltablename, "Name and Type")
notebook.AddPage(paneladd, "Add Fields")
notebook.AddPage(panelsyntax, "Syntax")
# BoxSizer vertical for paneltablename
boxptv = wx.BoxSizer(wx.VERTICAL)
gridsizer = wx.GridSizer(3, 2, 5, 5)
statictextdatabases = wx.StaticText(paneltablename, -1, "Database")
statictexttablename = wx.StaticText(paneltablename, -1, "Table Name")
statictexttabletype = wx.StaticText(paneltablename, -1, "Table Type")
self.comboboxdatabases = wx.ComboBox(paneltablename, -1)
self.textctrltablename = wx.TextCtrl(paneltablename, -1, size=self.comboboxdatabases.GetSize())
self.comboboxtabletype = wx.ComboBox(paneltablename, -1, style=wx.CB_READONLY)
dbnamelist = databases
for d in dbnamelist :
self.comboboxdatabases.Append(d)
tabletypelist = ['MyISAM', 'InnoDB', 'ISAM']
for t in tabletypelist :
self.comboboxtabletype.Append(t)
self.comboboxtabletype.SetValue(tabletypelist[0])
gridsizer.AddMany([
(statictextdatabases, 0, wx.ALIGN_LEFT),
(self.comboboxdatabases, 0, wx.ALIGN_LEFT),
(statictexttablename, 0, wx.ALIGN_LEFT),
(self.textctrltablename, 0, wx.ALIGN_LEFT),
(statictexttabletype, 0, wx.ALIGN_LEFT),
(self.comboboxtabletype, 0, wx.ALIGN_LEFT)
])
boxptv.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
button = wx.Button(paneltablename, ID_BUTTON_ADD_TABLE_NAME_TYPE, " &Add ")
boxhorizontal.Add(button, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxptv.Add(boxhorizontal, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
# event
self.Bind(wx.EVT_BUTTON, self.AddTableNameType, id=ID_BUTTON_ADD_TABLE_NAME_TYPE)
paneltablename.SetSizer(boxptv)
paneltablename.SetAutoLayout(True)
boxptv.Fit(paneltablename)
# BoxSizer vertical for paneladd
boxpav = wx.BoxSizer(wx.VERTICAL)
gridsizer = wx.GridSizer(9, 2, 5, 5)
statictextfieldname = wx.StaticText(paneladd, -1, "Field Name")
statictextdatatype = wx.StaticText(paneladd, -1, "Data Type")
statictextlengthvalues = wx.StaticText(paneladd, -1, "Length/Values")
statictextattributes = wx.StaticText(paneladd, -1, "Attributes")
statictextnull = wx.StaticText(paneladd, -1, "NULL")
statictextdefault = wx.StaticText(paneladd, -1, "Default")
statictextextra = wx.StaticText(paneladd, -1, "Extra")
statictextcolumndefinition = wx.StaticText(paneladd, -1, "Column Definition")
statictextfulltext = wx.StaticText(paneladd, -1, "Fulltext")
self.textctrlfieldname = wx.TextCtrl(paneladd, -1)
self.textctrlfieldname.SetFocus()
self.comboboxdatatype = wx.ComboBox(paneladd, -1, style=wx.CB_READONLY)
datatypelist = [
# numeric types
'TINYINT', 'BIT', 'BOOL', 'BOOLEAN', 'SMALLINT',
'MEDIUMINT', 'INT', 'INTEGER', 'BIGINT', 'FLOAT',
'DOUBLE', 'DOUBLE PRECISION','REAL', 'DECIMAL', 'DEC',
'NUMERIC', 'FIXED',
# date and time types
'DATE', 'DATETIME', 'TIMESTAMP', 'TIME', 'YEAR',
# string types
'CHAR', 'VARCHAR', 'BINARY', 'VARBINARY', 'TINYBLOB',
'TINYTEXT', 'BLOB', 'TEXT', 'MEDIUMBLOB', 'MEDIUMTEXT',
'LONGBLOB', 'LONGTEXT', 'ENUM', 'SET'
]
for d in datatypelist :
self.comboboxdatatype.Append(d)
self.textctrllengthvalues = wx.TextCtrl(paneladd, -1)
self.comboboxattributes = wx.ComboBox(paneladd, -1, style=wx.CB_READONLY)
attributeslist = ['', 'BINARY', 'UNSIGNED', 'UNSIGNED ZEROFILL']
for u in attributeslist :
self.comboboxattributes.Append(u)
self.comboboxnull = wx.ComboBox(paneladd, -1, style=wx.CB_READONLY)
nulllist = ['', 'NULL', 'NOT NULL']
for n in nulllist :
self.comboboxnull.Append(n)
self.textctrldefault = wx.TextCtrl(paneladd, -1)
self.comboboxextra = wx.ComboBox(paneladd, -1, style=wx.CB_READONLY)
extralist = ['', 'AUTO_INCREMENT']
for e in extralist :
self.comboboxextra.Append(e)
self.comboboxcolumndefinition = wx.ComboBox(paneladd, -1, style=wx.CB_READONLY)
columndefinitionlist = ['', 'PRIMARY KEY', 'INDEX', 'UNIQUE']
for p in columndefinitionlist :
self.comboboxcolumndefinition.Append(p)
self.checkboxfulltext = wx.CheckBox(paneladd, -1)
gridsizer.AddMany([
(statictextfieldname, 0, wx.ALIGN_LEFT),
(self.textctrlfieldname, 0, wx.ALIGN_LEFT),
(statictextdatatype, 0, wx.ALIGN_LEFT),
(self.comboboxdatatype, 0, wx.ALIGN_LEFT),
(statictextlengthvalues, 0, wx.ALIGN_LEFT),
(self.textctrllengthvalues, 0, wx.ALIGN_LEFT),
(statictextattributes, 0, wx.ALIGN_LEFT),
(self.comboboxattributes, 0, wx.ALIGN_LEFT),
(statictextnull, 0, wx.ALIGN_LEFT),
(self.comboboxnull, 0, wx.ALIGN_LEFT),
(statictextdefault, 0, wx.ALIGN_LEFT),
(self.textctrldefault, 0, wx.ALIGN_LEFT),
(statictextextra, 0, wx.ALIGN_LEFT),
(self.comboboxextra, 0, wx.ALIGN_LEFT),
(statictextcolumndefinition, 0, wx.ALIGN_LEFT),
(self.comboboxcolumndefinition, 0, wx.ALIGN_LEFT),
(statictextfulltext, 0, wx.ALIGN_LEFT),
(self.checkboxfulltext, 0, wx.ALIGN_LEFT)
])
boxpav.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
button = wx.Button(paneladd, ID_BUTTON_ADD_CREATE_TABLE, " &Add ")
#self.Bind(wx.EVT_BUTTON, self.OnAddCreateTable, id=ID_BUTTON_ADD_CREATE_TABLE)
boxhorizontal.Add(button, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxpav.Add(boxhorizontal, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
# event
self.Bind(wx.EVT_BUTTON, self.AddField, id=ID_BUTTON_ADD_CREATE_TABLE)
paneladd.SetSizer(boxpav)
paneladd.SetAutoLayout(True)
boxpav.Fit(paneladd)
# BoxSizer vertical for panelsyntax
boxpsv = wx.BoxSizer(wx.VERTICAL)
self.textctrlsyntax = wx.TextCtrl(panelsyntax, -1,
style=wx.TE_MULTILINE | wx.HSCROLL | wx.TE_RICH,
size=paneladd.GetSize())
boxpsv.Add(self.textctrlsyntax, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
panelsyntax.SetSizer(boxpsv)
panelsyntax.SetAutoLayout(True)
boxpsv.Fit(panelsyntax)
boxvertical.Add(notebook, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
cancel = wx.Button(self, wx.ID_CANCEL, " &Cancel ")
boxhorizontal.Add(cancel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
boxvertical.Fit(self)
self.ResetValue()
def ResetValue(self) :
self.syntaxvalue = ""
self.tabledetails = []
self.databasename = ""
self.tablename = ""
self.tabletype = ""
self.primarykey = ""
self.unique = ""
self.index = ""
self.fulltext = ""
def AddTableNameType(self, event) :
self.databasename = self.comboboxdatabases.GetValue()
self.tablename = self.textctrltablename.GetValue()
self.tabletype = self.comboboxtabletype.GetValue()
self.PanelSyntaxValue()
def AddField(self, event) :
item = ""
if len(self.tabledetails) > 0 :
item = ",n"
item += string.strip(self.textctrlfieldname.GetValue())
item += " " + self.comboboxdatatype.GetValue()
if len(string.strip(self.textctrllengthvalues.GetValue())) > 0 :
item += "(" + self.textctrllengthvalues.GetValue() + ")"
item += " " + self.comboboxattributes.GetValue()
item += " " + self.comboboxnull.GetValue()
if len(string.strip(self.textctrldefault.GetValue())) > 0 :
item += " DEFAULT '" + self.textctrldefault.GetValue() + "'"
item += " " + self.comboboxextra.GetValue()
if self.comboboxcolumndefinition.GetValue() == 'PRIMARY KEY' :
if len(self.primarykey) == 0 :
self.primarykey = self.textctrlfieldname.GetValue()
else :
self.primarykey += ", " + self.textctrlfieldname.GetValue()
elif self.comboboxcolumndefinition.GetValue() == 'INDEX' :
if len(self.index) == 0 :
self.index = self.textctrlfieldname.GetValue()
else :
self.index += ", " + self.textctrlfieldname.GetValue()
elif self.comboboxcolumndefinition.GetValue() == 'UNIQUE' :
if len(self.unique) == 0 :
self.unique = self.textctrlfieldname.GetValue()
else :
self.unique += ", " + self.textctrlfieldname.GetValue()
if self.checkboxfulltext.IsChecked() == 1 :
if len(self.fulltext) == 0 :
self.fulltext = self.textctrlfieldname.GetValue()
else :
self.fulltext += ", " + self.textctrlfieldname.GetValue()
self.tabledetails.append(item)
self.PanelSyntaxValue()
def PanelSyntaxValue(self) :
self.syntaxvalue = "CREATE TABLE " + self.databasename + "." + self.tablename + " (n"
for i in range(len(self.tabledetails)) :
self.syntaxvalue += self.tabledetails[i]
if len(self.primarykey) > 0 :
self.syntaxvalue += ",n PRIMARY KEY (" + self.primarykey + ")"
if len(self.index) > 0 :
self.syntaxvalue += ",n INDEX (" + self.index + ")"
if len(self.unique) > 0 :
self.syntaxvalue += ",n UNIQUE (" + self.unique + ")"
if len(self.fulltext) > 0 :
self.syntaxvalue += ",n FULLTEXT (" + self.fulltext + ")"
self.syntaxvalue += "n) TYPE=" + self.tabletype
self.textctrlsyntax.SetValue(self.syntaxvalue)
class TableDropDialog(wx.Dialog) :
def __init__(self, parent, id, title, connection, databases) :
wx.Dialog.__init__(self, parent, id, title)
self.connection = connection
boxvertical = wx.BoxSizer(wx.VERTICAL)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(self, -1, "Drop Table")
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
statictext.SetFont(font)
statictext.SetSize(statictext.GetBestSize())
boxhorizontal.Add(statictext, 0, wx.ALIGN_CENTER|wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
gridsizer = wx.GridSizer(2, 2, 5, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
statictextdb = wx.StaticText(self, -1, "Database Name")
self.comboboxdb = wx.ComboBox(self, ID_COMBOBOX_DATABASE, style=wx.CB_READONLY)
statictexttable = wx.StaticText(self, -1, "Table Name")
self.comboboxtable = wx.ComboBox(self, ID_COMBOBOX_TABLE, style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.DatabaseSelected, id=ID_COMBOBOX_DATABASE)
self.Bind(wx.EVT_COMBOBOX, self.TableSelected, id=ID_COMBOBOX_TABLE)
dbnamelist = databases
for d in dbnamelist :
self.comboboxdb.Append(d)
gridsizer.AddMany([
(statictextdb, 0, wx.ALIGN_LEFT),
(self.comboboxdb, 0, wx.ALIGN_LEFT),
(statictexttable, 0, wx.ALIGN_LEFT),
(self.comboboxtable, 0, wx.ALIGN_LEFT)
])
boxvertical.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
cancel = wx.Button(self, wx.ID_CANCEL, " &Cancel ")
boxhorizontal.Add(cancel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
boxvertical.Fit(self)
def DatabaseSelected(self, event) :
self.comboboxtable.Clear()
self.GetTable(self.connection, self.comboboxdb.GetValue())
def GetTable(self, connection, dbname) :
connection.query("""USE """ + dbname)
connection.query("""SHOW TABLES""")
r = connection.store_result()
f = r.fetch_row(maxrows=0)
for i in range(len(f)) :
self.comboboxtable.Append(f[i][0])
def TableSelected(self, event) :
self.dropsyntax = "DROP TABLE " + self.comboboxdb.GetValue() + "." + self.comboboxtable.GetValue()
class HelpAbout(wx.Dialog) :
def __init__(self, parent, id, title) :
wx.Dialog.__init__(self, parent, id, title)
boxvertical = wx.BoxSizer(wx.VERTICAL)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
namelabel = wx.StaticText(self, -1, __scriptname__)
font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
namelabel.SetFont(font)
namelabel.SetSize(namelabel.GetBestSize())
namelabel.SetSize(namelabel.GetBestSize())
boxhorizontal.Add(namelabel, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
gridsizer = wx.GridSizer(3, 2, 5, 5)
authorlabel = wx.StaticText(self, -1, "Author")
authorvalue = wx.StaticText(self, -1, __author__)
emaillabel = wx.StaticText(self, -1, "Email")
emailvalue = wx.StaticText(self, -1, __email__)
versionlabel = wx.StaticText(self, -1, "Version")
versionvalue = wx.StaticText(self, -1, __version__)
datelabel = wx.StaticText(self, -1, "Date")
datevalue = wx.StaticText(self, -1, __date__)
gridsizer.AddMany([
(authorlabel, 0, wx.ALIGN_LEFT),
(authorvalue, 0, wx.ALIGN_LEFT),
(emaillabel, 0, wx.ALIGN_LEFT),
(emailvalue, 0, wx.ALIGN_LEFT),
(versionlabel, 0, wx.ALIGN_LEFT),
(versionvalue, 0, wx.ALIGN_LEFT),
(datelabel, 0, wx.ALIGN_LEFT),
(datevalue, 0, wx.ALIGN_LEFT)
])
boxvertical.Add(gridsizer, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxhorizontal = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self, wx.ID_OK, " &OK ")
ok.SetDefault()
boxhorizontal.Add(ok, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
boxvertical.Add(boxhorizontal, 0, wx.ALIGN_CENTER | wx.ALL, 5)
self.SetSizer(boxvertical)
# We need it if we want to change the layout automatically
# see CheckBoxChangePort
self.SetAutoLayout(True)
boxvertical.Fit(self)
class HelpManual(dlg.ScrolledMessageDialog) :
def __init__(self, parent) :
f = open("manual.txt", "r")
msg = f.read()
f.close()
dlg.ScrolledMessageDialog.__init__(self, parent, msg, caption="Manual")
def OnOK(self, event) :
self.Destroy()
event.Skip()
class ErrorMessageDialog(dlg.ScrolledMessageDialog) :
def __init__(self, parent, msg) :
dlg.ScrolledMessageDialog.__init__(self, parent, msg, caption="Query Error")
def OnOK(self, event) :
self.Destroy()
event.Skip()
class MainFrame(wx.Frame):
# Style
style = {
'frame': wx.DEFAULT_FRAME_STYLE,
'splitter': wx.SUNKEN_BORDER | wx.CLIP_CHILDREN,
'textctrl': wx.TE_MULTILINE | wx.HSCROLL | wx.TE_RICH
}
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title,
size=wx.Size(750, 550),
style=self.style['frame'])
self.CentreOnScreen()
# Menu Bar
menubar = wx.MenuBar()
# Menu : File
menufile = wx.Menu()
menufile.Append(ID_FILE_QUIT, "&QuittCtrl+Q")
menubar.Append(menufile, "&File")
# Event
self.Bind(wx.EVT_MENU, self.MenuFileQuit, id=ID_FILE_QUIT)
# Menu : Database
menudatabase = wx.Menu()
menudatabase.Append(ID_DATABASE_CONNECT, "C&onnecttF11")
menudatabase.Append(ID_DATABASE_DISCONNECT, "D&isconnecttF12")
menudatabase.AppendSeparator()
menudatabase.Append(ID_DATABASE_CREATE, "&Create")
menudatabase.Append(ID_DATABASE_DROP, "&Drop")
menudatabase.AppendSeparator()
menudatabase.Append(ID_DATABASE_REFRESH, "&RefreshtCtrl+R")
menubar.Append(menudatabase, "&Database")
# Event
self.Bind(wx.EVT_MENU, self.MenuDatabaseConnect, id=ID_DATABASE_CONNECT)
self.Bind(wx.EVT_MENU, self.MenuDatabaseDisconnect, id=ID_DATABASE_DISCONNECT)
self.Bind(wx.EVT_MENU, self.MenuDatabaseCreate, id=ID_DATABASE_CREATE)
self.Bind(wx.EVT_MENU, self.MenuDatabaseDrop, id=ID_DATABASE_DROP)
self.Bind(wx.EVT_MENU, self.MenuDatabaseRefresh, id=ID_DATABASE_REFRESH)
# Menu : Table
menutable = wx.Menu()
menutable.Append(ID_TABLE_CREATE, "&Create")
menutable.Append(ID_TABLE_DROP, "&Drop")
menubar.Append(menutable, "&Table")
# Event
self.Bind(wx.EVT_MENU, self.MenuTableCreate, id=ID_TABLE_CREATE)
self.Bind(wx.EVT_MENU, self.MenuTableDrop, id=ID_TABLE_DROP)
# Menu : Query
menuquery = wx.Menu()
menuquery.Append(ID_QUERY_EXECUTE, "&ExecutetF5")
menubar.Append(menuquery, "&Query")
# Event
self.Bind(wx.EVT_MENU, self.MenuQueryExecute, id=ID_QUERY_EXECUTE)
# Menu : Help
menuhelp = wx.Menu()
menuhelp.Append(ID_HELP_MANUAL, "&ManualtF1")
menuhelp.AppendSeparator()
menuhelp.Append(ID_HELP_ABOUT, "&About")
menubar.Append(menuhelp, "&Help")
# Event
self.Bind(wx.EVT_MENU, self.MenuHelpManual, id=ID_HELP_MANUAL)
self.Bind(wx.EVT_MENU, self.MenuHelpAbout, id=ID_HELP_ABOUT)
self.SetMenuBar(menubar)
# Status Bar
self.statusbar = wx.StatusBar(self)
self.statusbar.SetFieldsCount(4)
widths = [-2, -1, 50, 50]
self.statusbar.SetStatusWidths(widths)
self.SetStatusBar(self.statusbar)
self.statusbar.SetStatusText("No Database Selected", 1)
# Split the Window
splitter1 = wx.SplitterWindow(self, style=self.style['splitter'])
splitter2 = wx.SplitterWindow(splitter1, style=self.style['splitter'])
# TextCtrl
self.textctrl = wx.TextCtrl(splitter2, -1, style=self.style['textctrl'])
self.textctrl.SetFocus()
# Grid
self.grid = gridlib.Grid(splitter2, -1)
self.grid.CreateGrid(1, 1)
self.grid.SetColLabelValue(0, "")
self.grid.SetRowLabelValue(0, "")
self.grid.EnableEditing(0)
self.grid.SetColLabelSize(20)
self.grid.SetRowLabelSize(0)
self.gridcols = 0
self.gridrows = 0
# TreeCtrl
self.treectrl = wx.TreeCtrl(splitter1, -1)
self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged, self.treectrl)
splitter2.SplitHorizontally(self.textctrl, self.grid, -275)
splitter1.SplitVertically(self.treectrl, splitter2, 150)
splitter1.SetMinimumPaneSize(20)
splitter2.SetMinimumPaneSize(20)
def MenuFileQuit(self, event) :
"""
Alt+F+Q or Ctrl+Q
"""
self.Close()
event.Skip()
def MenuDatabaseConnect(self, event) :
"""
Show the database connect dialog, Alt+D+O or F11
"""
dcd = DatabaseConnectDialog(self, -1, "Connect")
dcd.CenterOnScreen()
dcd.Show()
if dcd.ShowModal() == wx.ID_OK :
_host = dcd.textctrlhost.GetValue()
_user = dcd.textctrlusername.GetValue()
_passwd = dcd.textctrlpassword.GetValue()
if dcd.checkbox.IsChecked() == 0 :
# we need port as an integer
_port = int(dcd.textctrlport.GetValue())
self.DBConnect(_host, _user, _passwd, _port)
else :
self.DBConnect(_host, _user, _passwd)
dcd.Destroy()
event.Skip()
def MenuDatabaseDisconnect(self, event) :
"""
Alt+D+I or F11
"""
try :
self.DBClose()
except :
pass
event.Skip()
def MenuDatabaseCreate(self, event) :
"""
Show the database create dialog, Alt+D+C or F11
"""
databasecreate = DatabaseCreateDialog(self, -1, "Create")
databasecreate.CenterOnScreen()
databasecreate.Show()
if databasecreate.ShowModal() == wx.ID_OK :
self.ExecuteSQL(self.SplitSQL("CREATE DATABASE " + databasecreate.textctrl.GetValue()))
databasecreate.Destroy()
event.Skip()
def MenuDatabaseDrop(self, event) :
"""
Show the database drop dialog, Alt+D+D or F11
"""
databasedrop = DatabaseDropDialog(self, -1, "Drop", self.databases)
databasedrop.CenterOnScreen()
databasedrop.Show()
if databasedrop.ShowModal() == wx.ID_OK :
self.ExecuteSQL(self.SplitSQL("DROP DATABASE " + databasedrop.combobox.GetValue()))
databasedrop.Destroy()
event.Skip()
def MenuDatabaseRefresh(self, event) :
"""
Refresh database, get host, databases, and tables, Alt+D+R or Ctrl+R
"""
try :
rootitem = self.treectrl.GetItemText(self.treectrl.GetRootItem())
self.treectrl.DeleteAllItems()
self.DBGetDatabasesAndTables(rootitem)
except :
pass
event.Skip()
def MenuTableCreate(self, event) :
"""
Show the table create dialog, Alt+T+C
"""
tablecreatedialog = TableCreateDialog(self, -1, "Create Table", self.databases)
tablecreatedialog.CenterOnScreen()
tablecreatedialog.Show()
if tablecreatedialog.ShowModal() == wx.ID_OK :
self.ExecuteSQL(self.SplitSQL(tablecreatedialog.textctrlsyntax.GetValue()))
tablecreatedialog.ResetValue()
tablecreatedialog.Destroy()
event.Skip()
def MenuTableDrop(self, event) :
"""
Show the table drop dialog, Alt+T+D
"""
tabledrop = TableDropDialog(self, -1, "Drop Table", self.db, self.databases)
tabledrop.CenterOnScreen()
tabledrop.Show()
if tabledrop.ShowModal() == wx.ID_OK :
self.ExecuteSQL(self.SplitSQL(tabledrop.dropsyntax))
tabledrop.Destroy()
event.Skip()
def MenuQueryExecute(self, event) :
"""
Execute query, Alt+Q+E or F5
"""
self.ExecuteSQL(self.SplitSQL(self.textctrl.GetValue()))
event.Skip()
def MenuHelpManual(self, event) :
"""
Show the Manual, Alt+H+M or F1
"""
helpmanual = HelpManual(self)
helpmanual.Show()
def MenuHelpAbout(self, event) :
"""
Show the About dialog, Alt+H+A
"""
helpabout = HelpAbout(self, -1, "About")
helpabout.CenterOnScreen()
helpabout.Show()
event.Skip()
def DBConnect(self, _host, _user, _passwd, _port=3306) :
try :
self.db = MySQLdb.connect(host=_host, user=_user, passwd=_passwd, port=_port)
self.DBGetDatabasesAndTables(_host)
except MySQLdb.Error, details:
print "Error ", details
if ERROR_MESSAGE :
err = ErrorMessageDialog(self, ("Error " + str(details)))
err.Show()
def DBGetDatabasesAndTables(self, _host) :
try :
self.treeroot = self.treectrl.AddRoot(_host)
self.db.query("""SHOW DATABASES""")
r = self.db.store_result()
fr = r.fetch_row(maxrows=0)
self.databases = []
self.dbmap = {}
for i in fr :
self.databases.append(i[0])
for i in self.databases :
d = self.treectrl.AppendItem(self.treeroot, i)
self.dbmap[i] = d
self.db.query("""USE """ + i)
self.db.query("""SHOW TABLES""")
rt = self.db.store_result()
frt = rt.fetch_row(maxrows=0)
tables = []
for j in frt :
tables.append(j[0])
for j in tables :
t = self.treectrl.AppendItem(d, j)
self.db.query("""DESCRIBE """ + j)
rf = self.db.store_result()
frf = rf.fetch_row(maxrows=0)
field = []
for k in frf :
field.append(k[0])
for k in field :
fi = self.treectrl.AppendItem(t, k)
self.treectrl.Expand(self.treeroot)
except MySQLdb.Error, details :
print "Error ", details
if ERROR_MESSAGE :
err = ErrorMessageDialog(self, ("Error " + str(details)))
err.Show()
def DBClose(self) :
self.db.close()
self.treectrl.DeleteAllItems()
def SplitSQL(self, sql) :
"""
currently only supported the '#' comment
"""
sql = string.strip(sql)
tup = []
b = False
# get the # and n location and place it in 'tup' list
for i in range(len(sql)) :
if sql[i] == "#" :
b = True
index = i
while b :
if index < len(sql) :
if sql[index] == "n" :
b = False
front = i
end = index
index += 1
else :
b = False
front = i
end = index
tup.append((front, end))
index = 0
tup2 = []
# get char >= tup[i][0] and <= tup[i][1] and place it in tup2
for i in range(len(tup)) :
tup2.append("")
for j in range(tup[i][0], tup[i][1]) :
tup2[i] += sql[j]
# replace sql char with "" when it's found in tup2
for i in range(len(tup2)) :
try :
sql = string.replace(sql, tup2[i], "")
except :
pass
# replace, split, strip, and return
sql = string.replace(sql, "n", "")
ret = sql.split(";")
for i in range(len(ret)) :
ret[i] = string.strip(ret[i])
return ret
def ExecuteSQL(self, sql=[]) :
query = []
query = sql
success = False
errormessage = ""
for q in range(len(query)) :
# MySQL command
command = query[q].split(" ", 1)
if len(query[q]) > 0 :
# Set up the grid
self.grid.DeleteCols(0, self.gridcols, 1)
self.grid.DeleteRows(0, self.gridrows, 1)
self.grid.SetColLabelValue(0, "")
self.grid.SetColSize(0, self.grid.GetDefaultColSize())
self.grid.SetRowSize(0, self.grid.GetDefaultRowSize())
self.grid.ClearGrid()
try :
self.db.query(query[q])
r = self.db.store_result()
success = True
except MySQLdb.Error, detail :
success = False
self.gridcols = 0
self.gridrows = 0
print "Error", detail
errormessage += query[q] + "nError " + str(detail) + "nnn"
if success :
if command[0].upper() in has_result :
f = r.fetch_row(maxrows=0, how=1)
if len(f) >= 1 :
self.gridcols = len(f[0].keys())
self.gridrows = len(f)
self.grid.InsertCols(0, (self.gridcols - 1))
for i in range(len(f[0].keys())) :
self.grid.SetColLabelValue(i, f[0].keys()[i])
self.grid.InsertRows(1, len(f) - 1, 0)
for i in range(len(f)) :
for j in range(len(f[i].values())) :
if f[i].values()[j] == None :
self.grid.SetCellValue(i, j, "NULL")
else :
self.grid.SetCellValue(i, j, str(f[i].values()[j]))
self.grid.AutoSizeColumns(1)
self.grid.AutoSizeRows(1)
self.gridcols = j
self.gridrows = i
self.statusbar.SetStatusText(str(self.gridrows + 1), 2)
else :
self.gridcols = 0
self.gridrows = 0
elif command[0].upper() in no_result :
self.gridcols = 0
self.gridrows = 0
self.statusbar.SetStatusText("0", 2)
if command[0].upper() == 'USE' :
try :
item = self.dbmap[command[1].strip()]
self.treectrl.SelectItem(item)
self.treectrl.EnsureVisible(item)
self.treectrl.Expand(item)
except :
pass
else :
self.gridcols = 0
self.gridrows = 0
m = "Sorry, not supported or not tested yet."
print "Sorry, not supported or not tested yet."
errormessage += query[q] + "n" + m
else :
pass
if ERROR_MESSAGE :
if len(errormessage) > 0 :
err = ErrorMessageDialog(self, errormessage)
err.Show()
def OnTreeSelChanged(self, event) :
dbname = self.treectrl.GetItemText(event.GetItem())
if dbname in self.databases :
self.db.select_db(dbname)
self.statusbar.SetStatusText(str(dbname), 1)
event.Skip()
def OnCloseWindow(self, event):
try :
self.DBClose()
except :
pass
self.Destroy()
class MyApp(wx.App):
"""
We must have it
"""
def OnInit(self):
frame = MainFrame(None, __scriptname__)
frame.Show()
self.SetTopWindow(frame)
return True
def main():
app = MyApp(False)
app.MainLoop()
if __name__ == "__main__":
main()
Thursday, April 19, 2007
Subscribe to:
Posts (Atom)