123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- """
- This module implements connections for MySQLdb. Presently there is
- only one class: Connection. Others are unlikely. However, you might
- want to make your own subclasses. In most cases, you will probably
- override Connection.default_cursor with a non-standard Cursor class.
- """
- from MySQLdb import cursors
- from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \
- DatabaseError, OperationalError, IntegrityError, InternalError, \
- NotSupportedError, ProgrammingError
- import types, _mysql
- import re
- def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
- """
- If cursor is not None, (errorclass, errorvalue) is appended to
- cursor.messages; otherwise it is appended to
- connection.messages. Then errorclass is raised with errorvalue as
- the value.
- You can override this with your own error handler by assigning it
- to the instance.
- """
- error = errorclass, errorvalue
- if cursor:
- cursor.messages.append(error)
- else:
- connection.messages.append(error)
- del cursor
- del connection
- raise errorclass, errorvalue
- re_numeric_part = re.compile(r"^(\d+)")
- def numeric_part(s):
- """Returns the leading numeric part of a string.
- >>> numeric_part("20-alpha")
- 20
- >>> numeric_part("foo")
- >>> numeric_part("16b")
- 16
- """
- m = re_numeric_part.match(s)
- if m:
- return int(m.group(1))
- return None
- class Connection(_mysql.connection):
- """MySQL Database Connection Object"""
- default_cursor = cursors.Cursor
- def __init__(self, *args, **kwargs):
- """
- Create a connection to the database. It is strongly recommended
- that you only use keyword parameters. Consult the MySQL C API
- documentation for more information.
- host
- string, host to connect
- user
- string, user to connect as
- passwd
- string, password to use
- db
- string, database to use
- port
- integer, TCP/IP port to connect to
- unix_socket
- string, location of unix_socket to use
- conv
- conversion dictionary, see MySQLdb.converters
- connect_timeout
- number of seconds to wait before the connection attempt
- fails.
- compress
- if set, compression is enabled
- named_pipe
- if set, a named pipe is used to connect (Windows only)
- init_command
- command which is run once the connection is created
- read_default_file
- file from which default client values are read
- read_default_group
- configuration group to use from the default file
- cursorclass
- class object, used to create cursors (keyword only)
- use_unicode
- If True, text-like columns are returned as unicode objects
- using the connection's character set. Otherwise, text-like
- columns are returned as strings. columns are returned as
- normal strings. Unicode objects will always be encoded to
- the connection's character set regardless of this setting.
- charset
- If supplied, the connection character set will be changed
- to this character set (MySQL-4.1 and newer). This implies
- use_unicode=True.
- sql_mode
- If supplied, the session SQL mode will be changed to this
- setting (MySQL-4.1 and newer). For more details and legal
- values, see the MySQL documentation.
- client_flag
- integer, flags to use or 0
- (see MySQL docs or constants/CLIENTS.py)
- ssl
- dictionary or mapping, contains SSL connection parameters;
- see the MySQL documentation for more details
- (mysql_ssl_set()). If this is set, and the client does not
- support SSL, NotSupportedError will be raised.
- local_infile
- integer, non-zero enables LOAD LOCAL INFILE; zero disables
- autocommit
- If False (default), autocommit is disabled.
- If True, autocommit is enabled.
- If None, autocommit isn't set and server default is used.
- There are a number of undocumented, non-standard methods. See the
- documentation for the MySQL C API for some hints on what they do.
- """
- from MySQLdb.constants import CLIENT, FIELD_TYPE
- from MySQLdb.converters import conversions
- from weakref import proxy
- kwargs2 = kwargs.copy()
- if 'conv' in kwargs:
- conv = kwargs['conv']
- else:
- conv = conversions
- conv2 = {}
- for k, v in conv.items():
- if isinstance(k, int) and isinstance(v, list):
- conv2[k] = v[:]
- else:
- conv2[k] = v
- kwargs2['conv'] = conv2
- cursorclass = kwargs2.pop('cursorclass', self.default_cursor)
- charset = kwargs2.pop('charset', '')
- if charset:
- use_unicode = True
- else:
- use_unicode = False
- use_unicode = kwargs2.pop('use_unicode', use_unicode)
- sql_mode = kwargs2.pop('sql_mode', '')
- client_flag = kwargs.get('client_flag', 0)
- client_version = tuple([ numeric_part(n) for n in _mysql.get_client_info().split('.')[:2] ])
- if client_version >= (4, 1):
- client_flag |= CLIENT.MULTI_STATEMENTS
- if client_version >= (5, 0):
- client_flag |= CLIENT.MULTI_RESULTS
- kwargs2['client_flag'] = client_flag
- # PEP-249 requires autocommit to be initially off
- autocommit = kwargs2.pop('autocommit', False)
- super(Connection, self).__init__(*args, **kwargs2)
- self.cursorclass = cursorclass
- self.encoders = dict([ (k, v) for k, v in conv.items()
- if type(k) is not int ])
- self._server_version = tuple([ numeric_part(n) for n in self.get_server_info().split('.')[:2] ])
- db = proxy(self)
- def _get_string_literal():
- def string_literal(obj, dummy=None):
- return db.string_literal(obj)
- return string_literal
- def _get_unicode_literal():
- def unicode_literal(u, dummy=None):
- return db.literal(u.encode(unicode_literal.charset))
- return unicode_literal
- def _get_string_decoder():
- def string_decoder(s):
- return s.decode(string_decoder.charset)
- return string_decoder
- string_literal = _get_string_literal()
- self.unicode_literal = unicode_literal = _get_unicode_literal()
- self.string_decoder = string_decoder = _get_string_decoder()
- if not charset:
- charset = self.character_set_name()
- self.set_character_set(charset)
- if sql_mode:
- self.set_sql_mode(sql_mode)
- if use_unicode:
- self.converter[FIELD_TYPE.STRING].append((None, string_decoder))
- self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder))
- self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder))
- self.converter[FIELD_TYPE.BLOB].append((None, string_decoder))
- self.encoders[types.StringType] = string_literal
- self.encoders[types.UnicodeType] = unicode_literal
- self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
- if self._transactional:
- if autocommit is not None:
- self.autocommit(autocommit)
- self.messages = []
- def autocommit(self, on):
- on = bool(on)
- if self.get_autocommit() != on:
- _mysql.connection.autocommit(self, on)
- def cursor(self, cursorclass=None):
- """
- Create a cursor on which queries may be performed. The
- optional cursorclass parameter is used to create the
- Cursor. By default, self.cursorclass=cursors.Cursor is
- used.
- """
- return (cursorclass or self.cursorclass)(self)
- def __enter__(self):
- if self.get_autocommit():
- self.query("BEGIN")
- return self.cursor()
- def __exit__(self, exc, value, tb):
- if exc:
- self.rollback()
- else:
- self.commit()
- def literal(self, o):
- """
- 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
- converted and returned as a sequence.
- Non-standard. For internal use; do not use this in your
- applications.
- """
- return self.escape(o, self.encoders)
- def begin(self):
- """Explicitly begin a connection. Non-standard.
- DEPRECATED: Will be removed in 1.3.
- Use an SQL BEGIN statement instead."""
- from warnings import warn
- warn("begin() is non-standard and will be removed in 1.3",
- DeprecationWarning, 2)
- self.query("BEGIN")
- if not hasattr(_mysql.connection, 'warning_count'):
- def warning_count(self):
- """Return the number of warnings generated from the
- last query. This is derived from the info() method."""
- from string import atoi
- info = self.info()
- if info:
- return atoi(info.split()[-1])
- else:
- return 0
- def set_character_set(self, charset):
- """Set the connection character set to charset. The character
- set can only be changed in MySQL-4.1 and newer. If you try
- to change the character set from the current value in an
- older version, NotSupportedError will be raised."""
- if charset == "utf8mb4":
- py_charset = "utf8"
- else:
- py_charset = charset
- if self.character_set_name() != charset:
- try:
- super(Connection, self).set_character_set(charset)
- except AttributeError:
- if self._server_version < (4, 1):
- raise NotSupportedError("server is too old to set charset")
- self.query('SET NAMES %s' % charset)
- self.store_result()
- self.string_decoder.charset = py_charset
- self.unicode_literal.charset = py_charset
- def set_sql_mode(self, sql_mode):
- """Set the connection sql_mode. See MySQL documentation for
- legal values."""
- if self._server_version < (4, 1):
- raise NotSupportedError("server is too old to set sql_mode")
- self.query("SET SESSION sql_mode='%s'" % sql_mode)
- self.store_result()
- def show_warnings(self):
- """Return detailed information about warnings as a
- sequence of tuples of (Level, Code, Message). This
- is only supported in MySQL-4.1 and up. If your server
- is an earlier version, an empty sequence is returned."""
- if self._server_version < (4,1): return ()
- self.query("SHOW WARNINGS")
- r = self.store_result()
- warnings = r.fetch_row(0)
- return warnings
- Warning = Warning
- Error = Error
- InterfaceError = InterfaceError
- DatabaseError = DatabaseError
- DataError = DataError
- OperationalError = OperationalError
- IntegrityError = IntegrityError
- InternalError = InternalError
- ProgrammingError = ProgrammingError
- NotSupportedError = NotSupportedError
- errorhandler = defaulterrorhandler
|