mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-16 03:50:43 +08:00
faster surrogateescape
This commit is contained in:
@ -1,10 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
This module implements connections for MySQLdb. Presently there is
|
This module implements connections for MySQLdb. Presently there is
|
||||||
only one class: Connection. Others are unlikely. However, you might
|
only one class: Connection. Others are unlikely. However, you might
|
||||||
want to make your own subclasses. In most cases, you will probably
|
want to make your own subclasses. In most cases, you will probably
|
||||||
override Connection.default_cursor with a non-standard Cursor class.
|
override Connection.default_cursor with a non-standard Cursor class.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from MySQLdb import cursors
|
from MySQLdb import cursors
|
||||||
from MySQLdb.compat import unicode, PY2
|
from MySQLdb.compat import unicode, PY2
|
||||||
@ -15,6 +13,14 @@ import _mysql
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
# See http://bugs.python.org/issue24870
|
||||||
|
_surrogateescape_table = [chr(i) if i < 0x80 else chr(i + 0xdc00) for i in range(256)]
|
||||||
|
|
||||||
|
def _fast_surroundescape(s):
|
||||||
|
return s.decode('latin1').translate(_surrogateescape_table)
|
||||||
|
|
||||||
|
|
||||||
def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
|
def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
|
||||||
"""
|
"""
|
||||||
If cursor is not None, (errorclass, errorvalue) is appended to
|
If cursor is not None, (errorclass, errorvalue) is appended to
|
||||||
@ -34,7 +40,7 @@ def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
|
|||||||
del connection
|
del connection
|
||||||
if isinstance(errorvalue, BaseException):
|
if isinstance(errorvalue, BaseException):
|
||||||
raise errorvalue
|
raise errorvalue
|
||||||
if errorclass is not None:
|
if errorclass is not None:
|
||||||
raise errorclass(errorvalue)
|
raise errorclass(errorvalue)
|
||||||
else:
|
else:
|
||||||
raise Exception(errorvalue)
|
raise Exception(errorvalue)
|
||||||
@ -291,24 +297,21 @@ class Connection(_mysql.connection):
|
|||||||
self.commit()
|
self.commit()
|
||||||
|
|
||||||
def literal(self, o):
|
def literal(self, o):
|
||||||
"""
|
"""If o is a single object, returns an SQL literal as a string.
|
||||||
|
|
||||||
If o is a single object, returns an SQL literal as a string.
|
|
||||||
If o is a non-string sequence, the items of the sequence are
|
If o is a non-string sequence, the items of the sequence are
|
||||||
converted and returned as a sequence.
|
converted and returned as a sequence.
|
||||||
|
|
||||||
Non-standard. For internal use; do not use this in your
|
Non-standard. For internal use; do not use this in your
|
||||||
applications.
|
applications.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
s = self.escape(o, self.encoders)
|
s = self.escape(o, self.encoders)
|
||||||
# Python 3 doesn't support % operation for bytes object.
|
# Python 3(~3.4) doesn't support % operation for bytes object.
|
||||||
# We should decode it before using %.
|
# We should decode it before using %.
|
||||||
# Decoding with ascii and surrogateescape allows convert arbitrary
|
# Decoding with ascii and surrogateescape allows convert arbitrary
|
||||||
# bytes to unicode and back again.
|
# bytes to unicode and back again.
|
||||||
# See http://python.org/dev/peps/pep-0383/
|
# See http://python.org/dev/peps/pep-0383/
|
||||||
if not PY2 and isinstance(s, bytes):
|
if not PY2 and isinstance(s, (bytes, bytearray)):
|
||||||
return s.decode('ascii', 'surrogateescape')
|
return _fast_surroundescape(s)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def begin(self):
|
def begin(self):
|
||||||
|
@ -187,7 +187,7 @@ class BaseCursor(object):
|
|||||||
parameter placeholder in the query. If a mapping is used,
|
parameter placeholder in the query. If a mapping is used,
|
||||||
%(key)s must be used as the placeholder.
|
%(key)s must be used as the placeholder.
|
||||||
|
|
||||||
Returns long integer rows affected, if any
|
Returns integer represents rows affected, if any
|
||||||
"""
|
"""
|
||||||
while self.nextset():
|
while self.nextset():
|
||||||
pass
|
pass
|
||||||
@ -208,9 +208,12 @@ class BaseCursor(object):
|
|||||||
args = dict((key, db.literal(item)) for key, item in args.items())
|
args = dict((key, db.literal(item)) for key, item in args.items())
|
||||||
else:
|
else:
|
||||||
args = tuple(map(db.literal, args))
|
args = tuple(map(db.literal, args))
|
||||||
if not PY2 and isinstance(query, bytes):
|
if not PY2 and isinstance(query, (bytes, bytearray)):
|
||||||
query = query.decode(db.unicode_literal.charset)
|
query = query.decode(db.unicode_literal.charset)
|
||||||
query = query % args
|
try:
|
||||||
|
query = query % args
|
||||||
|
except TypeError as m:
|
||||||
|
self.errorhandler(self, ProgrammingError, str(m))
|
||||||
|
|
||||||
if isinstance(query, unicode):
|
if isinstance(query, unicode):
|
||||||
query = query.encode(db.unicode_literal.charset, 'surrogateescape')
|
query = query.encode(db.unicode_literal.charset, 'surrogateescape')
|
||||||
@ -218,17 +221,12 @@ class BaseCursor(object):
|
|||||||
res = None
|
res = None
|
||||||
try:
|
try:
|
||||||
res = self._query(query)
|
res = self._query(query)
|
||||||
except TypeError as m:
|
|
||||||
if m.args[0] in ("not enough arguments for format string",
|
|
||||||
"not all arguments converted"):
|
|
||||||
self.errorhandler(self, ProgrammingError, m.args[0])
|
|
||||||
else:
|
|
||||||
self.errorhandler(self, TypeError, m)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exc, value = sys.exc_info()[:2]
|
exc, value = sys.exc_info()[:2]
|
||||||
self.errorhandler(self, exc, value)
|
self.errorhandler(self, exc, value)
|
||||||
self._executed = query
|
self._executed = query
|
||||||
if not self._defer_warnings: self._warning_check()
|
if not self._defer_warnings:
|
||||||
|
self._warning_check()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def executemany(self, query, args):
|
def executemany(self, query, args):
|
||||||
@ -369,13 +367,13 @@ class BaseCursor(object):
|
|||||||
|
|
||||||
|
|
||||||
class CursorStoreResultMixIn(object):
|
class CursorStoreResultMixIn(object):
|
||||||
|
|
||||||
"""This is a MixIn class which causes the entire result set to be
|
"""This is a MixIn class which causes the entire result set to be
|
||||||
stored on the client side, i.e. it uses mysql_store_result(). If the
|
stored on the client side, i.e. it uses mysql_store_result(). If the
|
||||||
result set can be very large, consider adding a LIMIT clause to your
|
result set can be very large, consider adding a LIMIT clause to your
|
||||||
query, or using CursorUseResultMixIn instead."""
|
query, or using CursorUseResultMixIn instead."""
|
||||||
|
|
||||||
def _get_result(self): return self._get_db().store_result()
|
def _get_result(self):
|
||||||
|
return self._get_db().store_result()
|
||||||
|
|
||||||
def _query(self, q):
|
def _query(self, q):
|
||||||
rowcount = self._do_query(q)
|
rowcount = self._do_query(q)
|
||||||
@ -390,9 +388,10 @@ class CursorStoreResultMixIn(object):
|
|||||||
"""Fetches a single row from the cursor. None indicates that
|
"""Fetches a single row from the cursor. None indicates that
|
||||||
no more rows are available."""
|
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]
|
||||||
self.rownumber = self.rownumber+1
|
self.rownumber = self.rownumber + 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def fetchmany(self, size=None):
|
def fetchmany(self, size=None):
|
||||||
|
Reference in New Issue
Block a user