473,387 Members | 1,485 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,387 developers and data experts.

DB Connection Manager now supports mxODBC, win32ODBC and PyODBC

bartonc
6,596 Expert 4TB
This is a work in progress (current and active).
There are some issues to resolve in supporting multiple connection types and I plan to add PySQLite to the mix. The this update is due to my suggesting the accompanying helper functions in a recent post and noticing that the ones posted here are a bit out of date. I'll post those helpers in a separate thread.

I've also been working with the following database engines:
MySQL 5.x
SQLite3
JET engine 4.0

Here is the latest dbConection container which was originally called dbServer, but I'd love suggestions for a better name:
Expand|Select|Wrap|Line Numbers
  1. #-----------------------------------------------------------------------------
  2. # Name:        SQLConMan.py  ### This needs a better name ###
  3. # Purpose:     database connection handling. The DBServer() traps all errors and
  4. #              writes status to its master (which can be stdout). If an error does
  5. #              occure, Execute() returns None. This might be confusing since pyodbc
  6. #              returns None from execute() on quries that don't return a result set.
  7. #              It's interesting to not that db interface creator have begun add an
  8. #              execute() funtion to their connection objects.
  9. #
  10. # Author:      <your name>
  11. #
  12. # Created:     2007/10/13
  13. # RCS-ID:      $Id: wxdbtools.py $
  14. # Copyright:   (c) 2007
  15. # Licence:     <your licence>
  16. #-----------------------------------------------------------------------------
  17.  
  18. from time import time
  19.  
  20. ## MySQL is the default db here:
  21. ## MySQL differs from MSSQL and SQLite regarding TRANSACTION statemets  ##
  22. TRANSACTIONS = ('START TRANSACTION', 'BEGIN TRANSACTION')     # MySQL, SQLite & MSSQL
  23. TransactionQuery = TRANSACTIONS[0]
  24. ## and these have a different matrix of support
  25. LASTINSERTQUERIES = ('SELECT Last_Insert_Id()', 'SELECT @@IDENTITY') # MySQL & SQLite, MSSQL
  26. LastInsertQuery = LASTINSERTQUERIES[0]
  27. ## One idea for detecting the DB type is to try each one until it works ##
  28.  
  29. PYODBC = 'pyodbc'
  30. MXODBC = 'mxodbc'
  31. WIN23ODBC = 'win32odbc'
  32.  
  33. class SQLConMan(object):
  34.     global TransactionQuery
  35.     def __init__(self, master):
  36.         self.master = master      # a place to call write() on
  37.         self.dbConnection = None  # the API 2.0 connection object
  38.         self.dbCursor = None      # the API 2.0 cursor object
  39.  
  40.     def __getattribute__(self, name):
  41.         """Redirect method calls to the connection 'object'."""
  42.         try:
  43.             return object.__getattribute__(self, name)
  44.         except AttributeError:
  45.             # __getattribute__() only work for subtypes of object.
  46. ##            return object.__getattribute__(self.dbConnection, name)
  47.             return eval("self.dbConnection.%s" %(name))
  48.  
  49.     def Login(self, servername, username, password, autocommit=1, database="", conType=PYODBC):
  50.         """Attempt to create a database login. If successful, return
  51.            an open connection. Otherwise, return None."""
  52.         global OperationalError, ProgrammingError, DatabaseError, DriverError
  53.  
  54.         odbcstring = "DSN=%s;UID=%s;PWD=%s" %(servername, username, password)
  55.  
  56.         if conType == PYODBC:
  57.             from pyodbc import connect
  58.             from pyodbc import OperationalError
  59.             from pyodbc import ProgrammingError
  60.             from pyodbc import DatabaseError
  61.             from pyodbc import Error as DriverError
  62.             cac = int(not autocommit)
  63.             try:
  64.                 self.dbConnection = connect(odbcstring, autocommit=autocommit)
  65.                 self.dbCursor = self.dbConnection.cursor()
  66.             except (DatabaseError, OperationalError, DriverError), message:
  67.                 self.NoLogin(servername, username, message)
  68.                 return
  69.         elif conType == MXODBC:
  70.             from mx.ODBC.Windows import Connect
  71.             from mx.ODBC.Windows import OperationalError
  72.             from mx.ODBC.Windows import ProgrammingError
  73.             from mx.ODBC.Windows import DatabaseError
  74.             from mx.ODBC.Windows import error as DriverError
  75.             cac = int(not autocommit)
  76.             try:
  77.                 self.dbConnection = Connect(servername, user=username, password=password,
  78.                                             clear_auto_commit=cac)
  79.                 self.dbCursor = self.dbConnection.cursor()
  80.             except (DatabaseError, OperationalError), message:
  81.                 self.NoLogin(servername, username, message)
  82.                 return
  83.         elif conType == WIN32ODBC:
  84.             import odbc
  85.             from dbi import opError as OperationalError
  86.             from dbi import progError as ProgrammingError
  87.             from dbi import dataError as DatabaseError
  88.             from odbc import OdbcError as DriverError
  89.             try:
  90.                 self.dbConnection = odbc.odbc(odbcstring)
  91.                 self.dbCursor = self.dbConnection.cursor()
  92.             except (DatabaseError, OperationalError), message:
  93.                 self.NoLogin(servername, username, message)
  94.                 return
  95.  
  96.         self.master.write("%s has been logged onto %s\n" %(username, servername))
  97.         if database:
  98.             try:
  99.                 self.dbCursor('USE %s' %database)
  100.             except (DatabaseError, OperationalError):
  101.                 pass
  102.         return self.dbConnection
  103.  
  104.     def NoLogin(self, servername, username, message):
  105.         self.master.write('Couldn\'t log on to the server `%s` as `%s`\n' %(servername, username))
  106.         self.DBError("", message)
  107.  
  108.     def DBError(self, query, message):
  109.         """Format the current message and display it.
  110.            Report the query and error to the master."""
  111.         self.master.write('ODBC Error: %s\n' %message)
  112. ##        raise
  113. # all raised by PyODBC from various DBs #
  114. # """('42000', "[42000] [Microsoft][ODBC Microsoft Access Driver]
  115. # Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'. (-3500)")"""
  116. # """ ('42S02', "[42S02] [Microsoft][ODBC Microsoft Access Driver] 
  117. # The Microsoft Jet database engine cannot find the input table or query 'main'.  
  118. # Make sure it exists and that its name is spelled correctly. (-1305)")"""
  119.  
  120.  
  121. # """('42S02', "[42S02] [MySQL][ODBC 3.51 Driver][mysqld-5.0.22-community-max-nt]
  122. # Table 'hetap_setup.main' doesn't exist (1146)")"""
  123.  
  124. # """('HY000', '[HY000] near "USE": syntax error (1) (1)')"""
  125. # """('HY000', '[HY000] no such table: main (1) (1)')"""
  126.  
  127. ##        self.master.write('%s\nODBC Error %s #%d:  %s #%d\n' %(query, message[0], message[1],
  128. ##                          message[-2].split(']')[-1], message[-1]))
  129.  
  130.     def Execute(self, query, *params):
  131.         """Execution method reports on the number of rows affected and duration
  132.            of the database query execution and catches errors. Return a reference
  133.            to the cursor if no error ocurred, otherwise, None."""
  134.         cursor = self.dbCursor
  135.         if cursor:
  136.             try:
  137.                 now = time()
  138.                 if params:
  139.                     cursor.execute(query, *params)
  140.                 else:
  141.                     cursor.execute(query)
  142. ##                print cursor
  143. ##                nRows = cursor.rowcount
  144. ##                self.master.write("%s   " % query)
  145. ##                self.master.write("%d rows affected: %.2f sec.\n" %(nRows, time() - now))
  146.             except (DatabaseError, OperationalError, DriverError), message:
  147.                 self.DBError(query, message)
  148.                 return
  149.             return cursor
  150.  
  151.     def ExecuteScript(self, query):
  152.         """"""
  153.         for singlequery in query.split(';'):
  154.             if singlequery:
  155.                 self.Execute(singlequery + ';')
  156.  
  157.     def DBExists(self, database):
  158.         """Return True if database exists"""
  159.         cursor = self.Execute("show databases")
  160.         if cursor:
  161.             rows = cursor.fetchall()
  162.             return (database.strip('`').lower(),) in rows
  163.  
  164.     def TableExists(self, table):
  165.         """Return True if database exists"""
  166.         cursor = self.Execute("show tables")
  167.         if cursor:
  168.             rows = cursor.fetchall()
  169.             return (table.strip('`').lower(),) in rows
  170.  
  171.     def ConnectionIsOpen(self):
  172. ##        """Return 1 if the connection has been established and is not closed.
  173. ##           Return 0 if it is closed; None, if it has not been established."""
  174.         return self.dbConnection is not None
  175.  
  176.     def CloseConnection(self):
  177.         """Close the connection if it exists and is open."""
  178.         if self.dbConnection is not None:
  179.             try:
  180.                 self.dbConnection.close()
  181.                 self.master.write("Closed connection.\n")
  182.             except ProgrammingError:
  183.                 self.master.write("Connection is already closed!\n")
  184.         else:
  185.             self.master.write("Connection does not exist!\n")
  186.  
  187.     def SetMaster(self, master):
  188.         """Allow the master to be reset."""
  189.         self.master = master
  190.  
  191.   ## May want to rethink these ones ##
  192.  
  193.     def GetMaster(self):
  194.         return self.master
  195.  
  196.     def GetDbConnection(self):
  197.         return self.dbConnection
