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
Line 
1# -*- coding: UTF-8 -*-
2#
3# PyKota : Print Quotas for CUPS
4#
5# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
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
17# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18#
19# $Id$
20#
21#
22
23"""This module defines a class to access to a MySQL database backend."""
24
25import time
26
27from pykota.storage import PyKotaStorageError, BaseStorage
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 :   
45            port = 3306           # Use the default MySQL port
46       
47        self.tool.logdebug("Trying to open database (host=%s, port=%s, dbname=%s, user=%s)..." % (host, port, dbname, user))
48        try :
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 :
55            self.database.autocommit(1)
56        except AttributeError :   
57            raise PyKotaStorageError, _("Your version of python-mysqldb is too old. Please install a newer release.")
58        self.cursor = self.database.cursor()
59        self.cursor.execute("SET NAMES 'utf8';")
60        self.cursor.execute("SET TRANSACTION ISOLATION LEVEL READ COMMITTED;") # Same as PostgreSQL and Oracle's default
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 :
67            self.cursor.close()
68            self.database.close()
69            self.closed = 1
70            self.tool.logdebug("Database closed.")
71       
72    def beginTransaction(self) :   
73        """Starts a transaction."""
74        self.before = time.time()
75        self.cursor.execute("BEGIN;")
76        self.tool.logdebug("Transaction begins...")
77       
78    def commitTransaction(self) :   
79        """Commits a transaction."""
80        self.database.commit()
81        after = time.time()
82        self.tool.logdebug("Transaction committed.")
83        #self.tool.logdebug("Transaction duration : %.4f seconds" % (after - self.before))
84       
85    def rollbackTransaction(self) :     
86        """Rollbacks a transaction."""
87        self.database.rollback()
88        after = time.time()
89        self.tool.logdebug("Transaction aborted.")
90        #self.tool.logdebug("Transaction duration : %.4f seconds" % (after - self.before))
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 :
98            before = time.time()
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 :   
104            # This returns a list of lists. Integers are returned as longs.
105            result = self.cursor.fetchall()
106            after = time.time()
107            #self.tool.logdebug("Query Duration : %.4f seconds" % (after - before))
108            return result
109           
110    def doSearch(self, query) :       
111        """Does a search query."""
112        result = self.doRawSearch(query)
113        if result :
114            rows = []
115            fields = {}
116            for i in range(len(self.cursor.description)) :
117                fields[i] = self.cursor.description[i][0]
118            for row in result :
119                rowdict = {}
120                for field in fields.keys() :
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
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 :
137            before = time.time()
138            self.tool.logdebug("QUERY : %s" % query)
139            self.cursor.execute(query)
140        except self.database.Error, msg :   
141            self.tool.logdebug("Query failed : %s" % repr(msg))
142            raise PyKotaStorageError, str(msg)
143        else :   
144            after = time.time()
145            #self.tool.logdebug("Query Duration : %.4f seconds" % (after - before))
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 :
156            newfield = self.database.string_literal(field)
157            try :
158                return newfield.encode("UTF-8")
159            except :   
160                return newfield
161        else :
162            self.tool.logdebug("WARNING: field has no type, returning NULL")
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])]
169            for entry in result :
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.