root / pykota / trunk / pykota / storages / mysqlstorage.py @ 3260

Revision 3260, 6.8 kB (checked in by jerome, 16 years ago)

Changed license to GNU GPL v3 or later.
Changed Python source encoding from ISO-8859-15 to UTF-8 (only ASCII
was used anyway).

  • Property svn:keywords set to Author Date Id Revision
RevLine 
[3260]1# -*- coding: UTF-8 -*-
[2639]2#
[3260]3# PyKota : Print Quotas for CUPS
[2639]4#
[3133]5# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
[3260]6# This program is free software: you can redistribute it and/or modify
[2639]7# it under the terms of the GNU General Public License as published by
[3260]8# the Free Software Foundation, either version 3 of the License, or
[2639]9# (at your option) any later version.
[3260]10#
[2639]11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
[3260]17# along with this program.  If not, see <http://www.gnu.org/licenses/>.
[2639]18#
[2645]19# $Id$
[2639]20#
21#
22
[3184]23"""This module defines a class to access to a MySQL database backend."""
24
[2741]25import time
26
[2830]27from pykota.storage import PyKotaStorageError, BaseStorage
[2639]28from pykota.storages.sql import SQLStorage
29
30try :
31    import MySQLdb
32except ImportError :   
33    import sys
34    # TODO : to translate or not to translate ?
35    raise PyKotaStorageError, "This python version (%s) doesn't seem to have the MySQL module installed correctly." % sys.version.split()[0]
36
37class Storage(BaseStorage, SQLStorage) :
38    def __init__(self, pykotatool, host, dbname, user, passwd) :
39        """Opens the MySQL database connection."""
40        BaseStorage.__init__(self, pykotatool)
41        try :
42            (host, port) = host.split(":")
43            port = int(port)
44        except ValueError :   
[2874]45            port = 3306           # Use the default MySQL port
[2639]46       
47        self.tool.logdebug("Trying to open database (host=%s, port=%s, dbname=%s, user=%s)..." % (host, port, dbname, user))
[3009]48        try :
[3138]49            self.database = MySQLdb.connect(host=host, port=port, db=dbname, user=user, passwd=passwd, charset="utf8")
50        except TypeError :   
51            self.tool.logdebug("'charset' argument not allowed with this version of python-mysqldb, retrying without...")
52            self.database = MySQLdb.connect(host=host, port=port, db=dbname, user=user, passwd=passwd)
53           
54        try :
[3009]55            self.database.autocommit(1)
56        except AttributeError :   
[3010]57            raise PyKotaStorageError, _("Your version of python-mysqldb is too old. Please install a newer release.")
[2644]58        self.cursor = self.database.cursor()
[2954]59        self.cursor.execute("SET NAMES 'utf8';")
[2821]60        self.cursor.execute("SET TRANSACTION ISOLATION LEVEL READ COMMITTED;") # Same as PostgreSQL and Oracle's default
[2639]61        self.closed = 0
62        self.tool.logdebug("Database opened (host=%s, port=%s, dbname=%s, user=%s)" % (host, port, dbname, user))
63           
64    def close(self) :   
65        """Closes the database connection."""
66        if not self.closed :
[2644]67            self.cursor.close()
[2639]68            self.database.close()
69            self.closed = 1
70            self.tool.logdebug("Database closed.")
71       
72    def beginTransaction(self) :   
73        """Starts a transaction."""
[2741]74        self.before = time.time()
[2646]75        self.cursor.execute("BEGIN;")
[2639]76        self.tool.logdebug("Transaction begins...")
77       
78    def commitTransaction(self) :   
79        """Commits a transaction."""
80        self.database.commit()
[2741]81        after = time.time()
[2639]82        self.tool.logdebug("Transaction committed.")
[3183]83        #self.tool.logdebug("Transaction duration : %.4f seconds" % (after - self.before))
[2639]84       
85    def rollbackTransaction(self) :     
86        """Rollbacks a transaction."""
87        self.database.rollback()
[2741]88        after = time.time()
[2639]89        self.tool.logdebug("Transaction aborted.")
[3183]90        #self.tool.logdebug("Transaction duration : %.4f seconds" % (after - self.before))
[2639]91       
92    def doRawSearch(self, query) :
93        """Does a raw search query."""
94        query = query.strip()   
95        if not query.endswith(';') :   
96            query += ';'
97        try :
[2741]98            before = time.time()
[2639]99            self.tool.logdebug("QUERY : %s" % query)
100            self.cursor.execute(query)
101        except self.database.Error, msg :   
102            raise PyKotaStorageError, str(msg)
103        else :   
[2644]104            # This returns a list of lists. Integers are returned as longs.
[2741]105            result = self.cursor.fetchall()
106            after = time.time()
[3183]107            #self.tool.logdebug("Query Duration : %.4f seconds" % (after - before))
[2741]108            return result
[2639]109           
110    def doSearch(self, query) :       
111        """Does a search query."""
112        result = self.doRawSearch(query)
[2644]113        if result :
114            rows = []
[2639]115            fields = {}
116            for i in range(len(self.cursor.description)) :
[2644]117                fields[i] = self.cursor.description[i][0]
118            for row in result :
[2639]119                rowdict = {}
120                for field in fields.keys() :
[2644]121                    value = row[field]
122                    try :
123                        value = value.encode("UTF-8")
124                    except:
125                        pass
126                    rowdict[fields[field]] = value
127                rows.append(rowdict)
128            # returns a list of dicts
129            return rows
[2639]130
131    def doModify(self, query) :
132        """Does a (possibly multiple) modify query."""
133        query = query.strip()   
134        if not query.endswith(';') :   
135            query += ';'
136        try :
[2741]137            before = time.time()
[2639]138            self.tool.logdebug("QUERY : %s" % query)
139            self.cursor.execute(query)
140        except self.database.Error, msg :   
[2773]141            self.tool.logdebug("Query failed : %s" % repr(msg))
[2639]142            raise PyKotaStorageError, str(msg)
[2741]143        else :   
144            after = time.time()
[3183]145            #self.tool.logdebug("Query Duration : %.4f seconds" % (after - before))
[2639]146           
147    def doQuote(self, field) :
148        """Quotes a field for use as a string in SQL queries."""
149        if type(field) == type(0.0) :
150            return field
151        elif type(field) == type(0) :
152            return field
153        elif type(field) == type(0L) :
154            return field
155        elif field is not None :
[2862]156            newfield = self.database.string_literal(field)
157            try :
158                return newfield.encode("UTF-8")
[2863]159            except :   
[2862]160                return newfield
[2639]161        else :
[2644]162            self.tool.logdebug("WARNING: field has no type, returning NULL")
[2639]163            return "NULL"
164
165    def prepareRawResult(self, result) :
166        """Prepares a raw result by including the headers."""
167        if result :
168            entries = [tuple([f[0] for f in self.cursor.description])]
[2644]169            for entry in result :
[2639]170                row = []
171                for value in entry :
172                    try :
173                        value = value.encode("UTF-8")
174                    except :
175                        pass
176                    row.append(value)
177                entries.append(tuple(row))
178            return entries
Note: See TracBrowser for help on using the browser.