mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
390 lines
9.4 KiB
Python
Executable File
390 lines
9.4 KiB
Python
Executable File
# $Id$
|
|
#
|
|
# Copyright (C) 2000-2006 greg Landrum and Rational Discovery LLC
|
|
#
|
|
# @@ All Rights Reserved @@
|
|
#
|
|
""" defines class _DbConnect_, for abstracting connections to databases
|
|
|
|
"""
|
|
import RDConfig
|
|
import sys,types
|
|
import exceptions
|
|
if sys.platform == 'win32':
|
|
try:
|
|
raise NotImplementedError,'wxPython no longer supported'
|
|
#from Dbase import Gui
|
|
#from wxPython.wx import *
|
|
except:
|
|
haswx=0
|
|
else:
|
|
haswx=1
|
|
else:
|
|
haswx=0
|
|
|
|
class DbError(RuntimeError):
|
|
pass
|
|
|
|
from Dbase import DbUtils,DbInfo
|
|
import DbModule
|
|
|
|
|
|
class DbConnect(object):
|
|
""" This class is intended to abstract away many of the details of
|
|
interacting with databases.
|
|
|
|
It includes some GUI functionality
|
|
|
|
"""
|
|
def __init__(self,dbName='',tableName='',user='sysdba',password='masterkey'):
|
|
""" Constructor
|
|
|
|
**Arguments** (all optional)
|
|
|
|
- dbName: the name of the DB file to be used
|
|
|
|
- tableName: the name of the table to be used
|
|
|
|
- user: the username for DB access
|
|
|
|
- password: the password to be used for DB access
|
|
|
|
|
|
"""
|
|
|
|
self.dbName = dbName
|
|
self.tableName = tableName
|
|
self.user = user
|
|
self.password = password
|
|
self.cn = None
|
|
self.cursor = None
|
|
|
|
def UpdateTableNames(self,dlg):
|
|
""" Modifies a connect dialog to reflect new table names
|
|
|
|
**Arguments**
|
|
|
|
- dlg: the dialog to be updated
|
|
|
|
|
|
"""
|
|
self.user = self.userEntry.GetValue()
|
|
self.password = self.passwdEntry.GetValue()
|
|
self.dbName = self.dbBrowseButton.GetValue()
|
|
for i in xrange(self.dbTableChoice.Number()):
|
|
self.dbTableChoice.Delete(0)
|
|
|
|
names = self.GetTableNames()
|
|
|
|
for name in names:
|
|
self.dbTableChoice.Append(name)
|
|
dlg.sizer.Fit(dlg)
|
|
dlg.sizer.SetSizeHints(dlg)
|
|
dlg.Refresh()
|
|
|
|
if haswx:
|
|
def LaunchChoiceDialog(self,dlgParent):
|
|
""" launches the DB choice dialog
|
|
|
|
**Arguments**
|
|
|
|
- dlgParent: the parent of the dialog (should be a wxPython frame
|
|
or window)
|
|
|
|
**Notes**
|
|
|
|
- This dialog includes options to change:
|
|
|
|
1) the DB user name
|
|
|
|
2) the DB password
|
|
|
|
3) the actual DB file to be used
|
|
|
|
4) the name of the table to be used
|
|
|
|
"""
|
|
dlg = Gui.DbTableSelectDialog(dlgParent,-1)
|
|
if self.dbName:
|
|
dlg.SetDbName(self.dbName)
|
|
dlg.SetTableName(self.tableName)
|
|
dlg.Finalize()
|
|
res = dlg.ShowModal()
|
|
if res == wxID_OK:
|
|
self.dbName = dlg.GetDbName()
|
|
self.tableName = dlg.GetTableName()
|
|
self.user = dlg.GetUserName()
|
|
self.password = dlg.GetPassword()
|
|
else:
|
|
raise RuntimeError,'db choice cancelled'
|
|
else:
|
|
def LaunchChoiceDialog(self,dlgParent):
|
|
return
|
|
|
|
def GetTableNames(self,includeViews=0):
|
|
""" gets a list of tables available in a database
|
|
|
|
**Arguments**
|
|
|
|
- includeViews: if this is non-null, the views in the db will
|
|
also be returned
|
|
|
|
**Returns**
|
|
|
|
a list of table names
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbInfo.GetTableNames_
|
|
|
|
|
|
"""
|
|
return DbInfo.GetTableNames(self.dbName,self.user,self.password,
|
|
includeViews=includeViews)
|
|
|
|
def GetColumnNames(self,table='',join='',what='*',where='',**kwargs):
|
|
""" gets a list of columns available in the current table
|
|
|
|
**Returns**
|
|
|
|
a list of column names
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbInfo.GetColumnNames_
|
|
|
|
|
|
"""
|
|
if not table: table = self.tableName
|
|
return DbInfo.GetColumnNames(self.dbName,table,
|
|
self.user,self.password,
|
|
join=join,what=what)
|
|
def GetColumnNamesAndTypes(self,table='',join='',what='*',where='',**kwargs):
|
|
""" gets a list of columns available in the current table along with their types
|
|
|
|
**Returns**
|
|
|
|
a list of 2-tuples containing:
|
|
|
|
1) column name
|
|
|
|
2) column type
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbInfo.GetColumnNamesAndTypes_
|
|
|
|
|
|
"""
|
|
if not table: table = self.tableName
|
|
return DbInfo.GetColumnNamesAndTypes(self.dbName,table,
|
|
self.user,self.password,
|
|
join=join,what=what)
|
|
def GetColumns(self,fields,table='',join='',**kwargs):
|
|
""" gets a set of data from a table
|
|
|
|
**Arguments**
|
|
|
|
- fields: a string with the names of the fields to be extracted,
|
|
this should be a comma delimited list
|
|
|
|
**Returns**
|
|
|
|
a list of the data
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbUtils.GetColumns_
|
|
|
|
"""
|
|
if not table: table = self.tableName
|
|
return DbUtils.GetColumns(self.dbName,table,fields,
|
|
self.user,self.password,
|
|
join=join)
|
|
|
|
def GetData(self,table=None,fields='*',where='',removeDups=-1,join='',
|
|
transform=None,randomAccess=1,**kwargs):
|
|
""" a more flexible method to get a set of data from a table
|
|
|
|
**Arguments**
|
|
|
|
- table: (optional) the table to use
|
|
|
|
- fields: a string with the names of the fields to be extracted,
|
|
this should be a comma delimited list
|
|
|
|
- where: the SQL where clause to be used with the DB query
|
|
|
|
- removeDups: indicates which column should be used to recognize
|
|
duplicates in the data. -1 for no duplicate removal.
|
|
|
|
**Returns**
|
|
|
|
a list of the data
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbUtils.GetData_
|
|
|
|
|
|
"""
|
|
if table is None:
|
|
table = self.tableName
|
|
kwargs['forceList'] = kwargs.get('forceList',0)
|
|
return DbUtils.GetData(self.dbName,table,fieldString=fields,whereString=where,
|
|
user=self.user,password=self.password,removeDups=removeDups,
|
|
join=join,
|
|
transform=transform,randomAccess=randomAccess,**kwargs)
|
|
|
|
def GetDataCount(self,table=None,where='',join='',**kwargs):
|
|
""" returns a count of the number of results a query will return
|
|
|
|
**Arguments**
|
|
|
|
- table: (optional) the table to use
|
|
|
|
- where: the SQL where clause to be used with the DB query
|
|
|
|
- join: the SQL join clause to be used with the DB query
|
|
|
|
|
|
**Returns**
|
|
|
|
an int
|
|
|
|
**Notes**
|
|
|
|
- this uses _DbUtils.GetData_
|
|
|
|
"""
|
|
if table is None:
|
|
table = self.tableName
|
|
return DbUtils.GetData(self.dbName,table,fieldString='count(*)',whereString=where,
|
|
user=self.user,password=self.password,join=join,forceList=0)[0][0]
|
|
|
|
|
|
def GetCursor(self):
|
|
""" returns a cursor for direct manipulation of the DB
|
|
only one cursor is available
|
|
|
|
"""
|
|
if self.cursor is not None:
|
|
return self.cursor
|
|
|
|
self.cn = DbModule.connect(self.dbName,self.user,self.password)
|
|
self.cursor = self.cn.cursor()
|
|
return self.cursor
|
|
|
|
def KillCursor(self):
|
|
""" closes the cursor
|
|
|
|
"""
|
|
self.cursor = None
|
|
self.cn = None
|
|
|
|
def AddTable(self,tableName,colString):
|
|
""" adds a table to the database
|
|
|
|
**Arguments**
|
|
|
|
- tableName: the name of the table to add
|
|
|
|
- colString: a string containing column defintions
|
|
|
|
**Notes**
|
|
|
|
- if a table named _tableName_ already exists, it will be dropped
|
|
|
|
- the sqlQuery for addition is: "create table %(tableName) (%(colString))"
|
|
|
|
|
|
"""
|
|
c = self.GetCursor()
|
|
try:
|
|
c.execute('drop table %s cascade'%tableName)
|
|
except:
|
|
pass
|
|
else:
|
|
self.Commit()
|
|
|
|
addStr = 'create table %s (%s)'%(tableName,colString)
|
|
try:
|
|
c.execute(addStr)
|
|
except:
|
|
import traceback
|
|
print 'command failed:',addStr
|
|
traceback.print_exc()
|
|
else:
|
|
self.Commit()
|
|
def InsertData(self,tableName,vals):
|
|
""" inserts data into a table
|
|
|
|
**Arguments**
|
|
|
|
- tableName: the name of the table to manipulate
|
|
|
|
- vals: a sequence with the values to be inserted
|
|
|
|
"""
|
|
c = self.GetCursor()
|
|
if type(vals) != types.TupleType:
|
|
vals = tuple(vals)
|
|
insTxt = '('+','.join([DbModule.placeHolder]*len(vals))+')'
|
|
#insTxt = '(%s'%('%s,'*len(vals))
|
|
#insTxt = insTxt[0:-1]+')'
|
|
cmd = "insert into %s values %s"%(tableName,insTxt)
|
|
try:
|
|
c.execute(cmd,vals)
|
|
except:
|
|
import traceback
|
|
print 'insert failed:'
|
|
print cmd
|
|
print 'the error was:'
|
|
traceback.print_exc()
|
|
raise DbError,"Insert Failed"
|
|
|
|
def InsertColumnData(self,tableName,columnName,value,where):
|
|
""" inserts data into a particular column of the table
|
|
|
|
**Arguments**
|
|
|
|
- tableName: the name of the table to manipulate
|
|
|
|
- columnName: name of the column to update
|
|
|
|
- value: the value to insert
|
|
|
|
- where: a query yielding the row where the data should be inserted
|
|
|
|
"""
|
|
c = self.GetCursor()
|
|
cmd = "update %s set %s=%s where %s"%(tableName,columnName,
|
|
DbModule.placeHolder,where)
|
|
c.execute(cmd,(value,))
|
|
|
|
def AddColumn(self,tableName,colName,colType):
|
|
""" adds a column to a table
|
|
|
|
**Arguments**
|
|
|
|
- tableName: the name of the table to manipulate
|
|
|
|
- colName: name of the column to insert
|
|
|
|
- colType: the type of the column to add
|
|
|
|
"""
|
|
c = self.GetCursor()
|
|
try:
|
|
c.execute("alter table %s add %s %s"%(tableName,colName,colType))
|
|
except:
|
|
print 'AddColumn failed'
|
|
|
|
def Commit(self):
|
|
""" commits the current transaction
|
|
|
|
|
|
"""
|
|
self.cn.commit()
|
|
|