mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-16 03:50:43 +08:00
Some errorhandler cleanups
This commit is contained in:
@ -1,3 +1,7 @@
|
|||||||
|
0.9.2c2
|
||||||
|
|
||||||
|
* errorhandler cleanups (Rob Steele)
|
||||||
|
|
||||||
0.9.2c1
|
0.9.2c1
|
||||||
|
|
||||||
* If using Python 2.2 or newer, the _mysql connection object is
|
* If using Python 2.2 or newer, the _mysql connection object is
|
||||||
|
@ -16,18 +16,20 @@ import types, _mysql
|
|||||||
def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
|
def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
If cursor is not None, errorvalue is appended to cursor.messages;
|
If cursor is not None, (errorclass, errorvalue) is appended to
|
||||||
otherwise it is appended to connection.messages. Then errorclass
|
cursor.messages; otherwise it is appended to
|
||||||
is raised with errorvalue as the value.
|
connection.messages. Then errorclass is raised with errorvalue as
|
||||||
|
the value.
|
||||||
|
|
||||||
You can override this with your own error handler by assigning it
|
You can override this with your own error handler by assigning it
|
||||||
to the instance.
|
to the instance.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
error = errorclass, errorvalue
|
||||||
if cursor:
|
if cursor:
|
||||||
cursor.messages.append(errorvalue)
|
cursor.messages.append(error)
|
||||||
else:
|
else:
|
||||||
connection.messages.append(errorvalue)
|
connection.messages.append(error)
|
||||||
raise errorclass, errorvalue
|
raise errorclass, errorvalue
|
||||||
|
|
||||||
|
|
||||||
@ -132,7 +134,8 @@ class Connection(ConnectionBase):
|
|||||||
if self._transactional:
|
if self._transactional:
|
||||||
self.query("ROLLBACK")
|
self.query("ROLLBACK")
|
||||||
else:
|
else:
|
||||||
raise NotSupportedError, "Not supported by server"
|
self.errorhandler(None,
|
||||||
|
NotSupportedError, "Not supported by server")
|
||||||
|
|
||||||
def cursor(self, cursorclass=None):
|
def cursor(self, cursorclass=None):
|
||||||
"""
|
"""
|
||||||
|
@ -17,7 +17,6 @@ if hasattr(exceptions, "StopIteration"):
|
|||||||
else:
|
else:
|
||||||
_EndOfData = exceptions.IndexError
|
_EndOfData = exceptions.IndexError
|
||||||
|
|
||||||
|
|
||||||
class BaseCursor:
|
class BaseCursor:
|
||||||
|
|
||||||
"""A base for Cursor classes. Useful attributes:
|
"""A base for Cursor classes. Useful attributes:
|
||||||
@ -40,24 +39,36 @@ class BaseCursor:
|
|||||||
self.lastrowid = None
|
self.lastrowid = None
|
||||||
self.messages = []
|
self.messages = []
|
||||||
self.errorhandler = connection.errorhandler
|
self.errorhandler = connection.errorhandler
|
||||||
|
self._result = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close the cursor. No further queries will be possible."""
|
"""Close the cursor. No further queries will be possible."""
|
||||||
|
if not self.connection: return
|
||||||
|
del self.messages[:]
|
||||||
|
self.nextset()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
self.errorhandler = None
|
self.errorhandler = None
|
||||||
|
self._result = None
|
||||||
|
|
||||||
def _check_executed(self):
|
def _check_executed(self):
|
||||||
if not self._executed:
|
if not self._executed:
|
||||||
self.errorhandler(self.connection, self,
|
self.errorhandler(self, ProgrammingError, "execute() first")
|
||||||
ProgrammingError, "execute() first")
|
|
||||||
|
|
||||||
def nextset(self):
|
def nextset(self):
|
||||||
"""Advance to the next result set. Returns None if there are
|
"""Advance to the next result set.
|
||||||
no more result sets. Note that MySQL does not support multiple
|
|
||||||
result sets at this time."""
|
Returns None if there are no more result sets.
|
||||||
|
|
||||||
|
Note that MySQL does not support multiple result sets at this
|
||||||
|
time.
|
||||||
|
|
||||||
|
"""
|
||||||
|
del self.messages[:]
|
||||||
|
if self._executed:
|
||||||
|
self.fetchall()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def setinputsizes(self, *args):
|
def setinputsizes(self, *args):
|
||||||
@ -68,24 +79,26 @@ class BaseCursor:
|
|||||||
|
|
||||||
def _get_db(self):
|
def _get_db(self):
|
||||||
if not self.connection:
|
if not self.connection:
|
||||||
self.errorhandler(self.connection, self,
|
self.errorhandler(self, ProgrammingError, "cursor closed")
|
||||||
ProgrammingError, "cursor closed")
|
|
||||||
return self.connection
|
return self.connection
|
||||||
|
|
||||||
def execute(self, query, args=None):
|
def execute(self, query, args=()):
|
||||||
|
|
||||||
"""Execute a query.
|
"""Execute a query.
|
||||||
|
|
||||||
query -- string, query to execute on server
|
query -- string, query to execute on server
|
||||||
args -- optional sequence or mapping, parameters to use with query.
|
args -- optional sequence or mapping, parameters to use with query.
|
||||||
returns long integer rows affected, if any"""
|
|
||||||
|
|
||||||
|
Note: If args is a sequence, then %s must be used as the
|
||||||
|
parameter placeholder in the query. If a mapping is used,
|
||||||
|
%(key)s must be used as the placeholder.
|
||||||
|
|
||||||
|
Returns long integer rows affected, if any
|
||||||
|
|
||||||
|
"""
|
||||||
from types import ListType, TupleType
|
from types import ListType, TupleType
|
||||||
if args is None:
|
from sys import exc_info
|
||||||
r = self._query(query)
|
del self.messages[:]
|
||||||
elif type(args) is ListType and type(args[0]) is TupleType:
|
|
||||||
r = self.executemany(query, args) # deprecated
|
|
||||||
else:
|
|
||||||
try:
|
try:
|
||||||
r = self._query(query % self.connection.literal(args))
|
r = self._query(query % self.connection.literal(args))
|
||||||
except TypeError, m:
|
except TypeError, m:
|
||||||
@ -93,7 +106,10 @@ class BaseCursor:
|
|||||||
"not all arguments converted"):
|
"not all arguments converted"):
|
||||||
self.errorhandler(self, ProgrammingError, m.args[0])
|
self.errorhandler(self, ProgrammingError, m.args[0])
|
||||||
else:
|
else:
|
||||||
raise
|
self.errorhandler(self, TypeError, m)
|
||||||
|
except:
|
||||||
|
e = exc_info()
|
||||||
|
self.errorhandler(self, e[0], e[1])
|
||||||
self._executed = query
|
self._executed = query
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@ -102,15 +118,22 @@ class BaseCursor:
|
|||||||
"""Execute a multi-row query.
|
"""Execute a multi-row query.
|
||||||
|
|
||||||
query -- string, query to execute on server
|
query -- string, query to execute on server
|
||||||
args -- sequence of sequences or mappings, parameters to use with
|
|
||||||
query. The query must contain the clause "values ( ... )".
|
|
||||||
The parenthetical portion will be repeated once for each
|
|
||||||
item in the sequence.
|
|
||||||
returns long integer rows affected, if any
|
|
||||||
|
|
||||||
This method performs multiple-row inserts and similar queries."""
|
args
|
||||||
|
|
||||||
|
Sequence of sequences or mappings, parameters to use with
|
||||||
|
query.
|
||||||
|
|
||||||
|
Returns long integer rows affected, if any.
|
||||||
|
|
||||||
|
This method improves performance on multiple-row INSERT and
|
||||||
|
REPLACE. Otherwise it is equivalent to looping over args with
|
||||||
|
execute().
|
||||||
|
|
||||||
|
"""
|
||||||
from string import join
|
from string import join
|
||||||
|
from sys import exc_info
|
||||||
|
del self.messages[:]
|
||||||
if not args: return
|
if not args: return
|
||||||
m = insert_values.search(query)
|
m = insert_values.search(query)
|
||||||
if not m:
|
if not m:
|
||||||
@ -127,10 +150,12 @@ class BaseCursor:
|
|||||||
except TypeError, msg:
|
except TypeError, msg:
|
||||||
if msg.args[0] in ("not enough arguments for format string",
|
if msg.args[0] in ("not enough arguments for format string",
|
||||||
"not all arguments converted"):
|
"not all arguments converted"):
|
||||||
self.errorhandler(self.connection, self,
|
self.errorhandler(self, ProgrammingError, msg.args[0])
|
||||||
ProgrammingError, msg.args[0])
|
|
||||||
else:
|
else:
|
||||||
raise
|
self.errorhandler(self, TypeError, msg)
|
||||||
|
except:
|
||||||
|
e = exc_info()
|
||||||
|
self.errorhandler(self, e[0], e[1])
|
||||||
r = self._query(join(q,',\n'))
|
r = self._query(join(q,',\n'))
|
||||||
self._executed = query
|
self._executed = query
|
||||||
return r
|
return r
|
||||||
@ -145,8 +170,6 @@ class BaseCursor:
|
|||||||
self.rownumber = 0
|
self.rownumber = 0
|
||||||
self.description = self._result and self._result.describe() or None
|
self.description = self._result and self._result.describe() or None
|
||||||
self.lastrowid = db.insert_id()
|
self.lastrowid = db.insert_id()
|
||||||
message = db.info()
|
|
||||||
if message: self.messages.append(message)
|
|
||||||
self._check_for_warnings()
|
self._check_for_warnings()
|
||||||
return self.rowcount
|
return self.rowcount
|
||||||
|
|
||||||
@ -159,7 +182,7 @@ class BaseCursor:
|
|||||||
DEPRECATED: Use messages attribute"""
|
DEPRECATED: Use messages attribute"""
|
||||||
self._check_executed()
|
self._check_executed()
|
||||||
if self.messages:
|
if self.messages:
|
||||||
return self.messages[0]
|
return self.messages[-1]
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@ -170,6 +193,8 @@ class BaseCursor:
|
|||||||
return self.lastrowid
|
return self.lastrowid
|
||||||
|
|
||||||
def _fetch_row(self, size=1):
|
def _fetch_row(self, size=1):
|
||||||
|
if not self._result:
|
||||||
|
return ()
|
||||||
return self._result.fetch_row(size, self._fetch_type)
|
return self._result.fetch_row(size, self._fetch_type)
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
@ -203,10 +228,12 @@ class CursorWarningMixIn:
|
|||||||
|
|
||||||
def _check_for_warnings(self):
|
def _check_for_warnings(self):
|
||||||
from string import atoi, split
|
from string import atoi, split
|
||||||
if self.messages:
|
info = self._get_db().info()
|
||||||
warnings = atoi(split(self.messages[0])[-1])
|
if info is None:
|
||||||
|
return
|
||||||
|
warnings = atoi(split(info)[-1])
|
||||||
if warnings:
|
if warnings:
|
||||||
raise Warning, self.messages[0]
|
raise Warning, info
|
||||||
|
|
||||||
|
|
||||||
class CursorStoreResultMixIn:
|
class CursorStoreResultMixIn:
|
||||||
@ -225,12 +252,13 @@ class CursorStoreResultMixIn:
|
|||||||
|
|
||||||
def _query(self, q):
|
def _query(self, q):
|
||||||
rowcount = self._BaseCursor__do_query(q)
|
rowcount = self._BaseCursor__do_query(q)
|
||||||
self._rows = self._result and self._fetch_row(0) or ()
|
self._rows = self._fetch_row(0)
|
||||||
del self._result
|
self._result = None
|
||||||
return rowcount
|
return rowcount
|
||||||
|
|
||||||
def fetchone(self):
|
def fetchone(self):
|
||||||
"""Fetches a single row from the cursor."""
|
"""Fetches a single row from the cursor. None indicates that
|
||||||
|
no more rows are available."""
|
||||||
self._check_executed()
|
self._check_executed()
|
||||||
if self.rownumber >= len(self._rows): return None
|
if self.rownumber >= len(self._rows): return None
|
||||||
result = self._rows[self.rownumber]
|
result = self._rows[self.rownumber]
|
||||||
@ -284,9 +312,10 @@ class CursorStoreResultMixIn:
|
|||||||
elif mode == 'absolute':
|
elif mode == 'absolute':
|
||||||
r = value
|
r = value
|
||||||
else:
|
else:
|
||||||
raise ProgrammingError, "unknown scroll mode %s" % `mode`
|
self.errorhandler(self, ProgrammingError,
|
||||||
|
"unknown scroll mode %s" % `mode`)
|
||||||
if r < 0 or r >= len(self._rows):
|
if r < 0 or r >= len(self._rows):
|
||||||
raise IndexError, "out of range"
|
self.errorhandler(self, IndexError, "out of range")
|
||||||
self.rownumber = r
|
self.rownumber = r
|
||||||
|
|
||||||
|
|
||||||
@ -300,6 +329,8 @@ class CursorUseResultMixIn:
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close the cursor. No further queries can be executed."""
|
"""Close the cursor. No further queries can be executed."""
|
||||||
|
del self.messages[:]
|
||||||
|
self.nextset()
|
||||||
self._result = None
|
self._result = None
|
||||||
BaseCursor.close(self)
|
BaseCursor.close(self)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user