Oct 18 '07 #1
0 6870

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: timw.google | last post by:
I just downloaded the pyodbc source to try and install on my Linux FC3 box. I see that there is a setup.py file, but when I try to do a 'python setup.py build' (or just 'python setup.py') I get ...
5
by: Suresh | last post by:
Hi Guys I have Db2 server installed on remote server. i am connecting to that remote server by using VPN. I want to connect that remote DB2 server instance using my local machine DB2...
1
by: king kikapu | last post by:
Hi to all, can anyone give me a jump-start about how to call Stored Procedures from PyODBC ?? I want to execute a very simple testing Stored Procedure on an Sql Server database. I started...
2
by: Hitesh | last post by:
Hi currently I am using DNS and ODBC to connect to MS SQL database. Is there any other non-dns way to connect? If I want to run my script from different server I first have to create the DNS in...
0
by: timw.google | last post by:
How do I get a list of datasources with pyodbc? I know that with mx.ODBC.Windows I can use the DataSources method to get a dictionay containing the datasources. Is there a similar way to do this...
3
by: Joe Salmeri | last post by:
I have found a data corruption problem with pyodbc. OS = Windows XP SP2 DB = Microsoft Access XP PROBLEM: When selecting columns from a table that are of type Memo the value returned is...
3
by: Rajendran | last post by:
Hi all, I've installed pyodbc module to access my database (MS Access). I've setup a User level DSN to the database.mdb file. When I run my python code in the command prompt it is retrieving the...
0
by: john.goodleaf | last post by:
I've just built pyodbc 2.0.58 against freetds and unixodbc. When I attempt to invoke it, either from the test script or from the interpreter, I get: ImportError:...
0
by: dj | last post by:
Hello, I have just started working with minimock in doctest. I want to create a mock pyodbc object which returns a string value when the method execute is called. Here is my doctest: ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.