mysql-connector-python-1.1.6/0000755001577100000120000000000012276514327015452 5ustar pb2userwheelmysql-connector-python-1.1.6/unittests.py0000644001577100000120000006066712276514013020075 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Script for running unittests unittests.py launches all or selected unit tests. For more information and options, simply do: shell> python unittests.py --help The unittest.py script will check for tests in Python source files prefixed with 'test_' in the folder tests/. Tests and other data specific to a Python major version are stored in tests/py2 and tests/py3. Examples: Running unit tests using MySQL installed under /opt shell> python unittests.py --with-mysql=/opt/mysql/mysql-5.7 Executing unit tests for cursor module shell> python unittests.py -t cursor Keep the MySQL server(s) running; speeds up multiple runs: shell> python unittests.py --keep Force shutting down of still running MySQL servers, and bootstrap again: shell> python unittests.py --force Show a more verbose and comprehensive output of tests (see --help to safe information to a database): shell> python unittests.py --keep --stats Run tests using IPv6: shell> python unittests.py --ipv6 unittests.py has exit status 0 when tests were ran successfully, 1 otherwise. """ import sys import os import time import unittest import logging try: from argparse import ArgumentParser except: # Python v2.6 from optparse import OptionParser try: from unittest import TextTestResult except ImportError: # Compatibility with Python v2.6 from unittest import _TextTestResult as TextTestResult if ((sys.version_info >= (2, 6) and sys.version_info < (3, 0)) or sys.version_info >= (3, 1)): sys.path.insert(0, 'python{0}/'.format(sys.version_info[0])) else: raise RuntimeError("Python v%d.%d is not supported" % sys.version_info[0:2]) import mysql.connector import tests from tests import mysqld LOGGER = logging.getLogger(tests.LOGGER_NAME) # MySQL option file template. Platform specifics dynamically added later. MY_CNF = """ # MySQL option file for MySQL Connector/Python tests [mysqld-5.6] innodb_compression_level = 0 innodb_compression_failure_threshold_pct = 0 lc_messages_dir = {lc_messages_dir} lc_messages = en_US [mysqld-5.5] lc_messages_dir = {lc_messages_dir} lc_messages = en_US [mysqld-5.1] language = {lc_messages_dir} [mysqld-5.0] language = {lc_messages_dir} [mysqld] basedir = {basedir} datadir = {datadir} tmpdir = {tmpdir} port = {port} socket = {unix_socket} bind_address = {bind_address} pid-file = {pid_file} skip_name_resolve server_id = {serverid} sql_mode = "" default_time_zone = +00:00 log-error = mysqld_{name}.err log-bin = mysqld_{name}_bin general_log = ON local_infile = 1 innodb_flush_log_at_trx_commit = 2 ssl """ # Platform specifics if os.name == 'nt': MY_CNF += '\n'.join(( "ssl-ca = {ssl_dir}\\\\tests_CA_cert.pem", "ssl-cert = {ssl_dir}\\\\tests_server_cert.pem", "ssl-key = {ssl_dir}\\\\tests_server_key.pem", )) MYSQL_DEFAULT_BASE = os.path.join( "C:/", "Program Files", "MySQL", "MySQL Server 5.6") else: MY_CNF += '\n'.join(( "ssl-ca = {ssl_dir}/tests_CA_cert.pem", "ssl-cert = {ssl_dir}/tests_server_cert.pem", "ssl-key = {ssl_dir}/tests_server_key.pem", "innodb_flush_method = O_DIRECT", )) MYSQL_DEFAULT_BASE = os.path.join('/', 'usr', 'local', 'mysql') MYSQL_DEFAULT_TOPDIR = os.path.dirname(os.path.realpath(__file__)) _UNITTESTS_CMD_ARGS = { ('-T', '--one-test'): { 'dest': 'onetest', 'metavar': 'NAME', 'help': ( 'Particular test to execute, format: ' '[.[.]]. For example, to run a particular ' 'test BugOra13392739.test_reconnect() from the tests.test_bugs ' 'module, use following value for the -T option: ' ' tests.test_bugs.BugOra13392739.test_reconnect') }, ('-t', '--test'): { 'dest': 'testcase', 'metavar': 'NAME', 'help': 'Tests to execute, one of {names}'.format( names=tests.get_test_names()) }, ('-l', '--log'): { 'dest': 'logfile', 'metavar': 'NAME', 'default': None, 'help': 'Log file location (if not given, logging is disabled)' }, ('', '--force'): { 'dest': 'force', 'action': 'store_true', 'default': False, 'help': 'Remove previous MySQL test installation.' }, ('', '--keep'): { 'dest': 'keep', 'action': "store_true", 'default': False, 'help': 'Keep MySQL installation (i.e. for debugging)' }, ('', '--debug'): { 'dest': 'debug', 'action': 'store_true', 'default': False, 'help': 'Show/Log debugging messages' }, ('', '--verbosity'): { 'dest': 'verbosity', 'metavar': 'NUMBER', 'default': 0, 'type': int, 'help': 'Verbosity of unittests (default 0)', 'type_optparse': 'int' }, ('', '--stats'): { 'dest': 'stats', 'default': False, 'action': 'store_true', 'help': "Show timings of each individual test." }, ('', '--stats-host'): { 'dest': 'stats_host', 'default': None, 'metavar': 'NAME', 'help': ( "MySQL server for saving unittest statistics. Specify this option " "to start saving results to a database. Implies --stats.") }, ('', '--stats-port'): { 'dest': 'stats_port', 'default': 3306, 'metavar': 'PORT', 'help': ( "TCP/IP port of the MySQL server for saving unittest statistics. " "Implies --stats. (default 3306)") }, ('', '--stats-user'): { 'dest': 'stats_user', 'default': 'root', 'metavar': 'NAME', 'help': ( "User for connecting with the MySQL server for saving unittest " "statistics. Implies --stats. (default root)") }, ('', '--stats-password'): { 'dest': 'stats_password', 'default': '', 'metavar': 'PASSWORD', 'help': ( "Password for connecting with the MySQL server for saving unittest " "statistics. Implies --stats. (default to no password)") }, ('', '--stats-db'): { 'dest': 'stats_db', 'default': 'test', 'metavar': 'NAME', 'help': ( "Database name for saving unittest statistics. " "Implies --stats. (default test)") }, ('', '--with-mysql'): { 'dest': 'mysql_basedir', 'metavar': 'NAME', 'default': MYSQL_DEFAULT_BASE, 'help': ( "Installation folder of the MySQL server. " "(default {default})").format(default=MYSQL_DEFAULT_BASE) }, ('', '--mysql-topdir'): { 'dest': 'mysql_topdir', 'metavar': 'NAME', 'default': MYSQL_DEFAULT_TOPDIR, 'help': ( "Where to bootstrap the new MySQL instances for testing. " "(default {default})").format(default=MYSQL_DEFAULT_TOPDIR) }, ('', '--bind-address'): { 'dest': 'bind_address', 'metavar': 'NAME', 'default': '127.0.0.1', 'help': 'IP address to bind to' }, ('-H', '--host'): { 'dest': 'host', 'metavar': 'NAME', 'default': '127.0.0.1', 'help': 'Hostname or IP address for TCP/IP connections.' }, ('-P', '--port'): { 'dest': 'port', 'metavar': 'NUMBER', 'default': 33770, 'type': int, 'help': 'First TCP/IP port to use.', 'type_optparse': int, }, ('', '--unix-socket'): { 'dest': 'unix_socket_folder', 'metavar': 'NAME', 'help': 'Folder where UNIX Sockets will be created' }, ('', '--ipv6'): { 'dest': 'ipv6', 'action': 'store_true', 'default': False, 'help': ( 'Use IPv6 to run tests. This sets --bind-address=:: --host=::1.' ), }, } def _get_arg_parser(): """Parse comand line ArgumentParser This function parses the command line arguments and returns the parser. It works with both optparse and argparse where available. """ def _clean_optparse(adict): """Remove items from dictionary ending with _optparse""" new = {} for key in adict.keys(): if not key.endswith('_optparse'): new[key] = adict[key] return new new = True try: parser = ArgumentParser() add = parser.add_argument except NameError: # Fallback to old optparse new = False parser = OptionParser() add = parser.add_option for flags, params in _UNITTESTS_CMD_ARGS.items(): if new: flags = [i for i in flags if i] add(*flags, **_clean_optparse(params)) return parser def _show_help(msg=None, parser=None, exit_code=0): """Show the help of the given parser and exits If exit_code is -1, this function will not call sys.exit(). """ tests.printmsg(msg) if parser is not None: parser.print_help() if exit_code > -1: sys.exit(exit_code) def get_stats_tablename(): return "myconnpy_{version}".format( version='_'.join( [str(i) for i in mysql.connector.__version_info__[0:3]] ) ) def get_stats_field(pyver=None, myver=None): if not pyver: pyver = '.'.join([str(i) for i in sys.version_info[0:2]]) if not myver: myver = '.'.join([str(i) for i in tests.MYSQL_SERVERS[0].version[0:2]]) return "py{python}my{mysql}".format( python=pyver.replace('.', ''), mysql=myver.replace('.', '')) class StatsTestResult(TextTestResult): """Store test results in a database""" separator1 = '=' * 78 separator2 = '-' * 78 def __init__(self, stream, descriptions, verbosity, dbcnx=None): super(StatsTestResult, self).__init__(stream, descriptions, verbosity) self.stream = stream self.showAll = 0 self.dots = 0 self.descriptions = descriptions self._start_time = None self._stop_time = None self.elapsed_time = None self._dbcnx = dbcnx self._name = None def get_description(self, test): # pylint: disable=R0201 return "{0:.<60s} ".format(str(test)[0:58]) def startTest(self, test): super(StatsTestResult, self).startTest(test) self.stream.write(self.get_description(test)) self.stream.flush() self._start_time = time.time() def addSuccess(self, test): super(StatsTestResult, self).addSuccess(test) self._stop_time = time.time() self.elapsed_time = self._stop_time - self._start_time fmt = "{timing:>8.3f}s {state:<20s}" self.stream.writeln(fmt.format(state="ok", timing=self.elapsed_time)) if self._dbcnx: cur = self._dbcnx.cursor() stmt = ( "INSERT INTO {table} (test_case, {field}) " "VALUES (%s, %s) ON DUPLICATE KEY UPDATE {field} = %s" ).format(table=get_stats_tablename(), field=get_stats_field()) cur.execute(stmt, (str(test), self.elapsed_time, self.elapsed_time) ) cur.close() def _save_not_ok(self, test): cur = self._dbcnx.cursor() stmt = ( "INSERT INTO {table} (test_case, {field}) " "VALUES (%s, %s) ON DUPLICATE KEY UPDATE {field} = %s" ).format(table=get_stats_tablename(), field=get_stats_field()) cur.execute(stmt, (str(test), -1, -1)) cur.close() def addError(self, test, err): super(StatsTestResult, self).addError(test, err) self.stream.writeln("ERROR") if self._dbcnx: self._save_not_ok(test) def addFailure(self, test, err): super(StatsTestResult, self).addFailure(test, err) self.stream.writeln("FAIL") if self._dbcnx: self._save_not_ok(test) def addSkip(self, test, reason): try: super(StatsTestResult, self).addSkip(test, reason) except AttributeError: # We are using Python v2.6/v3.1 pass self.stream.writeln("skipped") if self._dbcnx: self._save_not_ok(test) def addExpectedFailure(self, test, err): super(StatsTestResult, self).addExpectedFailure(test, err) self.stream.writeln("expected failure") if self._dbcnx: self._save_not_ok(test) def addUnexpectedSuccess(self, test): super(StatsTestResult, self).addUnexpectedSuccess(test) self.stream.writeln("unexpected success") if self._dbcnx: self._save_not_ok(test) class StatsTestRunner(unittest.TextTestRunner): """Committing results test results""" resultclass = StatsTestResult def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, dbcnx=None): try: super(StatsTestRunner, self).__init__( stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False) except TypeError: # Compatibility with Python v2.6 super(StatsTestRunner, self).__init__( stream=sys.stderr, descriptions=True, verbosity=1) self._dbcnx = dbcnx def _makeResult(self): return self.resultclass(self.stream, self.descriptions, self.verbosity, dbcnx=self._dbcnx) def run(self, test): result = super(StatsTestRunner, self).run(test) if self._dbcnx: self._dbcnx.commit() return result class BasicTestResult(TextTestResult): """Basic test result""" def addSkip(self, test, reason): """Save skipped reasons""" tests.MESSAGES['SKIPPED'].append(reason) class BasicTestRunner(unittest.TextTestRunner): """Basic test runner""" resultclass = BasicTestResult def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False): try: super(BasicTestRunner, self).__init__( stream=stream, descriptions=descriptions, verbosity=verbosity, failfast=failfast, buffer=buffer) except TypeError: # Python v3.1 super(BasicTestRunner, self).__init__( stream=stream, descriptions=descriptions, verbosity=verbosity) class Python26TestRunner(unittest.TextTestRunner): """Python v2.6/3.1 Test Runner backporting needed functionality""" def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False): super(Python26TestRunner, self).__init__( stream=stream, descriptions=descriptions, verbosity=verbosity) def _makeResult(self): return BasicTestResult(self.stream, self.descriptions, self.verbosity) def setup_stats_db(cnx): """Setup the database for storing statistics""" cur = cnx.cursor() supported_python = ('2.6', '2.7', '3.1', '3.2', '3.3', '3.4') supported_mysql = ('5.1', '5.5', '5.6', '5.7') columns = [] for pyver in supported_python: for myver in supported_mysql: columns.append( " py{python}my{mysql} DECIMAL(8,4) DEFAULT -1".format( python=pyver.replace('.', ''), mysql=myver.replace('.', '')) ) create_table = ( "CREATE TABLE {table} ( " " test_case VARCHAR(100) NOT NULL," " {pymycols}, " " PRIMARY KEY (test_case)" ") ENGINE=InnoDB" ).format(table=get_stats_tablename(), pymycols=', '.join(columns)) try: cur.execute(create_table) except mysql.connector.ProgrammingError as err: if err.errno != 1050: raise LOGGER.info("Using exists table '{0}' for saving statistics".format( get_stats_tablename())) else: LOGGER.info("Created table '{0}' for saving statistics".format( get_stats_tablename())) cur.close() def init_mysql_server(port, options): """Initialize a MySQL Server""" name = 'server{0}'.format(len(tests.MYSQL_SERVERS) + 1) try: mysql_server = mysqld.MySQLServer( basedir=options.mysql_basedir, topdir=os.path.join(options.mysql_topdir, 'cpy_' + name), cnf=MY_CNF, bind_address=options.bind_address, port=port, unix_socket_folder=options.unix_socket_folder, ssl_folder=os.path.abspath(tests.SSL_DIR), name=name) except tests.mysqld.MySQLBootstrapError as err: LOGGER.error("Failed initializing MySQL server " "'{name}': {error} (use --with-mysql?)".format( name=name, error=str(err))) sys.exit(1) mysql_server._debug = options.debug have_to_bootstrap = True if options.force: # Force removal of previous test data if mysql_server.check_running(): mysql_server.stop() if not mysql_server.wait_down(): LOGGER.error( "Failed shutting down the MySQL server '{name}'".format( name=name)) sys.exit(1) mysql_server.remove() else: if mysql_server.check_running(): LOGGER.info( "Reusing previously bootstrapped MySQL server '{name}'".format( name=name)) have_to_bootstrap = False else: LOGGER.warning( "Can not connect to previously bootstrapped " "MySQL Server '{name}'; forcing bootstrapping".format( name=name)) mysql_server.remove() tests.MYSQL_VERSION = mysql_server.version tests.MYSQL_SERVERS.append(mysql_server) mysql_server.client_config = { 'host': options.host, 'port': port, 'unix_socket': mysql_server._unix_socket, 'user': 'root', 'password': '', 'database': 'myconnpy', 'connection_timeout': 5, } # Bootstrap and start a MySQL server if have_to_bootstrap: LOGGER.info("Bootstrapping MySQL server '{name}'".format(name=name)) try: mysql_server.bootstrap() except tests.mysqld.MySQLBootstrapError: LOGGER.error("Failed bootstrapping MySQL server '{name}'".format( name=name)) sys.exit(1) mysql_server.start() if not mysql_server.wait_up(): LOGGER.error("Failed to start the MySQL server '{name}'. " "Check error log.".format(name=name)) sys.exit(1) def setup_logger(logger, debug=False, logfile=None): """Setting up the logger""" formatter = logging.Formatter( "%(asctime)s [%(name)s:%(levelname)s] %(message)s") handler = None if logfile: handler = logging.FileHandler(logfile) else: handler = logging.StreamHandler() handler.setFormatter(formatter) if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) LOGGER.addHandler(handler) def main(): parser = _get_arg_parser() options = parser.parse_args() if isinstance(options, tuple): # Fallback to old optparse options = options[0] setup_logger(LOGGER, debug=options.debug, logfile=options.logfile) LOGGER.info( "MySQL Connector/Python unittest " "started using Python v{0}".format( '.'.join([str(v) for v in sys.version_info[0:3]]))) # Check if we can test IPv6 if options.ipv6: if not tests.IPV6_AVAILABLE: LOGGER.error("Can not test IPv6: not available on your system") sys.exit(1) options.bind_address = '::' options.host = '::1' LOGGER.info("Testing using IPv6. Binding to :: and using host ::1") else: tests.IPV6_AVAILABLE = False # Which tests cases to run if options.testcase: if options.testcase in tests.get_test_names(): for module in tests.get_test_modules(): if module.endswith('test_' + options.testcase): testcases = [module] break testsuite = unittest.TestLoader().loadTestsFromNames(testcases) else: msg = "Test case is not one of {0}".format( ', '.join(tests.get_test_names())) _show_help(msg=msg, parser=parser, exit_code=1) elif options.onetest: testsuite = unittest.TestLoader().loadTestsFromName(options.onetest) else: testcases = tests.get_test_modules() testsuite = unittest.TestLoader().loadTestsFromNames(testcases) # Initialize the MySQL Servers for i in range(0, tests.MYSQL_SERVERS_NEEDED): init_mysql_server(port=(options.port + i), options=options) LOGGER.info( "Using MySQL server version {0}".format( '.'.join([str(v) for v in tests.MYSQL_VERSION[0:3]]))) LOGGER.info("Starting unit tests") was_successful = False try: # Run test cases if options.stats: if options.stats_host: stats_db_info = { 'host': options.stats_host, 'port': options.stats_port, 'user': options.stats_user, 'password': options.stats_password, 'database': options.stats_db, } cnxstats = mysql.connector.connect(**stats_db_info) setup_stats_db(cnxstats) else: cnxstats = None result = StatsTestRunner( verbosity=options.verbosity, dbcnx=cnxstats).run( testsuite) elif sys.version_info[0:2] == (2, 6): result = Python26TestRunner(verbosity=options.verbosity).run( testsuite) else: result = BasicTestRunner(verbosity=options.verbosity).run( testsuite) was_successful = result.wasSuccessful() except KeyboardInterrupt: LOGGER.info("Unittesting was interrupted") was_successful = False # Log messages added by test cases for msg in tests.MESSAGES['WARNINGS']: LOGGER.warning(msg) for msg in tests.MESSAGES['INFO']: LOGGER.info(msg) # Show skipped tests if len(tests.MESSAGES['SKIPPED']): LOGGER.info( "Skipped tests: {0}".format( len(tests.MESSAGES['SKIPPED']))) if options.verbosity >= 1 or options.debug: for msg in tests.MESSAGES['SKIPPED']: LOGGER.info(msg) # Clean up for mysql_server in tests.MYSQL_SERVERS: name = mysql_server.name if not options.keep: mysql_server.stop() if not mysql_server.wait_down(): LOGGER.error("Failed stopping MySQL server '{name}'".format( name=name)) else: mysql_server.remove() LOGGER.info( "MySQL server '{name}' stopped and cleaned up".format( name=name)) elif not mysql_server.check_running(): mysql_server.start() if not mysql_server.wait_up(): LOGGER.error("MySQL could not be kept running; " "failed to restart") else: LOGGER.info("MySQL server kept running on {addr}:{port}".format( addr=mysql_server.bind_address, port=mysql_server.port) ) txt = "" if not was_successful: txt = "not " LOGGER.info( "MySQL Connector/Python unittests were {result}successful".format( result=txt)) # Return result of tests as exit code sys.exit(not was_successful) if __name__ == '__main__': main() mysql-connector-python-1.1.6/ChangeLog0000644001577100000120000000761212276514013017222 0ustar pb2userwheelMySQL Connector/Python - Release Notes / ChangeLog Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. Full release notes: http://dev.mysql.com/doc/relnotes/connector-python/en/ 1.1.6 (2014-01-11) ------------------ * BUG#18187561: Fixed Django backend errors with time functions 1.1.5 (2014-01-31) ------------------ * BUG#17857712: Added fixes to use CPY with Django 1.6 * BUG#18040042: Fixed clearing session with pooled connection * BUG#17826833: Fixed executemany for INSERT with no VALUES-clause * BUG#17573172: Added support for access modes for START TRANSACTION * BUG#18054810: Fixed output of pylint to include msg_id * BUG#17889076: Fixed error handling for unittests.py using -t option * BUG#17780576: Added support for utf8mb4 character set * BUG#17958420: Fix error handling parse_column_count() 1.1.4 (2013-12-11) ------------------ * BUG#17890173: Improve performance reading results * BUG#17589172: Fixed GPL to/from community RPM upgrades * BUG#17035093: Removed extra empty feature in MSI * BUG#17888821: Updated MSI upgrade codes * BUG#17943078: Adding support for building OS X packages 1.1.3b1 (2013-11-15) -------------------- * WL#7298: Refactored unittesting * WL#7230: Added unit tests performing code analysis * BUG#17079344: Fixed saving multi-byte strings with \x5c * BUG#17578937: Fixed reconnecting of pooled connections * BUG#17620395: Fixed packaging on older Debian systems * BUG#17372107: Fixed TCP/IP connection for older FreeBSD 1.1.2a1 (2013-01-15) -------------------- * BUG#17547529: pid option changed to pid-file * BUG#17414258: Added check to disallow changing size of pool * BUG#17422299: Fixed cmd_shutdown() for MySQL 5.6 * BUG#17406263: Fixed error message when pool is exhausted * BUG#17461777: Fixed reconnect() to stop once it succeeds * BUG#17215197: Added prepared argument for MySQLConnection.cursor() * BUG#17424009: Fixed RuntimeError on exit using Python v3 * BUG#17406398: Adding constraints on the pool name * BUG#17401406: Adding constraints on pool size * BUG#17353327: Fixed commercial MSI upgrade error * BUG#17485966: Removed alpha/beta tags from distributions * BUG#17473273: Fixed last_executed_query() for Django * BUG#13551483: Added converter_class connection argument * BUG#13369592: Added compress connection argument * BUG#17353301: Fixed MSI to remove previous installations * BUG#14273043: Fix warnings.py example 1.1.1a1 (2013-08-28) -------------------- * WL#6499: Adding database backend for Django * WL#6080: Added Connection Pooling * WL#7080: Added Distutils command to create Debian packages * BUG#17022399: Fixed error message executing while disconnected * BUG#16933795: Fixed errors.Error to retain the given message * BUG#17065366: Fixed executemany using MySQL functions as values * BUG#17041240: Fixed error closing cursor with unread results * BUG#17041412: Fixed fetchall() to include self._nextrow * BUG#17002411: Fixed loading data using LOAD DATA LOCAL INFILE * BUG#16234441: Fixed shutdown using different shutdown types * BUG#16660356: Fixed executemany() to do nothing given nothing * BUG#16655208: Fixed Unicode database names with Python v2 * BUG#17028999: Added timing for individual unittests * BUG#16656621: Fixed rollback to consume unread results * BUG#17028999: Added timing for individual unittests * BUG#16662920: Fixed fetching remaining rows in buffered cursors * BUG#16736916: Fixed FileNotFound with LOAD DATA INFILE * BUG#16972089: Fixed hyphen in version by removing it * BUG#16748411: Fixed catching errors of socket.getaddrinfo() 1.1.0a1 (2013-06-12) -------------------- * BUG#16896702: Updated errors using MySQL 5.7.1 * WL#6148: Added support for MySQL Prepared Statements * BUG#16234372: Fixed relative imports in Python v3 code * WL#6573: Added method to start transactions explicitly * WL#6517: Added more standard attributes for getting the version * WL#6574: Added the possibility to check for an ongoing transaction mysql-connector-python-1.1.6/README0000644001577100000120000000370512276514013016327 0ustar pb2userwheelMySQL Connector/Python 1.1 This is a release of MySQL Connector/Python, Oracle's dual- license Python Driver for MySQL. For the avoidance of doubt, this particular copy of the software is released under the version 2 of the GNU General Public License. MySQL Connector/Python is brought to you by Oracle. Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. License information can be found in the COPYING file. MySQL FOSS License Exception We want free and open source software applications under certain licenses to be able to use the GPL-licensed MySQL Connector/Python (specified GPL-licensed MySQL client libraries) despite the fact that not all such FOSS licenses are compatible with version 2 of the GNU General Public License. Therefore there are special exceptions to the terms and conditions of the GPLv2 as applied to these client libraries, which are identified and described in more detail in the FOSS License Exception at This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. This distribution may include materials developed by third parties. For license and attribution notices for these materials, please refer to the documentation that accompanies this distribution (see the "Licenses for Third-Party Components" appendix) or view the online documentation at A copy of the license/notices is also reproduced below. GPLv2 Disclaimer For the avoidance of doubt, except that if any license choice other than GPL or LGPL is available it will apply instead, Oracle elects to use only the General Public License version 2 (GPLv2) at this time for any software where a choice of GPL license versions is made available with the language indicating that GPLv2 or any later version may be used, or where a choice of which version of the GPL is applied is otherwise unspecified. mysql-connector-python-1.1.6/tests/0000755001577100000120000000000012276514327016614 5ustar pb2userwheelmysql-connector-python-1.1.6/tests/data/0000755001577100000120000000000012276514327017525 5ustar pb2userwheelmysql-connector-python-1.1.6/tests/data/local_data.csv0000644001577100000120000000010712276514013022313 0ustar pb2userwheel1 c1_1 c2_1 2 c1_2 c2_2 3 c1_3 c2_3 4 c1_4 c2_4 5 c1_5 c2_5 6 c1_6 c2_6mysql-connector-python-1.1.6/tests/data/ssl/0000755001577100000120000000000012276514327020326 5ustar pb2userwheelmysql-connector-python-1.1.6/tests/data/ssl/tests_server_cert.pem0000644001577100000120000000207612276514013024573 0ustar pb2userwheel-----BEGIN CERTIFICATE----- MIIC9TCCAd0CAQEwDQYJKoZIhvcNAQEFBQAwQjElMCMGA1UECwwcTXlTUUxDb25u ZWN0b3JQeXRob24gUm9vdCBDQTEZMBcGA1UEAwwQTXlDb25uUHkgUm9vdCBDQTAe Fw0xMzAzMjYxNTM1NTJaFw0yMjA0MTQxNTM1NTJaMD8xKTAnBgNVBAsMIE15U1FM Q29ubmVjdG9yUHl0aG9uIFNlcnZlciBDZXJ0MRIwEAYDVQQDDAlsb2NhbGhvc3Qw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDv6WQ/Ssum4RchjXSlwbcB au3WNccfodThBOAM27AOnJQWIjG4e5s9H7lLznI+VF5MgUbgbp/yz4D+CrSFvLgU 4xxzd1/SVbnzRJ5iD2EmaZPjoMkBmvDRd4ow6IdFN80Fpwxij6fUBHdRkyXyiYsG FE94PQCyD1R47LSubd/gfcjXw8Bt5cWqcopiolZ01bYuMzeZIw0et9gf6Iih2Zh1 bs9RthHfL3BfN4knljF3XmRQhfsc4w3MvdulX4mcfzS+E+keOOgPjfjo9KVCD1Zl F00wQdbSCWzf9uCP4OpKJGURyMQEmGMFPBOP98kqns1CqaE0PxKOpbcTX86nSEO5 AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFy4ONx0zFYgVNL046lfRmimyRf1gbmB pyyug9eW6QuuTfqbzFWOYZY8pG2lzKnHNUMmgzMNMpiRLRJ38Dj5rApg+7OkiTT+ l4DMIR/YblJryEvx6tNUq2Cu9GXKW2qrGJO3XVniuBpmg1srugdwyxS+LdFofgBc I4cKIDuXYATUpOFhEsFbMY6tGVeOXQN2jSWtUj6+mKiUWMyr+5NYD8xhjDV7q4GH JfQqWFzw7prtSYzwB8lc0PM2SLwxeE9cQUYN/UkW8HRxM7Ft5KyyXUk+2Jg61sZ2 QxMCV6NAGYMX40WRDqIZbs9AbHWoCxEwoXWtcmNb0GInsk39lFMJqw4= -----END CERTIFICATE----- mysql-connector-python-1.1.6/tests/data/ssl/tests_client_key.pem0000644001577100000120000000321712276514013024374 0ustar pb2userwheel-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA12y+7K/5P1uC8MM0yiY+YtULXGS9LTMgYQMLiO10FciQVb2O 3UVDPht9AAznFMOQ7HGG5JFbty9jbbJ5rsgfKNGOW2x6U7+MU61X7ELg5DC3vvy8 BXy+162NQZtd8XRJ9+OW+nnX74a3u3mrQoCGhiCnxa+SQ7+aDeH2hhCaamGoRP1n cTO87+sW+1sfsqi5Xs5XVN+FXC3IIYvM3w5MWxW+HGUoJKP/UU+5U1BgSUkoCE56 t0XtKgDWoe1G6hZEzNsH5baFxnq21jGLszn0KOa9BYknI7rwApAwCxwHVG1+FG12 rAK6qRqL8lah6eDlrtxVkX3AlJ8QMX49xt8e/QIDAQABAoIBAQCjSd5+cfSvvaHG 9XAyOkLXjz0JT6LFfBdy8Wfw5mwzhs9A7mo39qQ9k4BwZVdTOdnEH1lsL3IhrF3l bH8nqLFVs2IAkn02td6cHqyifR8SWIsuzUuHrULLINYNgML4nnji2TQ7r9epy6fB Bzx1MA7H5EDHa4mmqLkRBNJkVHl3YCGM25tXyhixC5MsNdSpTwLMvv/RVLqsHtH6 WZ3P8VZi/iOk28TQwLcFTQz4g6RM3jO/1O9tXhob9g1iUoLNd3mLR3+sdkhHf5bU ttEzxvfVl4Fe0463J4I/JeofGtDBkWgR4UI5ZVfC0xLvmVA4J3cxgUeAKsIwuqQT 9Gi4MDOBAoGBAP6MGCwZUmVqoaqaNF/XckwieJctYLUxhf/KA9S3pq2Y4PPFb7FO srqn90c2Qb4o13iZzak9rPKUVKwcL+VYknrVGb1ALyWySI7WEaUzsXLIGF2w010l TNUyL82NynGUx3/4gxvJf/K9weVkTU7KK2tfdB+ridv1ZcSn9bETMvVJAoGBANin fdqLh8tFMqTsc+bMvlogzns9y+MluJeqz+On706sVR6XsEF8LtzcnHAwOYFef6h5 cgrKGzfWaz88tNdgB82p/smLQcz4ouFAzTBX3y/+LG/+ybbkR9a2sO+gHA1eAukB Ia5q/t5jI0XiTa4lVoj2IJK7/hBjIYYBLA2TKQAVAoGBAPP6k7CxFKjga9R5uXmj p4oSAEPm2qrRrP5fQwzAeqIpxnPg6g2owObn17wJ5Tm/K8gMo3N0CjD4u6+71Kyf GMdjOiiLPKWFHMbLqF4QDiVWZQRoWC8PcXVnhSogncoAMLgYGpKnsFuaRh745KCA Zt2jwEoawShzLfgwhO4U2OMBAoGAULfuctsjZ79LRBj4gZfsn6WzaEU4zlNCd/di 5t2tkjEwsWowd+VtjEoBWucMtb9gboN40r5D78TKRlA2zDtyDNT2IV7p0BUeki/T gtxqQfY/1iYmPybEASIlv9F2QiCxkuAiDVq9xFtJTAMpj+VHXVXeAu1Zlf9pAQU0 xYX7c5UCgYA8Iux1dO7bakTlqwFUQCMM5IlzJJVT90Z8JQOCFk6a7bzTdOkyxYg2 BxiGjiFhNer6UshTNZj2svdUvVh9yH/iRGEP6eQAZR1AXIr1YazNmaG7tjIEZ4Yw zx8gdGTIDYBDChFQmJIB9Y7iNF8bu8JmyVuo2SJHhIVyXN/cM9T6gg== -----END RSA PRIVATE KEY----- mysql-connector-python-1.1.6/tests/data/ssl/tests_CA_cert.pem0000644001577100000120000000230412276514013023542 0ustar pb2userwheel-----BEGIN CERTIFICATE----- MIIDVzCCAj+gAwIBAgIJAIUsZ/vX9kOGMA0GCSqGSIb3DQEBBQUAMEIxJTAjBgNV BAsMHE15U1FMQ29ubmVjdG9yUHl0aG9uIFJvb3QgQ0ExGTAXBgNVBAMMEE15Q29u blB5IFJvb3QgQ0EwHhcNMTMwMzI2MTUzNTUyWhcNMjIwNDE0MTUzNTUyWjBCMSUw IwYDVQQLDBxNeVNRTENvbm5lY3RvclB5dGhvbiBSb290IENBMRkwFwYDVQQDDBBN eUNvbm5QeSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA qWcX9kD+b8c3hkPtPlIgwTsfGvhm/bJ64RHjCtQc2pi/fv9hlcryor8tWmdCCcw7 ajg5n/QAIJ8crD5D0kheGEnWVI7dyVxZVfT3CiKuS+GBxuQP2ejJi4aDGh2McVv4 aq1dXRqf2YWkM8PUjM0lzUD9MC9S4APtP6ux0TBhz5rv2ZWdg2EAjAl7Q56KM5m6 odpF+Z1ExnfVpNzWnpvlYHJ+GhbVWb2F0NbqBTmz4OLEAxU/O2fo43dwVlHp+yNd ib2V+VxeeyZmTt1CIeK6DStAiKdNLN5/N/+2FHZ9/XcA6qqxLFLeuTIySlPmuaX6 u2C8tmOWp99TCUL+GZ2iBwIDAQABo1AwTjAdBgNVHQ4EFgQU1objOGh5rgtBTmjK gPkN6SgXl64wHwYDVR0jBBgwFoAU1objOGh5rgtBTmjKgPkN6SgXl64wDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAWgHZzUo8oGP7YxMn9YACdbipTRYU IzGF+Cf0ueXktcEDbq7AIa6MsxXTp8pFOObvLiiecrMngYlqfHlYPL2HG+zOLDig nmkO4pGwTqCDZHO4aYBdiVMlaxSpxMX9R/kFYRP1P4AGLOp66FirNO5iLNlTIjpf PGebF+k0B1zUSUPsrZfa/d29XcJxBaw7aEOhARQYsymItasnTdcKvjZp1ahGnZYz yCDtJjVbXK/4qEtiSA4qcV1HrNuHmhZEwWahntLqo++x3oLK7DrWfHwTX5gHMyv2 DGTggnNfB8uzzNe3giT0j6ie9DJEnvv1hB0GpUToUNECusrKsYnWLdJkIA== -----END CERTIFICATE----- mysql-connector-python-1.1.6/tests/data/ssl/tests_server_key.pem0000644001577100000120000000321712276514013024424 0ustar pb2userwheel-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA7+lkP0rLpuEXIY10pcG3AWrt1jXHH6HU4QTgDNuwDpyUFiIx uHubPR+5S85yPlReTIFG4G6f8s+A/gq0hby4FOMcc3df0lW580SeYg9hJmmT46DJ AZrw0XeKMOiHRTfNBacMYo+n1AR3UZMl8omLBhRPeD0Asg9UeOy0rm3f4H3I18PA beXFqnKKYqJWdNW2LjM3mSMNHrfYH+iIodmYdW7PUbYR3y9wXzeJJ5Yxd15kUIX7 HOMNzL3bpV+JnH80vhPpHjjoD4346PSlQg9WZRdNMEHW0gls3/bgj+DqSiRlEcjE BJhjBTwTj/fJKp7NQqmhND8SjqW3E1/Op0hDuQIDAQABAoIBAQCyfCuVntq2E532 21td+ilhh6DcDfRPh0FuCwd46XQo2rqdYOEmw+bxaYmcaUG7N19UgZUuYX7j0RbB aUt2d7ln6LMBAF2siRSndHR0tcZsIn3hCnygkhn5bHrF+iixCVuhie7/4KpWZOA0 M0o3D7b7Vd7tsEy1LAyHTmr5nkrBosIpLXQvnjj8kF6MOQW09/72l7eiFwnRQ3yW eUn8l+vkIRpYzI/l1MFnj1lcGeDKRDFJMXZV7OropJaQabWuGyaddizP8ihhU/Vf VEHFJnW+AS3JpMO2Bf8ICMGu+0d4AJsNPW7KNNlqv79Nws2ijl6bcWz+E7NAG55C DY1LU5iBAoGBAPjf0QRpdDLd9+ntAkJMfSwhl0yqarZPuaGsKWnG5C7BPcj3wLaP GHn3CI0SF0JiwN0zOrLv821im5Wr5Ux/OoSDdIR/y9Vp8joTno0+7MUU5zuN93r+ 8EAHY5GEZoJ0ndU7xP50jEYq0AZinginyqtGyL6HpJL3VJoL14cCYYuRAoGBAPbH 4bHPWSEJY3X8Hq4KRbtyyTfT1s7zFrvDZHkWFH+tVD+DsKpmRQ5A0lWVBPhPaS1Y GJcu9h9VKSEjBgM2ZJpB8A4zJGYIgsPXQTOQm/s9fbWj76zJ8r2z4W7P2Ry9U1e5 cwZnQgLoPvBL7IHm4J92RfoRZO5IohRyUDaAdpGpAoGAIL3hU8FD5kVJjl7+Axbp CNtKem2ZKG8IrvplYGMoNfZ6WGwv0FS3FaSoXVbZ9IPld7R7rnre/a8RZPl+azf5 zOE2fRALEwKjOXzHSTHUGIGNgkpFGstbdDEEqmpOyi7pbNo2KnvO0JRlVdG3lM/u W+YuFtLllegwGywfqMVpa+ECgYEAp4/StFv4xdDNIuh8oGnDLWLkM674FO7DydwD FaCjbInxQWsWgq0MSIBFEO0tQbkRzkMZ91VgsqetVJ2mUHoXVxJcgBfDqDAxMe6v i+atsqru922HqMg6tQo1kHs6jSQUOeVmr7te/ABb8+dpgE6WyE+Tdhdnc9AHlWCF DGyvlXkCgYB2OYDiXSne2DYglcEk2pyr6h5sQRuKuYXnq7NWFTYIiLb/Bz6g9oLs fV5LkBfCWRSg3PoR8hX3F8PC1i2G+50gXucoFdvlvS5bawPABxtYGqhyz63awNud JnJIdqY3vLoUWeEZF3HmdBMN8jy6Am7pMynHFvoEjMBRmGNOjedZrA== -----END RSA PRIVATE KEY----- mysql-connector-python-1.1.6/tests/data/ssl/tests_client_cert.pem0000644001577100000120000000207612276514013024543 0ustar pb2userwheel-----BEGIN CERTIFICATE----- MIIC9TCCAd0CAQEwDQYJKoZIhvcNAQEFBQAwQjElMCMGA1UECwwcTXlTUUxDb25u ZWN0b3JQeXRob24gUm9vdCBDQTEZMBcGA1UEAwwQTXlDb25uUHkgUm9vdCBDQTAe Fw0xMzAzMjYxNTM1NTJaFw0yMjA0MTQxNTM1NTJaMD8xKTAnBgNVBAsMIE15U1FM Q29ubmVjdG9yUHl0aG9uIENsaWVudCBDZXJ0MRIwEAYDVQQDDAlsb2NhbGhvc3Qw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXbL7sr/k/W4LwwzTKJj5i 1QtcZL0tMyBhAwuI7XQVyJBVvY7dRUM+G30ADOcUw5DscYbkkVu3L2NtsnmuyB8o 0Y5bbHpTv4xTrVfsQuDkMLe+/LwFfL7XrY1Bm13xdEn345b6edfvhre7eatCgIaG IKfFr5JDv5oN4faGEJpqYahE/WdxM7zv6xb7Wx+yqLlezldU34VcLcghi8zfDkxb Fb4cZSgko/9RT7lTUGBJSSgITnq3Re0qANah7UbqFkTM2wfltoXGerbWMYuzOfQo 5r0FiScjuvACkDALHAdUbX4UbXasArqpGovyVqHp4OWu3FWRfcCUnxAxfj3G3x79 AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi+U6Fyc1L0qCTCiMvUMQuXacnOMH4q rHm7qDKkHHcMMGsspNXvLcVKEwJrX3dhP3dZ52eKyFsOjuTkO9eU5H8V2alO8iGD Zb6vHT/pQRInoc39SVDFx1QnJ7RlC2Z99xzncHMQChSlDCC+Lft/K5am7vXFwQ3e icfLqmR5hz6nc+opnPc7WbQu/cc7PesP5uroyKScYoqAiDJ2cKQJQFPM4Cvt/KZ3 22H/yCyQNkplIcrlQRF+l+sInNlJZr36INF0o91GcucyuLQzOXUn0L5eAyFzA9RQ 8xkVztqRN++CgbGAhqIt8ERBtxBvCpNxuFpgm4dPKCTLm+r7fJcKwDI= -----END CERTIFICATE----- mysql-connector-python-1.1.6/tests/data/ssl/tests_CA_key.pem0000644001577100000120000000321712276514013023401 0ustar pb2userwheel-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAqWcX9kD+b8c3hkPtPlIgwTsfGvhm/bJ64RHjCtQc2pi/fv9h lcryor8tWmdCCcw7ajg5n/QAIJ8crD5D0kheGEnWVI7dyVxZVfT3CiKuS+GBxuQP 2ejJi4aDGh2McVv4aq1dXRqf2YWkM8PUjM0lzUD9MC9S4APtP6ux0TBhz5rv2ZWd g2EAjAl7Q56KM5m6odpF+Z1ExnfVpNzWnpvlYHJ+GhbVWb2F0NbqBTmz4OLEAxU/ O2fo43dwVlHp+yNdib2V+VxeeyZmTt1CIeK6DStAiKdNLN5/N/+2FHZ9/XcA6qqx LFLeuTIySlPmuaX6u2C8tmOWp99TCUL+GZ2iBwIDAQABAoIBAAKXtFMtfXdieiQQ 6BGbGis652f3Q0RAtga5ylrBEkv6KHweFnU/bOU2vc/zYpxZxtMCV0duaY4WQU8V iN4wA1il0KTsptJNGoTpQdqi2z4IDn9nwCJaoLME9P6yUxLtEGk5jAM/xBCFLhUo uxkIjrqMcxOIteD9zmS6EPedoPGXbBFK2jBheArszZ/fiNhi7D2w03/s/Dhu14Px 5gjG5f+A/lS0l81RC5aeUt+wghA5y7TxY20fN1QU+XX2+Oft/HBq6xNloMlmPhzN loi952HlWLZS31QJRgEhXZ3aJMHDQ3z9I4M6RfdngW2aJTbuJq/weFgN0Z8ogDLK k/kuTfECgYEA2F5uRlUEW/0MKPrd10q5Ln3i3o0dQmW/QaPZ+SCjGan7xiC8Hm/2 awkZIIaHQThkgRtxgsLOY+o7NVWkzTeLBlCKl12O0TQ3ZofwXdWPdI2b7adiFnEd 6/htxQd90En7BgNls39j9bK7UVDDilJrRDKvyNzQKwHP95QRxJellJkCgYEAyG5p lB9j78CLWL9lZZgG7Xu/+DR63gceLLBAYclIfHzIb5B49TakasEgsT6JKbqmmwcC VXs+SSw0b1dYaFajOL9ceMkOFEn9KV5bESKcPJ2/JxBW6e5j6i4eo+oQxTTiAn75 UEcmPx8aBCtxhj4LFPKSwzi8mJNliRH2lLAYb58CgYEAlRrGLauq3GWOurLeq92v ra1M6YcfkcEiQu7SaI8oNqhgfBHU8bjAfNSBP1vV24ksIZiy6aSrrEkfUkrZzh4n rUtVpqfvopW0U/D8IP3p5S0tNmIyAzsinpnNs4jNF/vThDpVHJR+YzQvSAM7LZhM mWvAndAlmG2gToH4mJzUm4kCgYBKFk4ee4/0Uobvsifn6s88v46RT8zO/3CO8kOK Id4Sbgmk+5FKiv0xnNvZyJTpAN6O1YNuV5UJdTaYpX+/aa8BzfJ/j0oOA995iDA/ YDzCR0keRnLqG72BFbUrv9ydGNQmOgssOnCPyo5SVkCrb4mnH5dSZEmKWImipiow gfs2XwKBgQDSjbMlJme1fwNEt7EvwLJ6Zd4wSLs70IWvcX3k0g4PMhSj9J1zXRP+ wpOZCa4GW2y21t5dpHG2B+a9Sd+z0/NMSSBZ8SUfrbZza3gC6cJyPoBYy7w/PFx3 CgHcWRVI3n6+dkMYzpu2J1zzB2y0aiBE4icDq5+Uq7kO2OIytPVnHA== -----END RSA PRIVATE KEY----- mysql-connector-python-1.1.6/tests/test_style.py0000644001577100000120000000720112276514013021355 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests code analysis Requires: pylint v1.0.0 or higher """ import sys import os import tests import logging import unittest LOGGER = logging.getLogger(tests.LOGGER_NAME) _PYLINT_AVAILABLE = True try: from pylint import lint from pylint.reporters.text import TextReporter except ImportError as err: _PYLINT_AVAILABLE = False _CURRENT_PATH = os.path.abspath(os.path.dirname(__file__)) (_BASE_PATH, _,) = os.path.split(_CURRENT_PATH) PYLINTRC = os.path.join(_CURRENT_PATH, '..', 'support', 'style', 'pylint.rc') IGNORE_LIST = ['dbapi.py', 'client_error.py', 'errorcode.py', 'charsets.py'] @unittest.skipIf(not os.path.exists(PYLINTRC), "pylint.rc not available") class LintTests(tests.MySQLConnectorTests): """Class checking coding style""" def setUp(self): self.pylint_rc_path = PYLINTRC self.dir_path = os.path.join( _BASE_PATH, 'python{0}'.format(sys.version_info[0]), 'mysql', 'connector') self.output_file_path = os.path.join( _CURRENT_PATH, 'data', 'pylint_output.txt') self.pylint_output_file = open(self.output_file_path, "w+") self.failed_files = [] def tearDown(self): size = self.pylint_output_file.tell() self.pylint_output_file.close() if not size: os.remove(self.output_file_path) @unittest.skipIf(not _PYLINT_AVAILABLE, "pylint not available") def test_lint(self): """Process modules for pylint tests """ for root, _, files in os.walk(self.dir_path): for name in files: if name.endswith('.py') and name not in IGNORE_LIST: current_path = os.path.join(root, name) lint_run = lint.Run( [current_path, "--rcfile={0}".format( self.pylint_rc_path)], reporter=TextReporter( self.pylint_output_file), exit=False) if lint_run.linter.stats['by_msg']: rel_file_path = os.path.join( os.path.relpath(root, _BASE_PATH), name) self.failed_files.append(rel_file_path) if self.failed_files: file_names = '' for file in self.failed_files: file_names += file + '\n' self.fail('Lint tests failed on following files\n{0}\n' 'For more information check {1}.'.format( file_names, os.path.relpath(self.output_file_path, _BASE_PATH))) mysql-connector-python-1.1.6/tests/test_errors.py0000644001577100000120000002070212276514013021532 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.errors """ import tests from mysql.connector import errors class ErrorsTests(tests.MySQLConnectorTests): def test_custom_error_exception(self): customfunc = errors.custom_error_exception self.assertRaises(ValueError, customfunc, 'spam') self.assertRaises(ValueError, customfunc, 1) self.assertRaises(ValueError, customfunc, 1, 'spam') case = (1, errors.InterfaceError) exp = {1: errors.InterfaceError} self.assertEqual(exp, customfunc(*case)) exp = case = {1: errors.InterfaceError, 2: errors.ProgrammingError} self.assertEqual(exp, customfunc(case)) case = {1: errors.InterfaceError, 2: None} self.assertRaises(ValueError, customfunc, case) case = {1: errors.InterfaceError, 2: str()} self.assertRaises(ValueError, customfunc, case) case = {'1': errors.InterfaceError} self.assertRaises(ValueError, customfunc, case) self.assertEqual({}, customfunc({})) self.assertEqual({}, errors._CUSTOM_ERROR_EXCEPTIONS) def test_get_mysql_exception(self): tests = { errors.ProgrammingError: ( '24', '25', '26', '27', '28', '2A', '2C', '34', '35', '37', '3C', '3D', '3F', '42'), errors.DataError: ('02', '21', '22'), errors.NotSupportedError: ('0A',), errors.IntegrityError: ('23', 'XA'), errors.InternalError: ('40', '44'), errors.OperationalError: ('08', 'HZ', '0K'), errors.DatabaseError: ('07', '2B', '2D', '2E', '33', 'ZZ', 'HY'), } msg = 'Ham' for exp, errlist in tests.items(): for sqlstate in errlist: errno = 1000 res = errors.get_mysql_exception(errno, msg, sqlstate) self.assertTrue(isinstance(res, exp), "SQLState {0} should be {1}".format( sqlstate, exp.__name__)) self.assertEqual(sqlstate, res.sqlstate) self.assertEqual("{0} ({1}): {2}".format(errno, sqlstate, msg), str(res)) errno = 1064 sqlstate = "42000" msg = "You have an error in your SQL syntax" exp = "1064 (42000): You have an error in your SQL syntax" err = errors.get_mysql_exception(errno, msg, sqlstate) self.assertEqual(exp, str(err)) # Hardcoded exceptions self.assertTrue(isinstance(errors._ERROR_EXCEPTIONS, dict)) self.assertTrue( isinstance(errors.get_mysql_exception(1243, None, None), errors.ProgrammingError)) # Custom exceptions errors._CUSTOM_ERROR_EXCEPTIONS[1064] = errors.DatabaseError self.assertTrue( isinstance(errors.get_mysql_exception(1064, None, None), errors.DatabaseError)) errors._CUSTOM_ERROR_EXCEPTIONS = {} def test_get_exception(self): ok_packet = b'\x07\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00' err_packet = ( b'\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30' b'\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64' b'\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61' b'\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74' b'\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73' b'\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29' ) self.assertTrue(isinstance(errors.get_exception(err_packet), errors.ProgrammingError)) self.assertRaises(ValueError, errors.get_exception, ok_packet) res = errors.get_exception(b'\x47\x00\x00\x02\xff\x15') self.assertTrue(isinstance(res, errors.InterfaceError)) class ErrorTest(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.Error, Exception)) err = errors.Error() self.assertEqual(-1, err.errno) self.assertEqual('Unknown error', err.msg) self.assertEqual(None, err.sqlstate) msg = 'Ham' err = errors.Error(msg, errno=1) self.assertEqual(1, err.errno) self.assertEqual('1: {0}'.format(msg), err._full_msg) self.assertEqual(msg, err.msg) err = errors.Error('Ham', errno=1, sqlstate="SPAM") self.assertEqual(1, err.errno) self.assertEqual('1 (SPAM): Ham', err._full_msg) self.assertEqual('1 (SPAM): Ham', str(err)) err = errors.Error(errno=2000) self.assertEqual('Unknown MySQL error', err.msg) self.assertEqual('2000: Unknown MySQL error', err._full_msg) err = errors.Error(errno=2003, values=('/path/to/ham', 2)) self.assertEqual( "2003: Can't connect to MySQL server on '/path/to/ham' (2)", err._full_msg) self.assertEqual( "Can't connect to MySQL server on '/path/to/ham' (2)", err.msg) err = errors.Error(errno=2001, values=('ham',)) if '(Warning:' in str(err): self.fail('Found %d in error message.') err = errors.Error(errno=2003, values=('ham',)) self.assertEqual( "2003: Can't connect to MySQL server on '%-.100s' (%s) " "(Warning: not enough arguments for format string)", err._full_msg) def test___str__(self): msg = "Spam" self.assertEqual("Spam", str(errors.Error(msg))) self.assertEqual("1: Spam", str(errors.Error(msg, 1))) self.assertEqual("1 (XYZ): Spam", str(errors.Error(msg, 1, sqlstate='XYZ'))) class WarningTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.Warning, Exception)) class InterfaceErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.InterfaceError, errors.Error)) class DatabaseErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.DatabaseError, errors.Error)) class InternalErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.InternalError, errors.DatabaseError)) class OperationalErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.OperationalError, errors.DatabaseError)) class ProgrammingErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.ProgrammingError, errors.DatabaseError)) class IntegrityErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.IntegrityError, errors.DatabaseError)) class DataErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.DataError, errors.DatabaseError)) class NotSupportedErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.NotSupportedError, errors.DatabaseError)) class PoolErrorTests(tests.MySQLConnectorTests): def test___init__(self): self.assertTrue(issubclass(errors.PoolError, errors.Error)) mysql-connector-python-1.1.6/tests/test_pep249.py0000644001577100000120000004543012276514013021246 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for PEP-249 Rewritten from scratch. Found Ian Bicking's test suite and shamelessly stole few of his ideas. (Geert) """ import datetime import time import inspect import tests import mysql.connector as myconn class PEP249Base(tests.MySQLConnectorTests): def db_connect(self): return myconn.connect(**tests.get_mysql_config()) def get_connection_id(self, cursor): cid = None try: cursor.execute("SELECT CONNECTION_ID()") cid = cursor.fetchone()[0] except myconn.errors.Error as err: self.fail("Failed getting connection id; {0}".format(str(err))) return cid def setUp(self): self.cnx = self.db_connect() def tearDown(self): self.cnx.close() class PEP249ModuleTests(PEP249Base): def setUp(self): pass def tearDown(self): pass def test_connect(self): """Interface exports the connect()-function""" self.assertTrue(inspect.isfunction(myconn.connect), "Module does not export the connect()-function") cnx = myconn.connect(**tests.get_mysql_config()) self.assertTrue(isinstance(cnx, myconn.connection.MySQLConnection), "The connect()-method returns incorrect instance") def test_apilevel(self): """Interface sets the API level""" self.assertTrue(hasattr(myconn, 'apilevel'), "API level is not defined") self.assertEqual('2.0', myconn.apilevel, "API Level should be '2.0'") def test_threadsafety(self): """Interface defines thread safety""" self.assertTrue(myconn.threadsafety in (0, 1, 2, 3)) self.assertEqual(1, myconn.threadsafety) def test_paramstyle(self): """Interface sets the parameter style""" self.assertTrue(myconn.paramstyle in ('qmark', 'numeric', 'named', 'format', 'pyformat'), "paramstyle was assigned an unsupported value") self.assertEqual('pyformat', myconn.paramstyle, "paramstyle should be 'pyformat'") class PEP249ErrorsTests(PEP249Base): def setUp(self): pass def tearDown(self): pass def test_Warning(self): """Interface exports the Warning-exception""" self.assertTrue(issubclass(myconn.errors.Warning, Exception), "Warning is not subclass of Exception") def test_Error(self): """Interface exports the Error-exception""" self.assertTrue(issubclass(myconn.errors.Error, Exception), "Error is not subclass of Exception") def test_InterfaceError(self): """Interface exports the InterfaceError-exception""" self.assertTrue(issubclass(myconn.errors.InterfaceError, myconn.errors.Error), "InterfaceError is not subclass of errors.Error") def test_DatabaseError(self): """Interface exports the DatabaseError-exception""" self.assertTrue(issubclass(myconn.errors.DatabaseError, myconn.errors.Error), "DatabaseError is not subclass of errors.Error") def test_DataError(self): """Interface exports the DataError-exception""" self.assertTrue(issubclass(myconn.errors.DataError, myconn.errors.DatabaseError), "DataError is not subclass of errors.DatabaseError") def test_OperationalError(self): """Interface exports the OperationalError-exception""" self.assertTrue( issubclass(myconn.errors.OperationalError, myconn.errors.DatabaseError), "OperationalError is not subclass of errors.DatabaseError") def test_IntegrityError(self): """Interface exports the IntegrityError-exception""" self.assertTrue( issubclass(myconn.errors.IntegrityError, myconn.errors.DatabaseError), "IntegrityError is not subclass of errors.DatabaseError") def test_InternalError(self): """Interface exports the InternalError-exception""" self.assertTrue(issubclass(myconn.errors.InternalError, myconn.errors.DatabaseError), "InternalError is not subclass of errors.DatabaseError") def test_ProgrammingError(self): """Interface exports the ProgrammingError-exception""" self.assertTrue( issubclass(myconn.errors.ProgrammingError, myconn.errors.DatabaseError), "ProgrammingError is not subclass of errors.DatabaseError") def test_NotSupportedError(self): """Interface exports the NotSupportedError-exception""" self.assertTrue( issubclass(myconn.errors.NotSupportedError, myconn.errors.DatabaseError), "NotSupportedError is not subclass of errors.DatabaseError") class PEP249ConnectionTests(PEP249Base): def test_close(self): """Connection object has close()-method""" self.assertTrue(hasattr(self.cnx, 'close'), "Interface connection has no close()-method") self.assertTrue( inspect.ismethod(self.cnx.close), "Interface connection defines connect, but is not a method") def test_commit(self): """Connection object has commit()-method""" self.assertTrue(hasattr(self.cnx, 'commit'), "Interface connection has no commit()-method") self.assertTrue( inspect.ismethod(self.cnx.commit), "Interface connection defines commit, but is not a method") def test_rollback(self): """Connection object has rollback()-method""" self.assertTrue(hasattr(self.cnx, 'rollback'), "Interface connection has no rollback()-method") self.assertTrue( inspect.ismethod(self.cnx.rollback), "Interface connection defines rollback, but is not a method") def test_cursor(self): """Connection object has cursor()-method""" self.assertTrue(hasattr(self.cnx, 'cursor'), "Interface connection has no cursor()-method") self.assertTrue( inspect.ismethod(self.cnx.cursor), "Interface connection defines cursor, but is not a method") self.assertTrue( isinstance(self.cnx.cursor(), myconn.cursor.MySQLCursor), "Interface connection cursor()-method does not return a cursor") class PEP249CursorTests(PEP249Base): def setUp(self): self.cnx = self.db_connect() self.cur = self.cnx.cursor() def test_description(self): """Cursor object has description-attribute""" self.assertTrue(hasattr(self.cur, 'description'), "Cursor object has no description-attribute") self.assertEqual(None, self.cur.description, "Cursor object's description should default ot None") def test_rowcount(self): """Cursor object has rowcount-attribute""" self.assertTrue(hasattr(self.cur, 'rowcount'), "Cursor object has no rowcount-attribute") self.assertEqual(-1, self.cur.rowcount, "Cursor object's rowcount should default to -1") def test_lastrowid(self): """Cursor object has lastrowid-attribute""" self.assertTrue(hasattr(self.cur, 'lastrowid'), "Cursor object has no lastrowid-attribute") self.assertEqual(None, self.cur.lastrowid, "Cursor object's lastrowid should default to None") def test_callproc(self): """Cursor object has callproc()-method""" self.assertTrue(hasattr(self.cur, 'callproc'), "Cursor object has no callproc()-method") self.assertTrue(inspect.ismethod(self.cur.callproc), "Cursor object defines callproc, but is not a method") def test_close(self): """Cursor object has close()-method""" self.assertTrue(hasattr(self.cur, 'close'), "Cursor object has no close()-method") self.assertTrue(inspect.ismethod(self.cur.close), "Cursor object defines close, but is not a method") def test_execute(self): """Cursor object has execute()-method""" self.assertTrue(hasattr(self.cur, 'execute'), "Cursor object has no execute()-method") self.assertTrue(inspect.ismethod(self.cur.execute), "Cursor object defines execute, but is not a method") def test_executemany(self): """Cursor object has executemany()-method""" self.assertTrue(hasattr(self.cur, 'executemany'), "Cursor object has no executemany()-method") self.assertTrue( inspect.ismethod(self.cur.executemany), "Cursor object defines executemany, but is not a method") def test_fetchone(self): """Cursor object has fetchone()-method""" self.assertTrue(hasattr(self.cur, 'fetchone'), "Cursor object has no fetchone()-method") self.assertTrue(inspect.ismethod(self.cur.fetchone), "Cursor object defines fetchone, but is not a method") def test_fetchmany(self): """Cursor object has fetchmany()-method""" self.assertTrue(hasattr(self.cur, 'execute'), "Cursor object has no fetchmany()-method") self.assertTrue(inspect.ismethod(self.cur.fetchmany), "Cursor object defines fetchmany, but is not a method") def test_fetchall(self): """Cursor object has fetchall()-method""" self.assertTrue(hasattr(self.cur, 'fetchall'), "Cursor object has no fetchall()-method") self.assertTrue(inspect.ismethod(self.cur.fetchall), "Cursor object defines fetchall, but is not a method") def test_nextset(self): """Cursor object has nextset()-method""" self.assertTrue(hasattr(self.cur, 'nextset'), "Cursor object has no nextset()-method") self.assertTrue(inspect.ismethod(self.cur.nextset), "Cursor object defines nextset, but is not a method") def test_arraysize(self): """Cursor object has arraysize-attribute""" self.assertTrue(hasattr(self.cur, 'arraysize'), "Cursor object has no arraysize-attribute") self.assertEqual(1, self.cur.arraysize, "Cursor object's arraysize should default to 1") def test_setinputsizes(self): """Cursor object has setinputsizes()-method""" self.assertTrue(hasattr(self.cur, 'setinputsizes'), "Cursor object has no setinputsizes()-method") self.assertTrue(inspect.ismethod(self.cur.setinputsizes), "Cursor object's setinputsizes should default to 1") def test_setoutputsize(self): """Cursor object has setoutputsize()-method""" self.assertTrue(hasattr(self.cur, 'setoutputsize'), "Cursor object has no setoutputsize()-method") self.assertTrue(inspect.ismethod(self.cur.setoutputsize), "Cursor object's setoutputsize should default to 1") def _isolation_setup(self, drop, create): cursor = self.cnx.cursor() try: cursor.execute(drop) cursor.execute(create) except myconn.errors.Error as err: self.fail("Failed setting up test table; {0}".format(err)) cursor.close() def _isolation_connection_equal(self, cnx1, cnx2): cid1 = self.get_connection_id(cnx1) cid2 = self.get_connection_id(cnx2) return (cid1 == cid2) def _isolation_cleanup(self, drop): cursor = self.cnx.cursor() try: cursor.execute(drop) except myconn.errors.Error as err: self.fail("Failed cleaning up; {0}".format(err)) cursor.close() def _isolation_test(self, cnx1, cnx2, engine='MyISAM'): cur1 = cnx1.cursor() cur2 = cnx2.cursor() data = (1, 'myconnpy') tbl = 'myconnpy_cursor_isolation' stmt_create = ( "CREATE TABLE {table} " "(col1 INT, col2 VARCHAR(30), PRIMARY KEY (col1)) " "ENGINE={engine}" ).format(table=tbl, engine=engine) stmt_drop = "DROP TABLE IF EXISTS {table}".format(table=tbl) stmt_insert = ( "INSERT INTO {table} (col1,col2) " "VALUES (%s,%s)" ).format(table=tbl) stmt_select = "SELECT col1,col2 FROM {table}".format(table=tbl) # Setup cur1.execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ") cur2.execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ") self._isolation_setup(stmt_drop, stmt_create) conn_equal = self._isolation_connection_equal(cur1, cur2) if cnx1 == cnx2 and not conn_equal: self.fail("Cursors should have same connection ID") elif cnx1 != cnx2 and conn_equal: self.fail("Cursors should have different connection ID") # Insert data try: cur1.execute(stmt_insert, data) except myconn.errors.Error as err: self.fail("Failed inserting test data; {0}".format(str(err))) # Query for data result = None try: cur2.execute(stmt_select) result = cur2.fetchone() except myconn.errors.InterfaceError: pass except myconn.errors.Error as err: self.fail("Failed querying for test data; {0}".format(str(err))) if conn_equal: self.assertEqual(data, result) elif not conn_equal and engine.lower() == 'innodb': self.assertEqual(None, result) # Clean up self._isolation_cleanup(stmt_drop) cur1.close() cur2.close() def test_isolation1(self): """Cursor isolation between 2 cursor on same connection""" self._isolation_test(self.cnx, self.cnx, 'MyISAM') def test_isolation2(self): """Cursor isolation with 2 cursors, different connections, trans.""" db2 = self.db_connect() if tests.have_engine(db2, 'InnoDB'): self._isolation_test(self.cnx, db2, 'InnoDB') class PEP249TypeObjConstructorsTests(PEP249Base): def test_Date(self): """Interface exports Date""" exp = datetime.date(1977, 6, 14) self.assertEqual(myconn.Date(1977, 6, 14), exp, "Interface Date should return a datetime.date") def test_Time(self): """Interface exports Time""" exp = datetime.time(23, 56, 13) self.assertEqual(myconn.Time(23, 56, 13), exp, "Interface Time should return a datetime.time") def test_Timestamp(self): """Interface exports Timestamp""" adate = (1977, 6, 14, 21, 54, 23) exp = datetime.datetime(*adate) self.assertEqual( myconn.Timestamp(*adate), exp, "Interface Timestamp should return a datetime.datetime") def test_DateFromTicks(self): """Interface exports DateFromTicks""" ticks = 1 exp = datetime.date(*time.localtime(ticks)[:3]) self.assertEqual( myconn.DateFromTicks(ticks), exp, "Interface DateFromTicks should return a datetime.date") def test_TimeFromTicks(self): """Interface exports TimeFromTicks""" ticks = 1 exp = datetime.time(*time.localtime(ticks)[3:6]) self.assertEqual( myconn.TimeFromTicks(ticks), exp, "Interface TimeFromTicks should return a datetime.time") def test_TimestampFromTicks(self): """Interface exports TimestampFromTicks""" ticks = 1 exp = datetime.datetime(*time.localtime(ticks)[:6]) self.assertEqual( myconn.TimestampFromTicks(ticks), exp, "Interface TimestampFromTicks should return a datetime.datetime") def test_Binary(self): """Interface exports Binary""" exp = r'\u82b1'.encode('utf-8') self.assertEqual( myconn.Binary(r'\u82b1'.encode('utf-8')), exp, "Interface Binary should return a str") def test_STRING(self): """Interface exports STRING""" self.assertTrue(hasattr(myconn, 'STRING')) self.assertTrue( isinstance(myconn.STRING, myconn.dbapi._DBAPITypeObject), "Interface STRING should return a _DBAPITypeObject") def test_BINARY(self): """Interface exports BINARY""" self.assertTrue(hasattr(myconn, 'BINARY')) self.assertTrue( isinstance(myconn.BINARY, myconn.dbapi._DBAPITypeObject), "Interface BINARY should return a _DBAPITypeObject") def test_NUMBER(self): """Interface exports NUMBER""" self.assertTrue(hasattr(myconn, 'NUMBER')) self.assertTrue( isinstance(myconn.NUMBER, myconn.dbapi._DBAPITypeObject), "Interface NUMBER should return a _DBAPITypeObject") def test_DATETIME(self): """Interface exports DATETIME""" self.assertTrue(hasattr(myconn, 'DATETIME')) self.assertTrue( isinstance(myconn.DATETIME, myconn.dbapi._DBAPITypeObject), "Interface DATETIME should return a _DBAPITypeObject") def test_ROWID(self): """Interface exports ROWID""" self.assertTrue(hasattr(myconn, 'ROWID')) self.assertTrue( isinstance(myconn.ROWID, myconn.dbapi._DBAPITypeObject), "Interface ROWID should return a _DBAPITypeObject") mysql-connector-python-1.1.6/tests/py3/0000755001577100000120000000000012276514327017327 5ustar pb2userwheelmysql-connector-python-1.1.6/tests/py3/connection.py0000644001577100000120000000357112276514013022036 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for mysql.connector.connection specific to Python v3 """ OK_PACKET = b'\x07\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00' OK_PACKET_RESULT = { 'insert_id': 0, 'affected_rows': 0, 'field_count': 0, 'warning_count': 0, 'server_status': 0 } ERR_PACKET = b'\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\ b'\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\ b'\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\ b'\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\ b'\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\ b'\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29' EOF_PACKET = b'\x05\x00\x00\x00\xfe\x00\x00\x00\x00' EOF_PACKET_RESULT = {'status_flag': 0, 'warning_count': 0} mysql-connector-python-1.1.6/tests/py3/bugs.py0000644001577100000120000001141712276514013020635 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for bugs specific to Python v3 """ import os import tests from mysql.connector import connection, errors class BugOra14843456(tests.MySQLConnectorTests): """BUG#14843456: UNICODE USERNAME AND/OR PASSWORD FAILS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() if config['unix_socket'] and os.name != 'nt': self.host = 'localhost' else: self.host = config['host'] grant = "CREATE USER '{user}'@'{host}' IDENTIFIED BY '{password}'" self._credentials = [ ('Herne', 'Herne'), ('\u0141owicz', '\u0141owicz'), ] for user, password in self._credentials: self.cursor.execute(grant.format( user=user, host=self.host, password=password)) def tearDown(self): for user, password in self._credentials: self.cursor.execute("DROP USER '{user}'@'{host}'".format( user=user, host=self.host)) def test_unicode_credentials(self): config = tests.get_mysql_config() for user, password in self._credentials: config['user'] = user config['password'] = password config['database'] = None try: cnx = connection.MySQLConnection(**config) except (UnicodeDecodeError, errors.InterfaceError): self.fail('Failed using unicode username or password') else: cnx.close() class Bug499410(tests.MySQLConnectorTests): def test_use_unicode(self): """lp:499410 Disabling unicode does not work""" config = tests.get_mysql_config() config['use_unicode'] = False cnx = connection.MySQLConnection(**config) self.assertEqual(False, cnx._use_unicode) cnx.close() def test_charset(self): config = tests.get_mysql_config() config['use_unicode'] = False charset = 'greek' config['charset'] = charset cnx = connection.MySQLConnection(**config) data = [b'\xe1\xed\xf4\xdf\xef'] # Bye in Greek exp_unicode = [('\u03b1\u03bd\u03c4\u03af\u03bf',), ] exp_nonunicode = [(data[0],)] cur = cnx.cursor() tbl = '{0}test'.format(charset) try: cur.execute('DROP TABLE IF EXISTS {0}'.format(tbl)) cur.execute( 'CREATE TABLE {0} (c1 VARCHAR(60)) charset={1}'.format( tbl, charset)) except: self.fail("Failed creating test table.") try: stmt = 'INSERT INTO {0} VALUES (%s)'.format(tbl) for line in data: cur.execute(stmt, (line.strip(),)) except: self.fail("Failed populating test table.") cur.execute("SELECT * FROM {0}".format(tbl)) res_nonunicode = cur.fetchall() cnx.set_unicode(True) cur.execute("SELECT * FROM {0}".format(tbl)) res_unicode = cur.fetchall() try: cur.execute('DROP TABLE IF EXISTS {0}'.format(tbl)) except: self.fail("Failed cleaning up test table.") cnx.close() self.assertEqual(exp_nonunicode, res_nonunicode) self.assertEqual(exp_unicode, res_unicode) class BugOra17079344Extra(object): """Extras for test case test_bugs.BugOra17079344""" data_gbk = ['赵孟頫', '赵\孟\頫\\', '遜',] data_sjis = ['\u005c'] data_big5 = ['\u5C62'] class BugOra17780576Extra(object): """Extras for test case test_bugs.BugOra17780576""" data_utf8mb4 = ['😉😍', '😃😊', '😄😘😚',] mysql-connector-python-1.1.6/tests/py3/test_utils.py0000644001577100000120000002203412276514013022071 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.utils """ import struct import tests from mysql.connector import utils class UtilsTests(tests.MySQLConnectorTests): """Testing the helper functions in the utils module. These tests should not make a connection to the database. """ def _check_int_result(self, result, exp, data): if not isinstance(result, bytes): self.fail("Wrong result. Expected {0}, we got {1}".format( (type(exp), type(result)))) elif exp != result: self.fail("Wrong result. Expected {0}, we got {1}".format( (data, result))) def test_intread(self): """Use intread to read from valid strings.""" try: for i in range(4): utils.intread(b'a' * (i + 1)) except ValueError as err: self.fail("intread failed calling 'int{0}read: {1}".format( int(i) + 1, err)) def test_int1store(self): """Use int1store to pack an integer (2^8) as a string.""" data = 2 ** (8 - 1) exp = struct.pack(', like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.protocol """ import struct import datetime import decimal import tests from mysql.connector import (protocol, errors) from mysql.connector.constants import (ClientFlag, FieldType, FieldFlag) OK_PACKET = b'\x07\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00' OK_PACKET_RESULT = { 'insert_id': 0, 'affected_rows': 1, 'field_count': 0, 'warning_count': 1, 'server_status': 0 } ERR_PACKET = b'\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\ b'\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\ b'\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\ b'\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\ b'\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\ b'\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29' EOF_PACKET = b'\x01\x00\x00\x00\xfe\x00\x00\x00\x00' EOF_PACKET_RESULT = {'status_flag': 0, 'warning_count': 0} SEED = b'\x3b\x55\x78\x7d\x2c\x5f\x7c\x72\x49\x52'\ b'\x3f\x28\x47\x6f\x77\x28\x5f\x28\x46\x69' class MySQLProtocolTests(tests.MySQLConnectorTests): def setUp(self): self._protocol = protocol.MySQLProtocol() def test__scramble_password(self): """Scramble a password ready to send to MySQL""" password = "spam".encode('utf-8') hashed = b'\x3a\x07\x66\xba\xba\x01\xce\xbe\x55\xe6'\ b'\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91\x5b' res = self._protocol._scramble_password(password, SEED) self.assertEqual(hashed, res) def test_make_auth(self): """Make a MySQL authentication packet""" exp = { 'allset': b'\x0d\xa2\x03\x00\x00\x00\x00\x40' b'\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x68\x61\x6d\x00\x14\x3a\x07\x66\xba\xba\x01\xce' b'\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' b'\x5b\x74\x65\x73\x74\x00', 'nopass': b'\x0d\xa2\x03\x00\x00\x00\x00\x40' b'\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x68\x61\x6d\x00\x00\x74\x65\x73\x74\x00', 'nouser': b'\x0d\xa2\x03\x00\x00\x00\x00\x40' b'\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x14\x3a\x07\x66\xba\xba\x01\xce' b'\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' b'\x5b\x74\x65\x73\x74\x00', 'nodb': b'\x0d\xa2\x03\x00\x00\x00\x00\x40' b'\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x68\x61\x6d\x00\x14\x3a\x07\x66\xba\xba\x01\xce' b'\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' b'\x5b\x00', } flags = ClientFlag.get_default() kwargs = { 'seed': None, 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 33, 'client_flags': flags} self.assertRaises(errors.ProgrammingError, self._protocol.make_auth, **kwargs) kwargs['seed'] = SEED res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['allset'], res) kwargs['password'] = None res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nopass'], res) kwargs['password'] = 'spam' kwargs['database'] = None res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nodb'], res) kwargs['username'] = None kwargs['database'] = 'test' res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nouser'], res) def test_make_auth_ssl(self): """Make a SSL authentication packet""" cases = [ ({}, b'\x00\x00\x00\x00\x00\x00\x00\x40\x21\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00'), ({'charset': 8}, b'\x00\x00\x00\x00\x00\x00\x00\x40\x08\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00'), ({'client_flags': 240141}, b'\x0d\xaa\x03\x00\x00\x00\x00\x40\x21\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00'), ({'charset': 8, 'client_flags': 240141, 'max_allowed_packet': 2147483648}, b'\x0d\xaa\x03\x00\x00\x00\x00\x80\x08\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00'), ] for kwargs, exp in cases: self.assertEqual(exp, self._protocol.make_auth_ssl(**kwargs)) def test_make_command(self): """Make a generic MySQL command packet""" exp = b'\x01\x68\x61\x6d' arg = 'ham'.encode('utf-8') res = self._protocol.make_command(1, arg) self.assertEqual(exp, res) res = self._protocol.make_command(1, argument=arg) self.assertEqual(exp, res) exp = b'\x03' res = self._protocol.make_command(3) self.assertEqual(exp, res) def test_make_changeuser(self): """Make a change user MySQL packet""" exp = { 'allset': b'\x11\x68\x61\x6d\x00\x14\x3a\x07' b'\x66\xba\xba\x01\xce\xbe\x55\xe6\x29\x88\xaa\xae' b'\xdb\x00\xb3\x4d\x91\x5b\x74\x65\x73\x74\x00\x08' b'\x00', 'nopass': b'\x11\x68\x61\x6d\x00\x00\x74\x65' b'\x73\x74\x00\x08\x00', } kwargs = { 'seed': None, 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 8, 'client_flags': ClientFlag.get_default() } self.assertRaises(errors.ProgrammingError, self._protocol.make_change_user, **kwargs) kwargs['seed'] = SEED res = self._protocol.make_change_user(**kwargs) self.assertEqual(exp['allset'], res) kwargs['password'] = None res = self._protocol.make_change_user(**kwargs) self.assertEqual(exp['nopass'], res) def test_parse_handshake(self): """Parse handshake-packet sent by MySQL""" handshake = \ b'\x47\x00\x00\x00\x0a\x35\x2e\x30\x2e\x33\x30\x2d'\ b'\x65\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67'\ b'\x70\x6c\x2d\x6c\x6f\x67\x00\x09\x01\x00\x00\x68'\ b'\x34\x69\x36\x6f\x50\x21\x4f\x00\x2c\xa2\x08\x02'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72'\ b'\x59\x48\x00' exp = { 'protocol': 10, 'server_version_original': b'5.0.30-enterprise-gpl-log', 'charset': 8, 'server_threadid': 265, 'capabilities': 41516, 'server_status': 2, 'scramble': b'h4i6oP!OLng9&PD@WrYH' } res = self._protocol.parse_handshake(handshake) self.assertEqual(exp, res) def test_parse_ok(self): """Parse OK-packet sent by MySQL""" res = self._protocol.parse_ok(OK_PACKET) self.assertEqual(OK_PACKET_RESULT, res) okpkt = OK_PACKET + b'\x04spam' exp = OK_PACKET_RESULT.copy() exp['info_msg'] = 'spam' res = self._protocol.parse_ok(okpkt) self.assertEqual(exp, res) def test_parse_column_count(self): """Parse the number of columns""" packet = b'\x01\x00\x00\x01\x03' res = self._protocol.parse_column_count(packet) self.assertEqual(3, res) packet = b'\x01\x00' self.assertRaises(errors.InterfaceError, self._protocol.parse_column_count, packet) def test_parse_column(self): """Parse field-packet sent by MySQL""" column_packet = \ b'\x1a\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x04'\ b'\x53\x70\x61\x6d\x00\x0c\x21\x00\x09\x00\x00\x00'\ b'\xfd\x01\x00\x1f\x00\x00' exp = ('Spam', 253, None, None, None, None, 0, 1) res = self._protocol.parse_column(column_packet) self.assertEqual(exp, res) def test_parse_eof(self): """Parse EOF-packet sent by MySQL""" res = self._protocol.parse_eof(EOF_PACKET) self.assertEqual(EOF_PACKET_RESULT, res) def test_read_text_result(self): # Tested by MySQLConnectionTests.test_get_rows() and .test_get_row() pass def test_parse_binary_prepare_ok(self): """Parse Prepare OK packet""" cases = [ # SELECT CONCAT(?, ?) AS c1 (b'\x0c\x00\x00\x01' b'\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00', {'num_params': 2, 'statement_id': 1, 'warning_count': 0, 'num_columns': 1 } ), # DO 1 (b'\x0c\x00\x00\x01' b'\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', {'num_params': 0, 'statement_id': 1, 'warning_count': 0, 'num_columns': 0 } ), ] for packet, exp in cases: self.assertEqual(exp, self._protocol.parse_binary_prepare_ok(packet)) def test__parse_binary_integer(self): """Parse an integer from a binary packet""" # Case = Expected value; pack format; field type; field flag cases = [ (-128, 'b', FieldType.TINY, 0), (-32768, 'h', FieldType.SHORT, 0), (-2147483648, 'i', FieldType.LONG, 0), (-9999999999, 'q', FieldType.LONGLONG, 0), (255, 'B', FieldType.TINY, FieldFlag.UNSIGNED), (65535, 'H', FieldType.SHORT, FieldFlag.UNSIGNED), (4294967295, 'I', FieldType.LONG, FieldFlag.UNSIGNED), (9999999999, 'Q', FieldType.LONGLONG, FieldFlag.UNSIGNED), ] field_info = [None] * 8 field_info[0] = 'c1' for exp, fmt, field_type, flag in cases: field_info[1] = field_type field_info[7] = flag data = struct.pack(fmt, exp) + b'\x00\x00' res = self._protocol._parse_binary_integer(data, field_info) self.assertEqual((b'\x00\x00', exp), res, "Failed parsing binary integer '{0}'".format(exp)) def test__parse_binary_float(self): """Parse a float/double from a binary packet""" # Case = Expected value; data; field type cases = [ (-3.14159, b'\x6e\x86\x1b\xf0\xf9\x21\x09\xc0', FieldType.DOUBLE), (3.14159, b'\x6e\x86\x1b\xf0\xf9\x21\x09\x40', FieldType.DOUBLE), (-3.14, b'\xc3\xf5\x48\xc0', FieldType.FLOAT), (3.14, b'\xc3\xf5\x48\x40', FieldType.FLOAT), ] field_info = [None] * 8 field_info[0] = 'c1' for exp, data, field_type in cases: field_info[1] = field_type res = self._protocol._parse_binary_float(data + b'\x00\x00', field_info) self.assertEqual(b'\x00\x00', res[0], "Failed parsing binary float '{0}'".format(exp)) self.assertAlmostEqual( exp, res[1], places=5, msg="Failed parsing binary float '{0}'".format(exp)) def test__parse_binary_timestamp(self): """Parse a timestamp from a binary packet""" # Case = Expected value; data cases = [ (datetime.date(1977, 6, 14), b'\x04\xb9\x07\x06\x0e'), (datetime.datetime(1977, 6, 14, 21, 33, 14), b'\x07\xb9\x07\x06\x0e\x15\x21\x0e'), (datetime.datetime(1977, 6, 14, 21, 33, 14, 345), b'\x0b\xb9\x07\x06\x0e\x15\x21\x0e\x59\x01\x00\x00') ] for exp, data in cases: res = self._protocol._parse_binary_timestamp(data + b'\x00\x00', None) self.assertEqual((b'\x00\x00', exp), res, "Failed parsing timestamp '{0}'".format(exp)) def test__parse_binary_time(self): """Parse a time value from a binary packet""" cases = [ (datetime.timedelta(0, 44130), b'\x08\x00\x00\x00\x00\x00\x0c\x0f\x1e'), (datetime.timedelta(14, 15330), b'\x08\x00\x0e\x00\x00\x00\x04\x0f\x1e'), (datetime.timedelta(-14, 15330), b'\x08\x01\x0e\x00\x00\x00\x04\x0f\x1e'), (datetime.timedelta(10, 58530, 230000), b'\x0c\x00\x0a\x00\x00\x00\x10\x0f\x1e\x70\x82\x03\x00'), ] for exp, data in cases: res = self._protocol._parse_binary_time(data + b'\x00\x00', None) self.assertEqual((b'\x00\x00', exp), res, "Failed parsing time '{0}'".format(exp)) def test__parse_binary_values(self): """Parse values from a binary result packet""" # The packet in this test is result of the following query: # SELECT 'abc' AS aStr," # "3.14 AS aFloat," # "-3.14159 AS aDouble, " # "MAKEDATE(2003, 31) AS aDate, " # "TIMESTAMP('1977-06-14', '21:33:14') AS aDateTime, " # "MAKETIME(256,15,30.23) AS aTime, " # "NULL AS aNull" # fields = [('aStr', 253, None, None, None, None, 0, 1), ('aFloat', 246, None, None, None, None, 0, 129), ('aDouble', 246, None, None, None, None, 0, 129), ('aDate', 10, None, None, None, None, 1, 128), ('aDateTime', 12, None, None, None, None, 1, 128), ('aTime', 11, None, None, None, None, 1, 128), ('aNull', 6, None, None, None, None, 1, 128)] packet = (b'\x00\x01\x03\x61\x62\x63\x04\x33\x2e\x31\x34\x08' b'\x2d\x33\x2e\x31\x34\x31\x35\x39\x04\xd3\x07' b'\x01\x1f\x07\xb9\x07\x06\x0e\x15\x21\x0e\x0c' b'\x00\x0a\x00\x00\x00\x10\x0f\x1e\x70\x82\x03\x00') # float/double are returned as DECIMAL by MySQL exp = (b'abc', b'3.14', b'-3.14159', datetime.date(2003, 1, 31), datetime.datetime(1977, 6, 14, 21, 33, 14), datetime.timedelta(10, 58530, 230000), None) res = self._protocol._parse_binary_values(fields, packet) self.assertEqual(exp, res) def test_read_binary_result(self): """Read MySQL binary protocol result""" def test__prepare_binary_integer(self): """Prepare an integer for the MySQL binary protocol""" # Case = Data; expected value cases = [ (-128, (struct.pack('b', -128), FieldType.TINY, 0)), (-32768, (struct.pack('h', -32768), FieldType.SHORT, 0)), (-2147483648, (struct.pack('i', -2147483648), FieldType.LONG, 0)), (-9999999999, (struct.pack('q', -9999999999), FieldType.LONGLONG, 0)), (255, (struct.pack('B', 255), FieldType.TINY, 128)), (65535, (struct.pack('H', 65535), FieldType.SHORT, 128)), (4294967295, (struct.pack('I', 4294967295), FieldType.LONG, 128)), (9999999999, (struct.pack('Q', 9999999999), FieldType.LONGLONG, 128)), ] for data, exp in cases: res = self._protocol._prepare_binary_integer(data) self.assertEqual(exp, res, "Failed preparing value '{0}'".format(data)) def test__prepare_binary_timestamp(self): """Prepare a timestamp object for the MySQL binary protocol""" cases = [ (datetime.date(1977, 6, 14), (b'\x04\xb9\x07\x06\x0e', 10)), (datetime.datetime(1977, 6, 14), (b'\x07\xb9\x07\x06\x0e\x00\x00\x00', 12)), (datetime.datetime(1977, 6, 14, 21, 33, 14), (b'\x07\xb9\x07\x06\x0e\x15\x21\x0e', 12)), (datetime.datetime(1977, 6, 14, 21, 33, 14, 345), (b'\x0b\xb9\x07\x06\x0e\x15\x21\x0e\x59\x01\x00\x00', 12)), ] for data, exp in cases: self.assertEqual(exp, self._protocol._prepare_binary_timestamp(data), "Failed preparing value '{0}'".format(data)) # Raise an error self.assertRaises(ValueError, self._protocol._prepare_binary_timestamp, 'spam') def test__prepare_binary_time(self): """Prepare a time object for the MySQL binary protocol""" cases = [ (datetime.timedelta(hours=123, minutes=45, seconds=16), (b'\x08\x00\x05\x00\x00\x00\x03\x2d\x10', 11)), (datetime.timedelta(hours=-123, minutes=45, seconds=16), (b'\x08\x01\x06\x00\x00\x00\x15\x2d\x10', 11)), (datetime.timedelta(hours=123, minutes=45, seconds=16, microseconds=345), (b'\x0c\x00\x05\x00\x00\x00\x03\x2d\x10\x59\x01\x00\x00', 11)), (datetime.timedelta(days=123, minutes=45, seconds=16), (b'\x08\x00\x7b\x00\x00\x00\x00\x2d\x10', 11)), (datetime.time(14, 53, 36), (b'\x08\x00\x00\x00\x00\x00\x0e\x35\x24', 11)), (datetime.time(14, 53, 36, 345), (b'\x0c\x00\x00\x00\x00\x00\x0e\x35\x24\x59\x01\x00\x00', 11)) ] for data, exp in cases: self.assertEqual(exp, self._protocol._prepare_binary_time(data), "Failed preparing value '{0}'".format(data)) # Raise an error self.assertRaises(ValueError, self._protocol._prepare_binary_time, 'spam') def test_make_stmt_execute(self): """Make a MySQL packet with the STMT_EXECUTE command""" statement_id = 1 self.assertRaises(errors.InterfaceError, self._protocol.make_stmt_execute, statement_id, ('ham', 'spam'), (1, 2, 3)) data = ('ham', 'spam') exp = ( b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x0f' b'\x00\x0f\x00\x03\x68\x61\x6d\x04\x73\x70\x61\x6d' ) res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) # Testing types cases = [ ('ham', b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' b'\x01\x0f\x00\x03\x68\x61\x6d'), (decimal.Decimal('3.14'), b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' b'\x01\x00\x00\x04\x33\x2e\x31\x34'), (255, b'\x01\x00\x00\x00\x80\x01\x00\x00\x00\x00\x01\x01\x80\xff'), (-128, b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x01\x00\x80'), (datetime.datetime(1977, 6, 14, 21, 20, 30), b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' b'\x01\x0c\x00\x07\xb9\x07\x06\x0e\x15\x14\x1e'), (datetime.time(14, 53, 36, 345), b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x0b\x00' b'\x0c\x00\x00\x00\x00\x00\x0e\x35\x24\x59\x01\x00\x00'), (3.14, b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x05\x00' b'\x1f\x85\xeb\x51\xb8\x1e\x09\x40'), ] for data, exp in cases: res = self._protocol.make_stmt_execute(statement_id, (data,), (1,)) self.assertEqual( exp, res, "Failed preparing statement with '{0}'".format(data)) # Testing null bitmap data = (None, None) exp = b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x03\x01' res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) data = (None, 'Ham') exp = ( b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x01\x0f\x00' b'\x03\x48\x61\x6d' ) res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) data = ('a',) * 11 exp = ( b'\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01' b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00' b'\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x01\x61\x01\x61\x01\x61' b'\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61' b'\x01\x61' ) res = self._protocol.make_stmt_execute(statement_id, data, (1,) * 11) self.assertEqual(exp, res) # Raise an error passing an unsupported object as parameter value class UnSupportedObject(object): pass data = (UnSupportedObject(), UnSupportedObject()) self.assertRaises(errors.ProgrammingError, self._protocol.make_stmt_execute, statement_id, data, (1, 2)) mysql-connector-python-1.1.6/tests/py3/__init__.py0000644001577100000120000000502712276514013021434 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import errno import socket class DummySocket(object): """Dummy socket class This class helps to test socket connection without actually making any network activity. It is a proxy class using socket.socket. """ def __init__(self, *args): self._socket = socket.socket(*args) self._server_replies = b'' self._client_sends = [] self._raise_socket_error = 0 def __getattr__(self, attr): return getattr(self._socket, attr) def raise_socket_error(self, err=errno.EPERM): self._raise_socket_error = err def recv(self, bufsize=4096, flags=0): if self._raise_socket_error: raise socket.error(self._raise_socket_error) res = self._server_replies[0:bufsize] self._server_replies = self._server_replies[bufsize:] return res def send(self, string, flags=0): if self._raise_socket_error: raise socket.error(self._raise_socket_error) self._client_sends.append(string) return len(string) def sendall(self, string, flags=0): self._client_sends.append(string) return None def add_packet(self, packet): self._server_replies += packet def add_packets(self, packets): for packet in packets: self._server_replies += packet def reset(self): self._raise_socket_error = 0 self._server_replies = b'' self._client_sends = [] mysql-connector-python-1.1.6/tests/py3/cursor.py0000644001577100000120000011161712276514013021215 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for mysql.connector.cursor specific to Python v3 """ from decimal import Decimal import time import datetime import tests from mysql.connector import (connection, cursor, errors) class MySQLCursorTests(tests.TestsCursor): def setUp(self): self.cur = cursor.MySQLCursor(connection=None) self.cnx = None def test_init(self): """MySQLCursor object init""" try: cur = cursor.MySQLCursor(connection=None) except (SyntaxError, TypeError) as err: self.fail("Failed initializing MySQLCursor; {}".format(err)) exp = { '_connection': None, '_stored_results': [], '_nextrow': (None, None), '_warnings': None, '_warning_count': 0, '_executed': None, '_executed_list': [], } for key, value in exp.items(): self.assertEqual( value, getattr(cur, key), msg="Default for '{}' did not match.".format(key)) self.assertRaises(errors.InterfaceError, cursor.MySQLCursor, connection='foo') def test__set_connection(self): """MySQLCursor object _set_connection()-method""" self.check_method(self.cur, '_set_connection') self.assertRaises(errors.InterfaceError, self.cur._set_connection, 'foo') self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur._set_connection(self.cnx) self.cur.close() def test__reset_result(self): """MySQLCursor object _reset_result()-method""" self.check_method(self.cur, '_reset_result') def reset(self): self._test = "Reset called" self.cur.reset = reset.__get__(self.cur, cursor.MySQLCursor) exp = { 'rowcount': -1, '_stored_results': [], '_nextrow': (None, None), '_warnings': None, '_warning_count': 0, '_executed': None, '_executed_list': [], } self.cur._reset_result() for key, value in exp.items(): self.assertEqual(value, getattr(self.cur, key), msg="'{}' was not reset.".format(key)) # MySQLCursor._reset_result() must call MySQLCursor.reset() self.assertEqual('Reset called', self.cur._test) # pylint: disable=E1103 def test__have_unread_result(self): """MySQLCursor object _have_unread_result()-method""" self.check_method(self.cur, '_have_unread_result') class FakeConnection(object): def __init__(self): self.unread_result = False self.cur = cursor.MySQLCursor() self.cur._connection = FakeConnection() self.cur._connection.unread_result = True self.assertTrue(self.cur._have_unread_result()) self.cur._connection.unread_result = False self.assertFalse(self.cur._have_unread_result()) def test_next(self): """MySQLCursor object next()-method""" self.check_method(self.cur, 'next') self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = cursor.MySQLCursor(self.cnx) self.assertRaises(StopIteration, self.cur.__next__) self.cur.execute("SELECT BINARY 'ham'") exp = (b'ham',) self.assertEqual(exp, next(self.cur)) self.cur.close() def test_close(self): """MySQLCursor object close()-method""" self.check_method(self.cur, 'close') self.assertEqual(False, self.cur.close(), "close() should return False with no connection") self.assertEqual(None, self.cur._connection) def test__process_params(self): """MySQLCursor object _process_params()-method""" self.check_method(self.cur, '_process_params') self.assertRaises( errors.ProgrammingError, self.cur._process_params, 'foo') self.assertRaises(errors.ProgrammingError, self.cur._process_params, ()) st_now = time.localtime() data = ( None, int(128), int(1281288), float(3.14), Decimal('3.14'), r'back\slash', 'newline\n', 'return\r', "'single'", '"double"', 'windows\032', "Strings are sexy", '\u82b1', datetime.datetime(2008, 5, 7, 20, 0o1, 23), datetime.date(2008, 5, 7), datetime.time(20, 0o3, 23), st_now, datetime.timedelta(hours=40, minutes=30, seconds=12), ) exp = ( b'NULL', b'128', b'1281288', b'3.14', b"'3.14'", b"'back\\\\slash'", b"'newline\\n'", b"'return\\r'", b"'\\'single\\''", b'\'\\"double\\"\'', b"'windows\\\x1a'", b"'Strings are sexy'", b"'\xe8\x8a\xb1'", b"'2008-05-07 20:01:23'", b"'2008-05-07'", b"'20:03:23'", b"'" + time.strftime('%Y-%m-%d %H:%M:%S', st_now).encode('ascii') + b"'", b"'40:30:12'", ) self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() self.assertEqual((), self.cur._process_params(()), "_process_params() should return a tuple") res = self.cur._process_params(data) for (i, exped) in enumerate(exp): self.assertEqual(exped, res[i]) self.cur.close() def test__process_params_dict(self): """MySQLCursor object _process_params_dict()-method""" self.check_method(self.cur, '_process_params') self.assertRaises( errors.ProgrammingError, self.cur._process_params, 'foo') self.assertRaises(errors.ProgrammingError, self.cur._process_params, ()) st_now = time.localtime() data = { 'a': None, 'b': int(128), 'c': int(1281288), 'd': float(3.14), 'e': Decimal('3.14'), 'f': 'back\slash', # pylint: disable=W1401 'g': 'newline\n', 'h': 'return\r', 'i': "'single'", 'j': '"double"', 'k': 'windows\032', 'l': str("Strings are sexy"), 'm': '\u82b1', 'n': datetime.datetime(2008, 5, 7, 20, 0o1, 23), 'o': datetime.date(2008, 5, 7), 'p': datetime.time(20, 0o3, 23), 'q': st_now, 'r': datetime.timedelta(hours=40, minutes=30, seconds=12), } exp = { b'%(a)s': b'NULL', b'%(b)s': b'128', b'%(c)s': b'1281288', b'%(d)s': b'3.14', b'%(e)s': b"'3.14'", b'%(f)s': b"'back\\\\slash'", b'%(g)s': b"'newline\\n'", b'%(h)s': b"'return\\r'", b'%(i)s': b"'\\'single\\''", b'%(j)s': b'\'\\"double\\"\'', b'%(k)s': b"'windows\\\x1a'", b'%(l)s': b"'Strings are sexy'", b'%(m)s': b"'\xe8\x8a\xb1'", b'%(n)s': b"'2008-05-07 20:01:23'", b'%(o)s': b"'2008-05-07'", b'%(p)s': b"'20:03:23'", b'%(q)s': b"'" + time.strftime('%Y-%m-%d %H:%M:%S', st_now).encode('ascii') + b"'", b'%(r)s': b"'40:30:12'", } self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() self.assertEqual({}, self.cur._process_params_dict({}), "_process_params_dict() should return a dict") self.assertEqual(exp, self.cur._process_params_dict(data)) self.cur.close() def test__fetch_warnings(self): """MySQLCursor object _fetch_warnings()-method""" self.check_method(self.cur, '_fetch_warnings') self.assertRaises(errors.InterfaceError, self.cur._fetch_warnings) config = tests.get_mysql_config() config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchone() exp = [ ('Warning', 1292, "Truncated incorrect DOUBLE value: 'a'"), ('Warning', 1292, "Truncated incorrect DOUBLE value: 'b'") ] self.assertTrue(tests.cmp_result(exp, self.cur._fetch_warnings())) self.assertEqual(len(exp), self.cur._warning_count) def test__handle_noresultset(self): """MySQLCursor object _handle_noresultset()-method""" self.check_method(self.cur, '_handle_noresultset') self.assertRaises(errors.ProgrammingError, self.cur._handle_noresultset, None) data = { 'affected_rows': 1, 'insert_id': 10, 'warning_count': 100, 'server_status': 8, } config = tests.get_mysql_config() config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur._handle_noresultset(data) self.assertEqual(data['affected_rows'], self.cur.rowcount) self.assertEqual(data['insert_id'], self.cur.lastrowid) self.assertEqual(data['warning_count'], self.cur._warning_count) def test__handle_result(self): """MySQLCursor object _handle_result()-method""" self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() self.assertRaises(errors.InterfaceError, self.cur._handle_result, None) self.assertRaises(errors.InterfaceError, self.cur._handle_result, 'spam') self.assertRaises(errors.InterfaceError, self.cur._handle_result, {'spam': 5}) cases = [ {'affected_rows': 99999, 'insert_id': 10, 'warning_count': 100, 'server_status': 8, }, {'eof': {'status_flag': 0, 'warning_count': 0}, 'columns': [('1', 8, None, None, None, None, 0, 129)] }, ] self.cur._handle_result(cases[0]) self.assertEqual(cases[0]['affected_rows'], self.cur.rowcount) self.assertFalse(self.cur._connection.unread_result) self.assertFalse(self.cur._have_unread_result()) self.cur._handle_result(cases[1]) self.assertEqual(cases[1]['columns'], self.cur.description) self.assertTrue(self.cur._connection.unread_result) self.assertTrue(self.cur._have_unread_result()) def test_execute(self): """MySQLCursor object execute()-method""" self.check_method(self.cur, 'execute') self.assertEqual(None, self.cur.execute(None, None)) config = tests.get_mysql_config() config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.assertRaises(errors.ProgrammingError, self.cur.execute, 'SELECT %s,%s,%s', ('foo', 'bar',)) self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchone() exp = [ ('Warning', 1292, "Truncated incorrect DOUBLE value: 'a'"), ('Warning', 1292, "Truncated incorrect DOUBLE value: 'b'") ] self.assertTrue(tests.cmp_result(exp, self.cur._warnings)) self.cur.execute("SELECT BINARY 'ham'") exp = [(b'ham',)] self.assertEqual(exp, self.cur.fetchall()) self.cur.close() tbl = 'myconnpy_cursor' self._test_execute_setup(self.cnx, tbl) stmt_insert = "INSERT INTO {0} (col1,col2) VALUES (%s,%s)".format(tbl) self.cur = self.cnx.cursor() res = self.cur.execute(stmt_insert, (1, 100)) self.assertEqual(None, res, "Return value of execute() is wrong.") stmt_select = "SELECT col1,col2 FROM {0} ORDER BY col1".format(tbl) self.cur.execute(stmt_select) self.assertEqual([(1, '100')], self.cur.fetchall(), "Insert test failed") data = {'id': 2} stmt = "SELECT * FROM {0} WHERE col1 <= %(id)s".format(tbl) self.cur.execute(stmt, data) self.assertEqual([(1, '100')], self.cur.fetchall()) self._test_execute_cleanup(self.cnx, tbl) self.cur.close() def test_executemany(self): """MySQLCursor object executemany()-method""" self.check_method(self.cur, 'executemany') self.assertEqual(None, self.cur.executemany(None, [])) config = tests.get_mysql_config() config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'foo', None) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'foo', 'foo') self.assertEqual(None, self.cur.executemany('foo', [])) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'foo', ['foo']) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'SELECT %s', [('foo',), 'foo']) self.assertRaises(errors.ProgrammingError, self.cur.executemany, "INSERT INTO t1 1 %s", [(1,), (2,)]) self.cur.executemany("SELECT SHA1(%s)", [('foo',), ('bar',)]) self.assertEqual(None, self.cur.fetchone()) self.cur.close() tbl = 'myconnpy_cursor' self._test_execute_setup(self.cnx, tbl) stmt_insert = "INSERT INTO {0} (col1,col2) VALUES (%s,%s)".format(tbl) stmt_select = "SELECT col1,col2 FROM {0} ORDER BY col1".format(tbl) self.cur = self.cnx.cursor() res = self.cur.executemany(stmt_insert, [(1, 100), (2, 200), (3, 300)]) self.assertEqual(3, self.cur.rowcount) res = self.cur.executemany("SELECT %s", [('f',), ('o',), ('o',)]) self.assertEqual(3, self.cur.rowcount) data = [{'id': 2}, {'id': 3}] stmt = "SELECT * FROM {0} WHERE col1 <= %(id)s".format(tbl) self.cur.executemany(stmt, data) self.assertEqual(5, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(1, '100'), (2, '200'), (3, '300')], self.cur.fetchall(), "Multi insert test failed") data = [{'id': 2}, {'id': 3}] stmt = "DELETE FROM {0} WHERE col1 = %(id)s".format(tbl) self.cur.executemany(stmt, data) self.assertEqual(2, self.cur.rowcount) stmt = "TRUNCATE TABLE {0}".format(tbl) self.cur.execute(stmt) stmt = ( "/*comment*/INSERT/*comment*/INTO/*comment*/{0}(col1,col2)VALUES" "/*comment*/(%s,%s/*comment*/)/*comment()*/ON DUPLICATE KEY UPDATE" " col1 = VALUES(col1)" ).format(tbl) self.cur.executemany(stmt, [(4, 100), (5, 200), (6, 300)]) self.assertEqual(3, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(4, '100'), (5, '200'), (6, '300')], self.cur.fetchall(), "Multi insert test failed") stmt = "TRUNCATE TABLE {0}".format(tbl) self.cur.execute(stmt) stmt = ( "INSERT INTO/*comment*/{0}(col1,col2)VALUES" "/*comment*/(%s,'/*100*/')/*comment()*/ON DUPLICATE KEY UPDATE " "col1 = VALUES(col1)" ).format(tbl) self.cur.executemany(stmt, [(4,), (5,)]) self.assertEqual(2, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(4, '/*100*/'), (5, '/*100*/')], self.cur.fetchall(), "Multi insert test failed") self._test_execute_cleanup(self.cnx, tbl) self.cur.close() def test_fetchwarnings(self): """MySQLCursor object fetchwarnings()-method""" self.check_method(self.cur, 'fetchwarnings') self.assertEqual( None, self.cur.fetchwarnings(), "There should be no warnings after initiating cursor.") exp = ['A warning'] self.cur._warnings = exp self.cur._warning_count = len(self.cur._warnings) self.assertEqual(exp, self.cur.fetchwarnings()) self.cur.close() def test_stored_results(self): """MySQLCursor object stored_results()-method""" self.check_method(self.cur, 'stored_results') self.assertEqual([], self.cur._stored_results) self.assertTrue(hasattr(self.cur.stored_results(), '__iter__')) self.cur._stored_results.append('abc') self.assertEqual('abc', next(self.cur.stored_results())) try: _ = next(self.cur.stored_results()) except StopIteration: pass except: self.fail("StopIteration not raised") def _test_callproc_setup(self, cnx): self._test_callproc_cleanup(cnx) stmt_create1 = ( "CREATE PROCEDURE myconnpy_sp_1 " "(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) " "BEGIN SET pProd := pFac1 * pFac2; END;") stmt_create2 = ( "CREATE PROCEDURE myconnpy_sp_2 " "(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) " "BEGIN SELECT 'abc'; SELECT 'def'; SET pProd := pFac1 * pFac2; " "END;") stmt_create3 = ( "CREATE PROCEDURE myconnpy_sp_3" "(IN pStr1 VARCHAR(20), IN pStr2 VARCHAR(20), " "OUT pConCat VARCHAR(100)) " "BEGIN SET pConCat := CONCAT(pStr1, pStr2); END;") try: cur = cnx.cursor() cur.execute(stmt_create1) cur.execute(stmt_create2) cur.execute(stmt_create3) except errors.Error as err: self.fail("Failed setting up test stored routine; {0}".format(err)) cur.close() def _test_callproc_cleanup(self, cnx): sp_names = ('myconnpy_sp_1', 'myconnpy_sp_2', 'myconnpy_sp_3') stmt_drop = "DROP PROCEDURE IF EXISTS {procname}" try: cur = cnx.cursor() for sp_name in sp_names: cur.execute(stmt_drop.format(procname=sp_name)) except errors.Error as err: self.fail( "Failed cleaning up test stored routine; {0}".format(err)) cur.close() def test_callproc(self): """MySQLCursor object callproc()-method""" self.check_method(self.cur, 'callproc') self.assertRaises(ValueError, self.cur.callproc, None) self.assertRaises(ValueError, self.cur.callproc, 'sp1', None) config = tests.get_mysql_config() config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self._test_callproc_setup(self.cnx) self.cur = self.cnx.cursor() exp = (5, 4, 20) result = self.cur.callproc('myconnpy_sp_1', (exp[0], exp[1], 0)) self.assertEqual([], self.cur._stored_results) self.assertEqual(exp, result) exp = (6, 5, 30) result = self.cur.callproc('myconnpy_sp_2', (exp[0], exp[1], 0)) self.assertTrue(isinstance(self.cur._stored_results, list)) self.assertEqual(exp, result) exp_results = [ ('abc',), ('def',) ] for result, exp in zip(self.cur.stored_results(), iter(exp_results)): self.assertEqual(exp, result.fetchone()) exp = ('ham', 'spam', 'hamspam') result = self.cur.callproc('myconnpy_sp_3', (exp[0], exp[1], 0)) self.assertTrue(isinstance(self.cur._stored_results, list)) self.assertEqual(exp, result) self._test_callproc_cleanup(self.cnx) self.cur.close() def test_fetchone(self): """MySQLCursor object fetchone()-method""" self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() self.cur.execute("SELECT BINARY 'ham'") exp = (b'ham',) self.assertEqual(exp, self.cur.fetchone()) self.assertEqual(None, self.cur.fetchone()) self.cur.close() def test_fetchmany(self): """MySQLCursor object fetchmany()-method""" self.check_method(self.cur, 'fetchmany') self.assertEqual([], self.cur.fetchmany()) self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) tbl = 'myconnpy_fetch' self._test_execute_setup(self.cnx, tbl) stmt_insert = ( "INSERT INTO {table} (col1,col2) " "VALUES (%s,%s)".format(table=tbl)) stmt_select = ( "SELECT col1,col2 FROM {table} " "ORDER BY col1 DESC".format(table=tbl)) self.cur = self.cnx.cursor() nrrows = 10 data = [(i, str(i * 100)) for i in range(0, nrrows)] self.cur.executemany(stmt_insert, data) self.cur.execute(stmt_select) exp = [(9, '900'), (8, '800'), (7, '700'), (6, '600')] rows = self.cur.fetchmany(4) self.assertTrue(tests.cmp_result(exp, rows), "Fetching first 4 rows test failed.") exp = [(5, '500'), (4, '400'), (3, '300')] rows = self.cur.fetchmany(3) self.assertTrue(tests.cmp_result(exp, rows), "Fetching next 3 rows test failed.") exp = [(2, '200'), (1, '100'), (0, '0')] rows = self.cur.fetchmany(3) self.assertTrue(tests.cmp_result(exp, rows), "Fetching next 3 rows test failed.") self.assertEqual([], self.cur.fetchmany()) self._test_execute_cleanup(self.cnx, tbl) self.cur.close() def test_fetchall(self): """MySQLCursor object fetchall()-method""" self.check_method(self.cur, 'fetchall') self.assertRaises(errors.InterfaceError, self.cur.fetchall) self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) tbl = 'myconnpy_fetch' self._test_execute_setup(self.cnx, tbl) stmt_insert = ( "INSERT INTO {table} (col1,col2) " "VALUES (%s,%s)".format(table=tbl)) stmt_select = ( "SELECT col1,col2 FROM {table} " "ORDER BY col1 ASC".format(table=tbl)) self.cur = self.cnx.cursor() self.cur.execute("SELECT * FROM {table}".format(table=tbl)) self.assertEqual([], self.cur.fetchall(), "fetchall() with empty result should return []") nrrows = 10 data = [(i, str(i * 100)) for i in range(0, nrrows)] self.cur.executemany(stmt_insert, data) self.cur.execute(stmt_select) self.assertTrue(tests.cmp_result(data, self.cur.fetchall()), "Fetching all rows failed.") self.assertEqual(None, self.cur.fetchone()) self._test_execute_cleanup(self.cnx, tbl) self.cur.close() def test_raise_on_warning(self): self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cnx.raise_on_warnings = True self.cur = self.cnx.cursor() try: self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchall() except errors.Error: pass else: self.fail("Did not get exception while raising warnings.") def test__str__(self): """MySQLCursor object __str__()-method""" self.assertEqual("MySQLCursor: (Nothing executed yet)", self.cur.__str__()) self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() self.cur.execute("SELECT VERSION()") self.cur.fetchone() self.assertEqual("MySQLCursor: SELECT VERSION()", self.cur.__str__()) stmt = "SELECT VERSION(),USER(),CURRENT_TIME(),NOW(),SHA1('myconnpy')" self.cur.execute(stmt) self.cur.fetchone() self.assertEqual("MySQLCursor: {0}..".format(stmt[:30]), self.cur.__str__()) self.cur.close() def test_column_names(self): self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() stmt = "SELECT NOW() as now, 'The time' as label, 123 FROM dual" exp = ('now', 'label', '123') self.cur.execute(stmt) self.cur.fetchone() self.assertEqual(exp, self.cur.column_names) self.cur.close() def test_statement(self): self.cur = cursor.MySQLCursor() exp = 'SELECT * FROM ham' self.cur._executed = exp self.assertEqual(exp, self.cur.statement) self.cur._executed = ' ' + exp + ' ' self.assertEqual(exp, self.cur.statement) self.cur._executed = b'SELECT * FROM ham' self.assertEqual(exp, self.cur.statement) def test_with_rows(self): self.cur = cursor.MySQLCursor() self.assertFalse(self.cur.with_rows) self.cur._description = ('ham', 'spam') self.assertTrue(self.cur.with_rows) class MySQLCursorBufferedTests(tests.TestsCursor): def setUp(self): self.cur = cursor.MySQLCursorBuffered(connection=None) self.cnx = None def tearDown(self): if self.cnx: self.cnx.close() def test_init(self): """MySQLCursorBuffered object init""" try: cur = cursor.MySQLCursorBuffered(connection=None) except (SyntaxError, TypeError) as err: self.fail("Failed initializing MySQLCursorBuffered; {}".format( err)) else: cur.close() self.assertRaises(errors.InterfaceError, cursor.MySQLCursorBuffered, connection='foo') def test__next_row(self): """MySQLCursorBuffered object _next_row-attribute""" self.check_attr(self.cur, '_next_row', 0) def test__rows(self): """MySQLCursorBuffered object _rows-attribute""" self.check_attr(self.cur, '_rows', None) def test_execute(self): """MySQLCursorBuffered object execute()-method """ self.check_method(self.cur, 'execute') self.assertEqual(None, self.cur.execute(None, None)) config = tests.get_mysql_config() config['buffered'] = True config['get_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.assertEqual(True, isinstance(self.cur, cursor.MySQLCursorBuffered)) self.cur.execute("SELECT 1") self.assertEqual([(b'1',)], self.cur._rows) def test_raise_on_warning(self): config = tests.get_mysql_config() config['buffered'] = True config['raise_on_warnings'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() try: self.cur.execute("SELECT 'a' + 'b'") except errors.Error: pass else: self.fail("Did not get exception while raising warnings.") def test_with_rows(self): cur = cursor.MySQLCursorBuffered() self.assertFalse(cur.with_rows) cur._rows = [('ham',)] self.assertTrue(cur.with_rows) class MySQLCursorRawTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() def tearDown(self): self.cur.close() self.cnx.close() def test_fetchone(self): self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = (b'1', b'string', b'2010-12-31', b'2.5') self.assertEqual(exp, self.cur.fetchone()) class MySQLCursorRawBufferedTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True config['buffered'] = True self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() def tearDown(self): self.cur.close() self.cnx.close() def test_fetchone(self): self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = (b'1', b'string', b'2010-12-31', b'2.5') self.assertEqual(exp, self.cur.fetchone()) def test_fetchall(self): self.check_method(self.cur, 'fetchall') self.assertRaises(errors.InterfaceError, self.cur.fetchall) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = [(b'1', b'string', b'2010-12-31', b'2.5')] self.assertEqual(exp, self.cur.fetchall()) class MySQLCursorPreparedTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True config['buffered'] = True self.cnx = connection.MySQLConnection(**config) def test_callproc(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertRaises(errors.NotSupportedError, cur.callproc) def test_close(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) cur.close() self.assertEqual(None, cur._prepared) def test_fetch_row(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertEqual(None, cur._fetch_row()) cur._description = [('c1', 5, None, None, None, None, 1, 128)] # Monkey patch the get_row method of the connection for testing def _get_row(binary, columns): # pylint: disable=W0613 try: row = self.cnx._test_fetch_row[0] self.cnx._test_fetch_row = self.cnx._test_fetch_row[1:] except IndexError: return None return row self.cnx.get_row = _get_row eof_info = {'status_flag': 0, 'warning_count': 2} self.cnx.unread_result = True self.cnx._test_fetch_row = [(b'1', None), (None, eof_info)] self.assertEqual(b'1', cur._fetch_row()) self.assertEqual((None, None), cur._nextrow) self.assertEqual(eof_info['warning_count'], cur._warning_count) cur._reset_result() self.cnx.unread_result = True self.cnx._test_fetch_row = [(None, eof_info)] self.assertEqual(None, cur._fetch_row()) self.assertEqual((None, None), cur._nextrow) self.assertEqual(eof_info['warning_count'], cur._warning_count) def test_execute(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) cur2 = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) # No 1 stmt = "SELECT (? * 2) AS c1" cur.execute(stmt, (5,)) self.assertEqual(stmt, cur._executed) exp = { 'num_params': 1, 'statement_id': 1, 'parameters': [('?', 253, None, None, None, None, 1, 128)], 'warning_count': 0, 'num_columns': 1, 'columns': [('c1', 5, None, None, None, None, 1, 128)] } self.assertEqual(exp, cur._prepared) # No 2 stmt = "SELECT (? * 3) AS c2" # first, execute should fail, because unread results of No 1 self.assertRaises(errors.InternalError, cur2.execute, stmt) cur.fetchall() # We call with wrong number of values for paramaters self.assertRaises(errors.ProgrammingError, cur2.execute, stmt, (1, 3)) cur2.execute(stmt, (5,)) self.assertEqual(stmt, cur2._executed) exp = { 'num_params': 1, 'statement_id': 2, 'parameters': [('?', 253, None, None, None, None, 1, 128)], 'warning_count': 0, 'num_columns': 1, 'columns': [('c2', 5, None, None, None, None, 1, 128)] } self.assertEqual(exp, cur2._prepared) self.assertEqual([(15,)], cur2.fetchall()) # No 3 data = (3, 4) exp = [(5.0,)] stmt = "SELECT SQRT(POW(?, 2) + POW(?, 2)) AS hypotenuse" cur.execute(stmt, data) self.assertEqual(3, cur._prepared['statement_id']) self.assertEqual(exp, cur.fetchall()) # Execute the already prepared statement data = (4, 5) exp = (6.4031242374328485,) cur.execute(stmt, data) self.assertEqual(3, cur._prepared['statement_id']) self.assertEqual(exp, cur.fetchone()) def test_executemany(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertEqual(None, cur.executemany(None, [])) self.assertRaises(errors.InterfaceError, cur.executemany, 'ham', None) self.assertRaises(errors.ProgrammingError, cur.executemany, 'ham', 'ham') self.assertEqual(None, cur.executemany('ham', [])) self.assertRaises(errors.ProgrammingError, cur.executemany, 'ham', ['ham']) cur.executemany("SELECT SHA1(%s)", [('ham',), ('bar',)]) self.assertEqual(None, cur.fetchone()) cur.close() cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) tbl = 'myconnpy_cursor' self._test_execute_setup(self.cnx, tbl) stmt_insert = "INSERT INTO {table} (col1,col2) VALUES (%s, %s)".format( table=tbl) stmt_select = "SELECT col1,col2 FROM {table} ORDER BY col1".format( table=tbl) cur.executemany(stmt_insert, [(1, 100), (2, 200), (3, 300)]) self.assertEqual(3, cur.rowcount) cur.executemany("SELECT %s", [('h',), ('a',), ('m',)]) self.assertEqual(3, cur.rowcount) cur.execute(stmt_select) self.assertEqual([(1, b'100'), (2, b'200'), (3, b'300')], cur.fetchall(), "Multi insert test failed") data = [(2,), (3,)] stmt = "DELETE FROM {table} WHERE col1 = %s".format(table=tbl) cur.executemany(stmt, data) self.assertEqual(2, cur.rowcount) self._test_execute_cleanup(self.cnx, tbl) cur.close() def test_fetchone(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _fetch_row(): try: row = cur._test_fetch_row[0] cur._test_fetch_row = cur._test_fetch_row[1:] except IndexError: return None return row cur._fetch_row = _fetch_row cur._test_fetch_row = [(b'ham',)] self.assertEqual((b'ham',), cur.fetchone()) self.assertEqual(None, cur.fetchone()) def test_fetchmany(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _fetch_row(): try: row = cur._test_fetch_row[0] cur._test_fetch_row = cur._test_fetch_row[1:] except IndexError: return None return row cur._fetch_row = _fetch_row rows = [(1, b'100'), (2, b'200'), (3, b'300')] cur._test_fetch_row = rows self.cnx.unread_result = True self.assertEqual(rows[0:2], cur.fetchmany(2)) self.assertEqual([rows[2]], cur.fetchmany(2)) self.assertEqual([], cur.fetchmany()) def test_fetchall(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _get_rows(binary, columns): # pylint: disable=W0613 self.unread_result = False # pylint: disable=W0201 return ( self.cnx._test_fetch_row, {'status_flag': 0, 'warning_count': 3} ) self.cnx.get_rows = _get_rows rows = [(1, 100), (2, 200), (3, 300)] self.cnx._test_fetch_row = rows self.cnx.unread_result = True self.assertEqual(rows, cur.fetchall()) self.assertEqual(len(rows), cur._rowcount) self.assertEqual(3, cur._warning_count) self.assertRaises(errors.InterfaceError, cur.fetchall) mysql-connector-python-1.1.6/tests/py3/test_network.py0000644001577100000120000004221612276514013022426 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.network """ import os import socket import logging from collections import deque import unittest import tests from mysql.connector import (network, errors, constants) LOGGER = logging.getLogger(tests.LOGGER_NAME) class NetworkTests(tests.MySQLConnectorTests): """Testing mysql.connector.network functions""" def test__prepare_packets(self): """Prepare packets for sending""" data = (b'abcdefghijklmn', 1) exp = [b'\x0e\x00\x00\x01abcdefghijklmn'] self.assertEqual(exp, network._prepare_packets(*(data))) data = (b'a' * (constants.MAX_PACKET_LENGTH + 1000), 2) exp = [ b'\xff\xff\xff\x02' + (b'a' * constants.MAX_PACKET_LENGTH), b'\xe8\x03\x00\x03' + (b'a' * 1000) ] self.assertEqual(exp, network._prepare_packets(*(data))) class BaseMySQLSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network.BaseMySQLSocket""" def setUp(self): config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] self.cnx = network.BaseMySQLSocket() def tearDown(self): try: self.cnx.close_connection() except: pass def _get_socket(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) LOGGER.debug("Get socket for {host}:{port}".format( host=self._host, port=self._port)) sock.connect((self._host, self._port)) return sock def test_init(self): """MySQLSocket initialization""" exp = { 'sock': None, '_connection_timeout': None, '_packet_queue': deque(), 'recvsize': 1024 * 8, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_next_packet_number(self): """Test packet number property""" self.assertEqual(0, self.cnx.next_packet_number) self.assertEqual(0, self.cnx._packet_number) self.assertEqual(1, self.cnx.next_packet_number) self.assertEqual(1, self.cnx._packet_number) self.cnx._packet_number = 255 self.assertEqual(0, self.cnx.next_packet_number) def test_open_connection(self): """Opening a connection""" self.assertRaises(NotImplementedError, self.cnx.open_connection) def test_get_address(self): """Get the address of a connection""" self.assertRaises(NotImplementedError, self.cnx.get_address) def test_close_connection(self): """Closing a connection""" self.cnx.close_connection() self.assertEqual(None, self.cnx.sock) def test_send_plain(self): """Send plain data through the socket""" data = b'asddfasdfasdf' self.assertRaises(errors.OperationalError, self.cnx.send_plain, data, 0) self.cnx.sock = tests.DummySocket() data = [ (b'\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1), (b'\x03\x53\x45\x4c\x45\x43\x54\x20\x22' + (b'\x61' * (constants.MAX_PACKET_LENGTH + 1000)) + b'\x22', 2)] self.assertRaises(Exception, self.cnx.send_plain, None, None) for value in data: exp = network._prepare_packets(*value) try: self.cnx.send_plain(*value) except errors.Error as err: self.fail("Failed sending pktnr {}: {}".format(value[1], str(err))) self.assertEqual(exp, self.cnx.sock._client_sends) self.cnx.sock.reset() def test_send_compressed(self): """Send compressed data through the socket""" data = b'asddfasdfasdf' self.assertRaises(errors.OperationalError, self.cnx.send_compressed, data, 0) self.cnx.sock = tests.DummySocket() self.assertRaises(Exception, self.cnx.send_compressed, None, None) # Small packet data = (b'\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1) exp = [b'\x11\x00\x00\x00\x00\x00\x00\r\x00\x00\x01\x03SELECT "abc"'] try: self.cnx.send_compressed(*data) except errors.Error as err: self.fail("Failed sending pktnr {}: {}".format(data[1], err)) self.assertEqual(exp, self.cnx.sock._client_sends) self.cnx.sock.reset() # Slightly bigger packet (not getting compressed) data = (b'\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1) exp = (24, b'\x11\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x01\x03' b'\x53\x45\x4c\x45\x43\x54\x20\x22') try: self.cnx.send_compressed(*data) except errors.Error as err: self.fail("Failed sending pktnr {}: {}".format(data[1], str(err))) received = self.cnx.sock._client_sends[0] self.assertEqual(exp, (len(received), received[:20])) self.cnx.sock.reset() # Big packet data = (b'\x03\x53\x45\x4c\x45\x43\x54\x20\x22' + b'\x61' * (constants.MAX_PACKET_LENGTH + 1000) + b'\x22', 2) exp = [ (63, b'\x38\x00\x00\x00\x00\x40\x00\x78\x9c\xed\xc1\x31' b'\x0d\x00\x20\x0c\x00\xb0\x04\x8c'), (16322, b'\xbb\x3f\x00\x01\xf9\xc3\xff\x78\x9c\xec\xc1\x81' b'\x00\x00\x00\x00\x80\x20\xd6\xfd')] try: self.cnx.send_compressed(*data) except errors.Error as err: self.fail("Failed sending pktnr {}: {}".format(data[1], str(err))) received = [(len(r), r[:20]) for r in self.cnx.sock._client_sends] self.assertEqual(exp, received) self.cnx.sock.reset() def test_recv_plain(self): """Receive data from the socket""" self.cnx.sock = tests.DummySocket() def get_address(): return 'dummy' self.cnx.get_address = get_address # Receive a packet which is not 4 bytes long self.cnx.sock.add_packet(b'\01\01\01') self.assertRaises(errors.InterfaceError, self.cnx.recv_plain) # Receive the header of a packet, but nothing more self.cnx.sock.add_packet(b'\01\00\00\00') self.assertRaises(errors.InterfaceError, self.cnx.recv_plain) # Socket fails to receive and produces an error self.cnx.sock.raise_socket_error() self.assertRaises(errors.OperationalError, self.cnx.recv_plain) # Receive packets after a query, SELECT "Ham" exp = [ b'\x01\x00\x00\x01\x01', b'\x19\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x03\x48\x61\x6d\x00' b'\x0c\x21\x00\x09\x00\x00\x00\xfd\x01\x00\x1f\x00\x00', b'\x05\x00\x00\x03\xfe\x00\x00\x02\x00', b'\x04\x00\x00\x04\x03\x48\x61\x6d', b'\x05\x00\x00\x05\xfe\x00\x00\x02\x00', ] self.cnx.sock.reset() self.cnx.sock.add_packets(exp) length_exp = len(exp) result = [] packet = self.cnx.recv_plain() while packet: result.append(packet) if length_exp == len(result): break packet = self.cnx.recv_plain() self.assertEqual(exp, result) def test_recv_compressed(self): """Receive compressed data from the socket""" self.cnx.sock = tests.DummySocket() def get_address(): return 'dummy' self.cnx.get_address = get_address # Receive a packet which is not 7 bytes long self.cnx.sock.add_packet(b'\01\01\01\01\01\01') self.assertRaises(errors.InterfaceError, self.cnx.recv_compressed) # Receive the header of a packet, but nothing more self.cnx.sock.add_packet(b'\01\00\00\00\00\00\00') self.assertRaises(errors.InterfaceError, self.cnx.recv_compressed) # Socket fails to receive and produces an error self.cnx.sock.raise_socket_error() self.assertRaises(errors.OperationalError, self.cnx.recv_compressed) # Receive result of query SELECT REPEAT('a',1*1024*1024), 'XYZ' packets = ( b'\x80\x00\x00\x01\x00\x40\x00\x78\x9c\xed\xcb\xbd\x0a\x81\x01' b'\x14\xc7\xe1\xff\xeb\xa5\x28\x83\x4d\x26\x99\x7c\x44\x21\x37' b'\x60\xb0\x4b\x06\x6c\x0a\xd7\xe3\x7a\x15\x79\xc9\xec\x0a\x9e' b'\x67\x38\x9d\xd3\xaf\x53\x24\x45\x6d\x96\xd4\xca\xcb\xf5\x96' b'\xa4\xbb\xdb\x6c\x37\xeb\xfd\x68\x78\x1e\x4e\x17\x93\xc5\x7c' b'\xb9\xfa\x8e\x71\xda\x83\xaa\xde\xf3\x28\xd2\x4f\x7a\x49\xf9' b'\x7b\x28\x0f\xc7\xd3\x27\xb6\xaa\xfd\xf9\x8d\x8d\xa4\xfe\xaa' b'\xae\x34\xd3\x69\x3c\x93\xce\x19\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xeb\x0d\xe7\xa5\x29\xb8', b'\x05\x04\x00\x02\x68\xc0\x0f\x78\x9c\xed\xc1\x31\x01\x00\x00' b'\x08\x03\xa0\xc3\x92\xea\xb7\xfe\x25\x8c\x60\x01\x20\x01' + b'\x00' * 999 + b'\xe0\x53\x3d\x7b\x0a\x29\x40\x7b' ) exp = [ b'\x01\x00\x00\x01\x02', b'\x2d\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x17\x52\x45\x50' b'\x45\x41\x54\x28\x27\x61\x27\x2c\x31\x2a\x31\x30\x32\x34\x2a' b'\x31\x30\x32\x34\x29\x00\x0c\x21\x00\x00\x00\x90\x00\xfa\x01' b'\x00\x1f\x00\x00', b'\x19\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x03\x58\x59\x5a' b'\x00\x0c\x21\x00\x09\x00\x00\x00\xfd\x01\x00\x1f\x00\x00', b'\x05\x00\x00\x04\xfe\x00\x00\x00\x00', b'\x08\x00\x10\x05\xfd\x00\x00\x10' + b'\x61' * 1 * 1024 * 1024 + b'\x03\x58\x59\x5a' ] self.cnx.sock.reset() self.cnx.sock.add_packets(packets) length_exp = len(exp) packet = self.cnx.recv_compressed() counter = 0 while packet and counter < length_exp: self.assertEqual(exp[counter], packet) packet = self.cnx.recv_compressed() counter += 1 def test_set_connection_timeout(self): """Set the connection timeout""" exp = 5 self.cnx.set_connection_timeout(exp) self.assertEqual(exp, self.cnx._connection_timeout) @unittest.skipIf(os.name == 'nt', "Skip UNIX Socket tests on Windows") class MySQLUnixSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network.MySQLUnixSocket""" def setUp(self): config = tests.get_mysql_config() self._unix_socket = config['unix_socket'] self.cnx = network.MySQLUnixSocket(unix_socket=config['unix_socket']) def tearDown(self): try: self.cnx.close_connection() except: pass def test_init(self): """MySQLUnixSocket initialization""" exp = { 'unix_socket': self._unix_socket, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_get_address(self): """Get path to the Unix socket""" exp = self._unix_socket self.assertEqual(exp, self.cnx.get_address()) def test_open_connection(self): """Open a connection using a Unix socket""" if os.name == 'nt': self.assertRaises(errors.InterfaceError, self.cnx.open_connection) else: try: self.cnx.open_connection() except errors.Error as err: self.fail(str(err)) @unittest.skipIf(not tests.SSL_AVAILABLE, "Could not test switch to SSL. Make sure Python supports " "SSL.") def test_switch_to_ssl(self): """Switch the socket to use SSL""" args = { 'ca': os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem'), 'cert': os.path.join(tests.SSL_DIR, 'tests_client_cert.pem'), 'key': os.path.join(tests.SSL_DIR, 'tests_client_key.pem'), } self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) # Handshake failure sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(4) sock.connect(self._unix_socket) self.cnx.sock = sock self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) class MySQLTCPSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network..MySQLTCPSocket""" def setUp(self): config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] self.cnx = network.MySQLTCPSocket(host=self._host, port=self._port) def tearDown(self): try: self.cnx.close_connection() except: pass def test_init(self): """MySQLTCPSocket initialization""" exp = { 'server_host': self._host, 'server_port': self._port, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_get_address(self): """Get TCP/IP address""" exp = "%s:%s" % (self._host, self._port) self.assertEqual(exp, self.cnx.get_address()) @unittest.skipIf(tests.IPV6_AVAILABLE, "Testing IPv6, not testing IPv4") def test_open_connection__ipv4(self): """Open a connection using TCP""" try: self.cnx.open_connection() except errors.Error as err: self.fail(str(err)) config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] cases = [ # Address, Expected Family, Should Raise, Force IPv6 (tests.get_mysql_config()['host'], socket.AF_INET, False, False), ] for case in cases: self._test_open_connection(*case) @unittest.skipIf(not tests.IPV6_AVAILABLE, "IPv6 testing disabled") def test_open_connection__ipv6(self): """Open a connection using TCP""" config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] cases = [ # Address, Expected Family, Should Raise, Force IPv6 ('::1', socket.AF_INET6, False, False), ('2001::14:06:77', socket.AF_INET6, True, False), ('xx:00:xx', socket.AF_INET6, True, False), ] for case in cases: self._test_open_connection(*case) def _test_open_connection(self, addr, family, should_raise, force): try: sock = network.MySQLTCPSocket(host=addr, port=self._port, force_ipv6=force) sock.set_connection_timeout(1) sock.open_connection() except (errors.InterfaceError, socket.error): if not should_raise: self.fail('{0} incorrectly raised socket.error'.format( addr)) else: if should_raise: self.fail('{0} should have raised socket.error'.format( addr)) else: self.assertEqual(family, sock._family, "Family for {0} did not match".format( addr, family, sock._family)) sock.close_connection() @unittest.skipIf(not tests.SSL_AVAILABLE, "Could not test switch to SSL. Make sure Python supports " "SSL.") def test_switch_to_ssl(self): """Switch the socket to use SSL""" args = { 'ca': os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem'), 'cert': os.path.join(tests.SSL_DIR, 'tests_client_cert.pem'), 'key': os.path.join(tests.SSL_DIR, 'tests_client_key.pem'), } self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) # Handshake failure (family, socktype, proto, _, sockaddr) = socket.getaddrinfo(self._host, self._port)[0] sock = socket.socket(family, socktype, proto) sock.settimeout(4) sock.connect(sockaddr) self.cnx.sock = sock self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) mysql-connector-python-1.1.6/tests/py3/test_conversion.py0000644001577100000120000004046012276514013023121 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.conversion """ from decimal import Decimal import datetime import time import tests from mysql.connector import conversion, constants class MySQLConverterBaseTests(tests.MySQLConnectorTests): def test_init(self): cnv = conversion.MySQLConverterBase() self.assertEqual('utf8', cnv.charset) self.assertEqual(True, cnv.use_unicode) def test_init2(self): cnv = conversion.MySQLConverterBase(charset='latin1', use_unicode=False) self.assertEqual('latin1', cnv.charset) self.assertEqual(False, cnv.use_unicode) def test_set_charset(self): cnv = conversion.MySQLConverterBase() cnv.set_charset('latin2') self.assertEqual('latin2', cnv.charset) def test_set_useunicode(self): cnv = conversion.MySQLConverterBase() cnv.set_unicode(False) self.assertEqual(False, cnv.use_unicode) def test_to_mysql(self): cnv = conversion.MySQLConverterBase() self.assertEqual('a value', cnv.to_mysql('a value')) def test_to_python(self): cnv = conversion.MySQLConverterBase() self.assertEqual('a value', cnv.to_python('nevermind', 'a value')) def test_escape(self): cnv = conversion.MySQLConverterBase() self.assertEqual("'a value'", cnv.escape("'a value'")) def test_quote(self): cnv = conversion.MySQLConverterBase() self.assertEqual("'a value'", cnv.escape("'a value'")) class MySQLConverterTests(tests.MySQLConnectorTests): def setUp(self): self.cnv = conversion.MySQLConverter() def tearDown(self): pass def test_init(self): pass def test_escape(self): """Making strings ready for MySQL operations""" data = ( None, # should stay the same int(128), # should stay the same int(1281288), # should stay the same float(3.14), # should stay the same Decimal('3.14'), # should stay a Decimal r'back\slash', 'newline\n', 'return\r', "'single'", '"double"', 'windows\032', ) exp = ( None, 128, 1281288, float(3.14), Decimal("3.14"), 'back\\\\slash', 'newline\\n', 'return\\r', "\\'single\\'", '\\"double\\"', 'windows\\\x1a' ) res = tuple([self.cnv.escape(v) for v in data]) self.failUnless(res, exp) def test_quote(self): """Quote values making them ready for MySQL operations.""" data = [ None, int(128), int(1281288), float(3.14), Decimal('3.14'), b'string A', b"string B", ] exp = ( b'NULL', b'128', b'1281288', b'3.14', b'3.14', b"'string A'", b"'string B'", ) res = tuple([self.cnv.quote(value) for value in data]) self.failUnlessEqual(res, exp) def test_to_mysql(self): """Convert Python types to MySQL types using helper method""" st_now = time.localtime() data = ( 128, # int 1281288, # long float(3.14), # float 'Strings are sexy', r'\u82b1', None, datetime.datetime(2008, 5, 7, 20, 0o1, 23), datetime.date(2008, 5, 7), datetime.time(20, 0o3, 23), st_now, datetime.timedelta(hours=40, minutes=30, seconds=12), Decimal('3.14'), ) exp = ( data[0], data[1], data[2], self.cnv._str_to_mysql(data[3]), self.cnv._str_to_mysql(data[4]), None, b'2008-05-07 20:01:23', b'2008-05-07', b'20:03:23', time.strftime('%Y-%m-%d %H:%M:%S', st_now).encode('ascii'), b'40:30:12', b'3.14', ) res = tuple([self.cnv.to_mysql(value) for value in data]) self.failUnlessEqual(res, exp) def test__str_to_mysql(self): """A Python string becomes bytes.""" data = 'This is a string' exp = data.encode() res = self.cnv._str_to_mysql(data) self.assertEqual(exp, res) def test__bytes_to_mysql(self): """A Python bytes stays bytes.""" data = b'This is a bytes' exp = data res = self.cnv._bytes_to_mysql(data) self.assertEqual(exp, res) def test__nonetype_to_mysql(self): """Python None stays None for MySQL.""" data = None res = self.cnv._nonetype_to_mysql(data) self.assertEqual(data, res) def test__datetime_to_mysql(self): """A datetime.datetime becomes formatted like Y-m-d H:M:S[.f]""" cases = [ (datetime.datetime(2008, 5, 7, 20, 1, 23), b'2008-05-07 20:01:23'), (datetime.datetime(2012, 5, 2, 20, 1, 23, 10101), b'2012-05-02 20:01:23.010101') ] for data, exp in cases: self.assertEqual(exp, self.cnv._datetime_to_mysql(data)) def test__date_to_mysql(self): """A datetime.date becomes formatted like Y-m-d""" data = datetime.date(2008, 5, 7) res = self.cnv._date_to_mysql(data) exp = data.strftime('%Y-%m-%d').encode('ascii') self.assertEqual(exp, res) def test__time_to_mysql(self): """A datetime.time becomes formatted like Y-m-d H:M:S[.f]""" cases = [ (datetime.time(20, 3, 23), b'20:03:23'), (datetime.time(20, 3, 23, 10101), b'20:03:23.010101'), ] for data, exp in cases: self.assertEqual(exp, self.cnv._time_to_mysql(data)) def test__struct_time_to_mysql(self): """A time.struct_time becomes formatted like Y-m-d H:M:S""" data = time.localtime() res = self.cnv._struct_time_to_mysql(data) exp = time.strftime('%Y-%m-%d %H:%M:%S', data).encode('ascii') self.assertEqual(exp, res) def test__timedelta_to_mysql(self): """A datetime.timedelta becomes format like 'H:M:S[.f]'""" cases = [ (datetime.timedelta(hours=40, minutes=30, seconds=12), b'40:30:12'), (datetime.timedelta(hours=-40, minutes=30, seconds=12), b'-40:30:12'), (datetime.timedelta(hours=40, minutes=-1, seconds=12), b'39:59:12'), (datetime.timedelta(hours=-40, minutes=60, seconds=12), b'-39:00:12'), (datetime.timedelta(hours=40, minutes=30, seconds=12, microseconds=10101), b'40:30:12.010101'), (datetime.timedelta(hours=-40, minutes=30, seconds=12, microseconds=10101), b'-40:30:12.010101'), (datetime.timedelta(hours=40, minutes=-1, seconds=12, microseconds=10101), b'39:59:12.010101'), (datetime.timedelta(hours=-40, minutes=60, seconds=12, microseconds=10101), b'-39:00:12.010101'), ] for data, exp in cases: self.assertEqual(exp, self.cnv._timedelta_to_mysql(data)) def test__decimal_to_mysql(self): """A decimal.Decimal becomes a string.""" data = Decimal('3.14') self.assertEqual(b'3.14', self.cnv._decimal_to_mysql(data)) def test_to_python(self): """Convert MySQL data to Python types using helper method""" data = ( #, None, None, None, None, True, constants.FieldFlag.NUM), (b'3.14', ('float', constants.FieldType.FLOAT)), (b'128', ('int', constants.FieldType.TINY)), (b'1281288', ('long', constants.FieldType.LONG)), (b'3.14', ('decimal', constants.FieldType.DECIMAL)), (b'2008-05-07', ('date', constants.FieldType.DATE)), (b'45:34:10', ('time', constants.FieldType.TIME)), (b'2008-05-07 22:34:10', ('datetime', constants.FieldType.DATETIME)), (b'val1,val2', ('set', constants.FieldType.SET, None, None, None, None, True, constants.FieldFlag.SET)), (b'\xc3\xa4 utf8 string', ('utf8', constants.FieldType.STRING, None, None, None, None, True, 0)), ('2008', ('year', constants.FieldType.YEAR)), (b'\x80\x00\x00\x00', ('bit', constants.FieldType.BIT)), ) exp = ( float(data[0][0]), int(data[1][0]), int(data[2][0]), Decimal('3.14'), datetime.date(2008, 5, 7), datetime.timedelta(hours=45, minutes=34, seconds=10), datetime.datetime(2008, 5, 7, 22, 34, 10), {'val1', 'val2'}, str(data[8][0], 'utf8'), int(data[9][0]), 2147483648, ) res = tuple([self.cnv.to_python(v[1], v[0]) for v in data]) self.failUnlessEqual(res, exp) def test__FLOAT_to_python(self): """Convert a MySQL FLOAT/DOUBLE to a Python float type""" data = b'3.14' exp = float(data) res = self.cnv._FLOAT_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._FLOAT_to_python, self.cnv._DOUBLE_to_python) def test__INT_to_python(self): """Convert a MySQL TINY/SHORT/INT24/INT to a Python int type""" data = b'128' exp = int(data) res = self.cnv._INT_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._INT_to_python, self.cnv._TINY_to_python) self.assertEqual(self.cnv._INT_to_python, self.cnv._SHORT_to_python) self.assertEqual(self.cnv._INT_to_python, self.cnv._INT24_to_python) def test__LONG_to_python(self): """Convert a MySQL LONG/LONGLONG to a Python long type""" data = b'1281288' exp = int(data) res = self.cnv._LONG_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._LONG_to_python, self.cnv._LONGLONG_to_python) def test__DECIMAL_to_python(self): """Convert a MySQL DECIMAL to a Python decimal.Decimal type""" data = b'3.14' exp = Decimal('3.14') res = self.cnv._DECIMAL_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._DECIMAL_to_python, self.cnv._NEWDECIMAL_to_python) def test__BIT_to_python(self): """Convert a MySQL BIT to Python int""" data = [ b'\x80', b'\x80\x00', b'\x80\x00\x00', b'\x80\x00\x00\x00', b'\x80\x00\x00\x00\x00', b'\x80\x00\x00\x00\x00\x00', b'\x80\x00\x00\x00\x00\x00\x00', b'\x80\x00\x00\x00\x00\x00\x00\x00', ] exp = [128, 32768, 8388608, 2147483648, 549755813888, 140737488355328, 36028797018963968, 9223372036854775808] for i, buf in enumerate(data): self.assertEqual(self.cnv._BIT_to_python(buf), exp[i]) def test__DATE_to_python(self): """Convert a MySQL DATE to a Python datetime.date type""" data = b'2008-05-07' exp = datetime.date(2008, 5, 7) res = self.cnv._DATE_to_python(data) self.assertEqual(exp, res) res = self.cnv._DATE_to_python(b'0000-00-00') self.assertEqual(None, res) res = self.cnv._DATE_to_python(b'1000-00-00') self.assertEqual(None, res) def test__TIME_to_python(self): """Convert a MySQL TIME to a Python datetime.time type""" cases = [ (b'45:34:10', datetime.timedelta(hours=45, minutes=34, seconds=10)), (b'-45:34:10', datetime.timedelta(hours=-45, minutes=34, seconds=10)), (b'45:34:10.010101', datetime.timedelta(hours=45, minutes=34, seconds=10, microseconds=10101)), (b'-45:34:10.010101', datetime.timedelta(hours=-45, minutes=34, seconds=10, microseconds=10101)), ] for data, exp in cases: self.assertEqual(exp, self.cnv._TIME_to_python(data)) def test__DATETIME_to_python(self): """Convert a MySQL DATETIME to a Python datetime.datetime type""" cases = [ (b'2008-05-07 22:34:10', datetime.datetime(2008, 5, 7, 22, 34, 10)), (b'2008-05-07 22:34:10.010101', datetime.datetime(2008, 5, 7, 22, 34, 10, 10101)), (b'0000-00-00 00:00:00', None), (b'1000-00-00 00:00:00', None), ] for data, exp in cases: self.assertEqual(exp, self.cnv._DATETIME_to_python(data)) def test__YEAR_to_python(self): """Convert a MySQL YEAR to Python int""" data = '2008' exp = 2008 self.assertEqual(exp, self.cnv._YEAR_to_python(data)) data = 'foobar' self.assertRaises(ValueError, self.cnv._YEAR_to_python, data) def test__SET_to_python(self): """Convert a MySQL SET type to a Python sequence This actually calls hte _STRING_to_python() method since a SET is returned as string by MySQL. However, the description of the field has in it's field flags that the string is a SET. """ data = b'val1,val2' exp = {'val1', 'val2'} desc = ('foo', constants.FieldType.STRING, 2, 3, 4, 5, 6, constants.FieldFlag.SET) res = self.cnv._STRING_to_python(data, desc) self.assertEqual(exp, res) def test__STRING_to_python_utf8(self): """Convert a UTF-8 MySQL STRING/VAR_STRING to a Python Unicode type""" self.cnv.set_charset('utf8') # default data = b'\xc3\xa4 utf8 string' exp = data.decode('utf-8') res = self.cnv._STRING_to_python(data) self.assertEqual(exp, res) def test__STRING_to_python_latin1(self): """Convert a ISO-8859-1 MySQL STRING/VAR_STRING to a Python str""" self.cnv.set_charset('latin1') self.cnv.set_unicode(False) data = b'\xe4 latin string' exp = data res = self.cnv._STRING_to_python(data) self.assertEqual(exp, res) exp = data.decode('latin1') self.cnv.set_unicode(True) res = self.cnv._STRING_to_python(data) self.assertEqual(exp, res) self.cnv.set_charset('utf8') self.cnv.set_unicode(True) def test__STRING_to_python_binary(self): """Convert a STRING BINARY to Python bytes type""" data = b'\x33\xfd\x34\xed' desc = ('foo', constants.FieldType.STRING, 2, 3, 4, 5, 6, constants.FieldFlag.BINARY) res = self.cnv._STRING_to_python(data, desc) self.assertEqual(data, res) def test__BLOB_to_python_binary(self): """Convert a BLOB BINARY to Python bytes type""" data = b'\x33\xfd\x34\xed' desc = ('foo', constants.FieldType.BLOB, 2, 3, 4, 5, 6, constants.FieldFlag.BINARY) res = self.cnv._BLOB_to_python(data, desc) self.assertEqual(data, res) mysql-connector-python-1.1.6/tests/test_constants.py0000644001577100000120000003420312276514013022233 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.constants """ import tests from mysql.connector import constants, errors class Helpers(tests.MySQLConnectorTests): def test_flag_is_set(self): """Check if a particular flag/bit is set""" data = [ 1 << 3, 1 << 5, 1 << 7, ] flags = 0 for flag in data: flags |= flag for flag in data: self.assertTrue(constants.flag_is_set(flag, flags)) self.assertFalse(constants.flag_is_set(1 << 4, flags)) def test_MAX_PACKET_LENGTH(self): """Check MAX_PACKET_LENGTH""" self.assertEqual(16777215, constants.MAX_PACKET_LENGTH) def test_NET_BUFFER_LENGTH(self): """Check NET_BUFFER_LENGTH""" self.assertEqual(8192, constants.NET_BUFFER_LENGTH) class FieldTypeTests(tests.MySQLConnectorTests): desc = { 'DECIMAL': (0x00, 'DECIMAL'), 'TINY': (0x01, 'TINY'), 'SHORT': (0x02, 'SHORT'), 'LONG': (0x03, 'LONG'), 'FLOAT': (0x04, 'FLOAT'), 'DOUBLE': (0x05, 'DOUBLE'), 'NULL': (0x06, 'NULL'), 'TIMESTAMP': (0x07, 'TIMESTAMP'), 'LONGLONG': (0x08, 'LONGLONG'), 'INT24': (0x09, 'INT24'), 'DATE': (0x0a, 'DATE'), 'TIME': (0x0b, 'TIME'), 'DATETIME': (0x0c, 'DATETIME'), 'YEAR': (0x0d, 'YEAR'), 'NEWDATE': (0x0e, 'NEWDATE'), 'VARCHAR': (0x0f, 'VARCHAR'), 'BIT': (0x10, 'BIT'), 'NEWDECIMAL': (0xf6, 'NEWDECIMAL'), 'ENUM': (0xf7, 'ENUM'), 'SET': (0xf8, 'SET'), 'TINY_BLOB': (0xf9, 'TINY_BLOB'), 'MEDIUM_BLOB': (0xfa, 'MEDIUM_BLOB'), 'LONG_BLOB': (0xfb, 'LONG_BLOB'), 'BLOB': (0xfc, 'BLOB'), 'VAR_STRING': (0xfd, 'VAR_STRING'), 'STRING': (0xfe, 'STRING'), 'GEOMETRY': (0xff, 'GEOMETRY'), } type_groups = { 'string': [ constants.FieldType.VARCHAR, constants.FieldType.ENUM, constants.FieldType.VAR_STRING, constants.FieldType.STRING, ], 'binary': [ constants.FieldType.TINY_BLOB, constants.FieldType.MEDIUM_BLOB, constants.FieldType.LONG_BLOB, constants.FieldType.BLOB, ], 'number': [ constants.FieldType.DECIMAL, constants.FieldType.NEWDECIMAL, constants.FieldType.TINY, constants.FieldType.SHORT, constants.FieldType.LONG, constants.FieldType.FLOAT, constants.FieldType.DOUBLE, constants.FieldType.LONGLONG, constants.FieldType.INT24, constants.FieldType.BIT, constants.FieldType.YEAR, ], 'datetime': [ constants.FieldType.DATETIME, constants.FieldType.TIMESTAMP, ], } def test_attributes(self): """Check attributes for FieldType""" self.assertEqual('FIELD_TYPE_', constants.FieldType.prefix) for key, value in self.desc.items(): self.failUnless(key in constants.FieldType.__dict__, '{0} is not an attribute of FieldType'.format(key)) self.assertEqual( value[0], constants.FieldType.__dict__[key], '{0} attribute of FieldType has wrong value'.format(key)) def test_get_desc(self): """Get field type by name""" for key, value in self.desc.items(): exp = value[1] res = constants.FieldType.get_desc(key) self.assertEqual(exp, res) self.assertEqual(None, constants.FieldType.get_desc('FooBar')) def test_get_info(self): """Get field type by id""" for _, value in self.desc.items(): exp = value[1] res = constants.FieldType.get_info(value[0]) self.assertEqual(exp, res) self.assertEqual(None, constants.FieldType.get_info(999999999)) def test_get_string_types(self): """DBAPI string types""" self.assertEqual(self.type_groups['string'], constants.FieldType.get_string_types()) def test_get_binary_types(self): """DBAPI string types""" self.assertEqual(self.type_groups['binary'], constants.FieldType.get_binary_types()) def test_get_number_types(self): """DBAPI number types""" self.assertEqual(self.type_groups['number'], constants.FieldType.get_number_types()) def test_get_timestamp_types(self): """DBAPI datetime types""" self.assertEqual(self.type_groups['datetime'], constants.FieldType.get_timestamp_types()) class FieldFlagTests(tests.MySQLConnectorTests): desc = { 'NOT_NULL': (1 << 0, "Field can't be NULL"), 'PRI_KEY': (1 << 1, "Field is part of a primary key"), 'UNIQUE_KEY': (1 << 2, "Field is part of a unique key"), 'MULTIPLE_KEY': (1 << 3, "Field is part of a key"), 'BLOB': (1 << 4, "Field is a blob"), 'UNSIGNED': (1 << 5, "Field is unsigned"), 'ZEROFILL': (1 << 6, "Field is zerofill"), 'BINARY': (1 << 7, "Field is binary "), 'ENUM': (1 << 8, "field is an enum"), 'AUTO_INCREMENT': (1 << 9, "field is a autoincrement field"), 'TIMESTAMP': (1 << 10, "Field is a timestamp"), 'SET': (1 << 11, "field is a set"), 'NO_DEFAULT_VALUE': (1 << 12, "Field doesn't have default value"), 'ON_UPDATE_NOW': (1 << 13, "Field is set to NOW on UPDATE"), 'NUM': (1 << 14, "Field is num (for clients)"), 'PART_KEY': (1 << 15, "Intern; Part of some key"), 'GROUP': (1 << 14, "Intern: Group field"), # Same as NUM 'UNIQUE': (1 << 16, "Intern: Used by sql_yacc"), 'BINCMP': (1 << 17, "Intern: Used by sql_yacc"), 'GET_FIXED_FIELDS': (1 << 18, "Used to get fields in item tree"), 'FIELD_IN_PART_FUNC': (1 << 19, "Field part of partition func"), 'FIELD_IN_ADD_INDEX': (1 << 20, "Intern: Field used in ADD INDEX"), 'FIELD_IS_RENAMED': (1 << 21, "Intern: Field is being renamed"), } def test_attributes(self): """Check attributes for FieldFlag""" self.assertEqual('', constants.FieldFlag._prefix) for key, value in self.desc.items(): self.failUnless(key in constants.FieldFlag.__dict__, '{0} is not an attribute of FieldFlag'.format(key)) self.assertEqual( value[0], constants.FieldFlag.__dict__[key], '{0} attribute of FieldFlag has wrong value'.format(key)) def test_get_desc(self): """Get field flag by name""" for key, value in self.desc.items(): exp = value[1] res = constants.FieldFlag.get_desc(key) self.assertEqual(exp, res) def test_get_info(self): """Get field flag by id""" for exp, info in self.desc.items(): # Ignore the NUM/GROUP (bug in MySQL source code) if info[0] == 1 << 14: break res = constants.FieldFlag.get_info(info[0]) self.assertEqual(exp, res) def test_get_bit_info(self): """Get names of the set flags""" data = 0 data |= constants.FieldFlag.BLOB data |= constants.FieldFlag.BINARY exp = ['BINARY', 'BLOB'].sort() self.assertEqual(exp, constants.FieldFlag.get_bit_info(data).sort()) class CharacterSetTests(tests.MySQLConnectorTests): """Tests for constants.CharacterSet""" def test_get_info(self): """Get info about charset using MySQL ID""" exp = ('utf8', 'utf8_general_ci') data = 33 self.assertEqual(exp, constants.CharacterSet.get_info(data)) exception = errors.ProgrammingError data = 50000 self.assertRaises(exception, constants.CharacterSet.get_info, data) def test_get_desc(self): """Get info about charset using MySQL ID as string""" exp = 'utf8/utf8_general_ci' data = 33 self.assertEqual(exp, constants.CharacterSet.get_desc(data)) exception = errors.ProgrammingError data = 50000 self.assertRaises(exception, constants.CharacterSet.get_desc, data) def test_get_default_collation(self): """Get default collation for a given Character Set""" func = constants.CharacterSet.get_default_collation data = 'sjis' exp = ('sjis_japanese_ci', data, 13) self.assertEqual(exp, func(data)) self.assertEqual(exp, func(exp[2])) exception = errors.ProgrammingError data = 'foobar' self.assertRaises(exception, func, data) def test_get_charset_info(self): """Get info about charset by name and collation""" func = constants.CharacterSet.get_charset_info exp = (209, 'utf8', 'utf8_esperanto_ci') data = exp[1:] self.assertEqual(exp, func(data[0], data[1])) self.assertEqual(exp, func(None, data[1])) self.assertEqual(exp, func(exp[0])) self.assertRaises(errors.ProgrammingError, constants.CharacterSet.get_charset_info, 666) self.assertRaises( errors.ProgrammingError, constants.CharacterSet.get_charset_info, charset='utf8', collation='utf8_spam_ci') self.assertRaises( errors.ProgrammingError, constants.CharacterSet.get_charset_info, collation='utf8_spam_ci') def test_get_supported(self): """Get list of all supported character sets""" exp = ( 'big5', 'latin2', 'dec8', 'cp850', 'latin1', 'hp8', 'koi8r', 'swe7', 'ascii', 'ujis', 'sjis', 'cp1251', 'hebrew', 'tis620', 'euckr', 'latin7', 'koi8u', 'gb2312', 'greek', 'cp1250', 'gbk', 'cp1257', 'latin5', 'armscii8', 'utf8', 'ucs2', 'cp866', 'keybcs2', 'macce', 'macroman', 'cp852', 'utf8mb4','utf16', 'utf16le', 'cp1256', 'utf32', 'binary', 'geostd8', 'cp932', 'eucjpms' ) self.assertEqual(exp, constants.CharacterSet.get_supported()) class SQLModesTests(tests.MySQLConnectorTests): modes = ( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', ) def test_get_info(self): for mode in SQLModesTests.modes: self.assertEqual(mode, getattr(constants.SQLMode, mode), 'Wrong info for SQL Mode {0}'.format(mode)) def test_get_full_info(self): modes = tuple(sorted(SQLModesTests.modes)) self.assertEqual(modes, constants.SQLMode.get_full_info()) class ShutdownTypeTests(tests.MySQLConnectorTests): """Test COM_SHUTDOWN types""" desc = { 'SHUTDOWN_DEFAULT': (b'\x00', "defaults to SHUTDOWN_WAIT_ALL_BUFFERS"), 'SHUTDOWN_WAIT_CONNECTIONS': ( b'\x01', "wait for existing connections to finish"), 'SHUTDOWN_WAIT_TRANSACTIONS': (b'\x02', "wait for existing trans to finish"), 'SHUTDOWN_WAIT_UPDATES': (b'\x08', "wait for existing updates to finish"), 'SHUTDOWN_WAIT_ALL_BUFFERS': ( b'\x10', "flush InnoDB and other storage engine buffers"), 'SHUTDOWN_WAIT_CRITICAL_BUFFERS': ( b'\x11', "don't flush InnoDB buffers, flush other storage engines' buffers"), 'KILL_QUERY': (b'\xfe', "(no description)"), 'KILL_CONNECTION': (b'\xff', "(no description)"), } def test_attributes(self): """Check attributes for FieldType""" self.assertEqual('', constants.ShutdownType.prefix) for key, value in self.desc.items(): self.failUnless(key in constants.ShutdownType.__dict__, '{0} is not an attribute of FieldType'.format(key)) self.assertEqual( value[0], constants.ShutdownType.__dict__[key], '{0} attribute of ShutdownType has wrong value'.format(key)) def test_get_desc(self): """Get field flag by name""" for key, value in self.desc.items(): exp = value[1] res = constants.ShutdownType.get_desc(key) self.assertEqual(exp, res) mysql-connector-python-1.1.6/tests/test_mysql_datatypes.py0000644001577100000120000002743712276514013023455 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for MySQL data types """ from decimal import Decimal import time import datetime from mysql.connector import connection import tests def _get_insert_stmt(tbl, cols): insert = "INSERT INTO {table} ({columns}) values ({values})".format( table=tbl, columns=','.join(cols), values=','.join(['%s'] * len(cols)) ) return insert def _get_select_stmt(tbl, cols): select = "SELECT {columns} FROM {table} ORDER BY id".format( columns=','.join(cols), table=tbl ) return select class TestsDataTypes(tests.MySQLConnectorTests): tables = { 'bit': 'myconnpy_mysql_bit', 'int': 'myconnpy_mysql_int', 'bool': 'myconnpy_mysql_bool', 'float': 'myconnpy_mysql_float', 'decimal': 'myconnpy_mysql_decimal', 'temporal': 'myconnpy_mysql_temporal', 'temporal_year': 'myconnpy_mysql_temporal_year', } def compare(self, name, val1, val2): self.assertEqual(val1, val2, "%s %s != %s" % (name, val1, val2)) def drop_tables(self, cnx): cur = cnx.cursor() table_names = self.tables.values() cur.execute("DROP TABLE IF EXISTS {tables}".format( tables=','.join(table_names)) ) cur.close() class TestsCursor(TestsDataTypes): def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.drop_tables(self.cnx) def tearDown(self): self.drop_tables(self.cnx) self.cnx.close() def test_numeric_int(self): """MySQL numeric integer data types""" cur = self.cnx.cursor() columns = [ 'tinyint_signed', 'tinyint_unsigned', 'bool_signed', 'smallint_signed', 'smallint_unsigned', 'mediumint_signed', 'mediumint_unsigned', 'int_signed', 'int_unsigned', 'bigint_signed', 'bigint_unsigned', ] cur.execute(( "CREATE TABLE {table} (" "`id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT," "`tinyint_signed` TINYINT SIGNED," "`tinyint_unsigned` TINYINT UNSIGNED," "`bool_signed` BOOL," "`smallint_signed` SMALLINT SIGNED," "`smallint_unsigned` SMALLINT UNSIGNED," "`mediumint_signed` MEDIUMINT SIGNED," "`mediumint_unsigned` MEDIUMINT UNSIGNED," "`int_signed` INT SIGNED," "`int_unsigned` INT UNSIGNED," "`bigint_signed` BIGINT SIGNED," "`bigint_unsigned` BIGINT UNSIGNED," "PRIMARY KEY (id))" ).format(table=self.tables['int']) ) data = [ ( -128, # tinyint signed 0, # tinyint unsigned 0, # boolean -32768, # smallint signed 0, # smallint unsigned -8388608, # mediumint signed 0, # mediumint unsigned -2147483648, # int signed 0, # int unsigned -9223372036854775808, # big signed 0, # big unsigned ), ( 127, # tinyint signed 255, # tinyint unsigned 127, # boolean 32767, # smallint signed 65535, # smallint unsigned 8388607, # mediumint signed 16777215, # mediumint unsigned 2147483647, # int signed 4294967295, # int unsigned 9223372036854775807, # big signed 18446744073709551615, # big unsigned ) ] insert = _get_insert_stmt(self.tables['int'], columns) select = _get_select_stmt(self.tables['int'], columns) cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() for i, col in enumerate(columns): self.compare(col, data[0][i], rows[0][i]) self.compare(col, data[1][i], rows[1][i]) cur.close() def test_numeric_bit(self): """MySQL numeric bit data type""" cur = self.cnx.cursor() columns = [ 'c8', 'c16', 'c24', 'c32', 'c40', 'c48', 'c56', 'c63', 'c64'] cur.execute(( "CREATE TABLE {table} (" "`id` int NOT NULL AUTO_INCREMENT," "`c8` bit(8) DEFAULT NULL," "`c16` bit(16) DEFAULT NULL," "`c24` bit(24) DEFAULT NULL," "`c32` bit(32) DEFAULT NULL," "`c40` bit(40) DEFAULT NULL," "`c48` bit(48) DEFAULT NULL," "`c56` bit(56) DEFAULT NULL," "`c63` bit(63) DEFAULT NULL," "`c64` bit(64) DEFAULT NULL," "PRIMARY KEY (id))" ).format(table=self.tables['bit']) ) insert = _get_insert_stmt(self.tables['bit'], columns) select = _get_select_stmt(self.tables['bit'], columns) data = list() data.append(tuple([0] * len(columns))) values = list() for col in columns: values.append(1 << int(col.replace('c', '')) - 1) data.append(tuple(values)) values = list() for col in columns: values.append((1 << int(col.replace('c', ''))) - 1) data.append(tuple(values)) cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() self.assertEqual(rows, data) cur.close() def test_numeric_float(self): """MySQL numeric float data type""" cur = self.cnx.cursor() columns = [ 'float_signed', 'float_unsigned', 'double_signed', 'double_unsigned', ] cur.execute(( "CREATE TABLE {table} (" "`id` int NOT NULL AUTO_INCREMENT," "`float_signed` FLOAT(6,5) SIGNED," "`float_unsigned` FLOAT(6,5) UNSIGNED," "`double_signed` DOUBLE(15,10) SIGNED," "`double_unsigned` DOUBLE(15,10) UNSIGNED," "PRIMARY KEY (id))" ).format(table=self.tables['float']) ) insert = _get_insert_stmt(self.tables['float'], columns) select = _get_select_stmt(self.tables['float'], columns) data = [ (-3.402823466, 0, -1.7976931348623157, 0,), (-1.175494351, 3.402823466, 1.7976931348623157, 2.2250738585072014), (-1.23455678, 2.999999, -1.3999999999999999, 1.9999999999999999), ] cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() for j in range(0, len(data)): for i, col in enumerate(columns[0:2]): self.compare(col, round(data[j][i], 5), rows[j][i]) for i, col in enumerate(columns[2:2]): self.compare(col, round(data[j][i], 10), rows[j][i]) cur.close() def test_numeric_decimal(self): """MySQL numeric decimal data type""" cur = self.cnx.cursor() columns = [ 'decimal_signed', 'decimal_unsigned', ] cur.execute(( "CREATE TABLE {table} (" "`id` int NOT NULL AUTO_INCREMENT," "`decimal_signed` DECIMAL(65,30) SIGNED," "`decimal_unsigned` DECIMAL(65,30) UNSIGNED," "PRIMARY KEY (id))" ).format(table=self.tables['decimal']) ) insert = _get_insert_stmt(self.tables['decimal'], columns) select = _get_select_stmt(self.tables['decimal'], columns) data = [ (Decimal( '-9999999999999999999999999.999999999999999999999999999999'), Decimal( '+9999999999999999999999999.999999999999999999999999999999')), (Decimal('-1234567.1234'), Decimal('+123456789012345.123456789012345678901')), (Decimal( '-1234567890123456789012345.123456789012345678901234567890'), Decimal( '+1234567890123456789012345.123456789012345678901234567890')), ] cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() self.assertEqual(data, rows) cur.close() def test_temporal_datetime(self): """MySQL temporal date/time data types""" cur = self.cnx.cursor() cur.execute("SET SESSION time_zone = '+00:00'") columns = [ 't_date', 't_datetime', 't_time', 't_timestamp', 't_year_4', ] cur.execute(( "CREATE TABLE {table} (" "`id` int NOT NULL AUTO_INCREMENT," "`t_date` DATE," "`t_datetime` DATETIME," "`t_time` TIME," "`t_timestamp` TIMESTAMP DEFAULT 0," "`t_year_4` YEAR(4)," "PRIMARY KEY (id))" ).format(table=self.tables['temporal']) ) insert = _get_insert_stmt(self.tables['temporal'], columns) select = _get_select_stmt(self.tables['temporal'], columns) data = [ (datetime.date(2010, 1, 17), datetime.datetime(2010, 1, 17, 19, 31, 12), datetime.timedelta(hours=43, minutes=32, seconds=21), datetime.datetime(2010, 1, 17, 19, 31, 12), 0), (datetime.date(1000, 1, 1), datetime.datetime(1000, 1, 1, 0, 0, 0), datetime.timedelta(hours=-838, minutes=59, seconds=59), datetime.datetime(*time.gmtime(1)[:6]), 1901), (datetime.date(9999, 12, 31), datetime.datetime(9999, 12, 31, 23, 59, 59), datetime.timedelta(hours=838, minutes=59, seconds=59), datetime.datetime(2038, 1, 19, 3, 14, 7), 2155), ] cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() for j in (range(0, len(data))): for i, col in enumerate(columns): self.compare("{column} (data[{count}])".format( column=col, count=j), data[j][i], rows[j][i]) # Testing YEAR(2), which is now obsolete since MySQL 5.6.6 tblname = self.tables['temporal_year'] cur.execute( "CREATE TABLE {table} (" "`id` int NOT NULL AUTO_INCREMENT KEY, " "`t_year_2` YEAR(2))".format(table=tblname) ) cur.execute(_get_insert_stmt(tblname, ['t_year_2']), (10,)) cur.execute(_get_select_stmt(tblname, ['t_year_2'])) row = cur.fetchone() if tests.MYSQL_VERSION >= (5, 6, 6): self.assertEqual(2010, row[0]) else: self.assertEqual(10, row[0]) cur.close() mysql-connector-python-1.1.6/tests/test_connection.py0000644001577100000120000020101412276514013022352 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.connection """ import sys import os import logging import timeit import unittest from decimal import Decimal import io import tests try: if sys.version_info[0] == 2: from .py2.connection import * else: from .py3.connection import * except ImportError: raise from mysql.connector.conversion import (MySQLConverterBase, MySQLConverter) from mysql.connector import (connection, network, errors, constants, cursor) LOGGER = logging.getLogger(tests.LOGGER_NAME) class _DummyMySQLConnection(connection.MySQLConnection): def _open_connection(self, *args, **kwargs): pass def _post_connection(self, *args, **kwargs): pass class ConnectionTests(tests.MySQLConnectorTests): def test_DEFAULT_CONFIGURATION(self): exp = { 'database': None, 'user': '', 'password': '', 'host': '127.0.0.1', 'port': 3306, 'unix_socket': None, 'use_unicode': True, 'charset': 'utf8', 'collation': None, 'converter_class': MySQLConverter, 'autocommit': False, 'time_zone': None, 'sql_mode': None, 'get_warnings': False, 'raise_on_warnings': False, 'connection_timeout': None, 'client_flags': 0, 'compress': False, 'buffered': False, 'raw': False, 'ssl_ca': None, 'ssl_cert': None, 'ssl_key': None, 'ssl_verify_cert': False, 'passwd': None, 'db': None, 'connect_timeout': None, 'dsn': None, 'force_ipv6': False, } self.assertEqual(exp, connection.DEFAULT_CONFIGURATION) class MySQLConnectionTests(tests.MySQLConnectorTests): def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) def tearDown(self): try: self.cnx.close() except: pass def test_init(self): """MySQLConnection initialization""" cnx = connection.MySQLConnection() exp = { 'converter': None, '_converter_class': MySQLConverter, '_client_flags': constants.ClientFlag.get_default(), '_charset_id': 33, '_user': '', '_password': '', '_database': '', '_host': '127.0.0.1', '_port': 3306, '_unix_socket': None, '_use_unicode': True, '_get_warnings': False, '_raise_on_warnings': False, '_connection_timeout': None, '_buffered': False, '_unread_result': False, '_have_next_result': False, '_raw': False, '_client_host': '', '_client_port': 0, '_ssl': {}, '_in_transaction': False, '_force_ipv6': False, } for key, value in exp.items(): self.assertEqual( value, cnx.__dict__[key], msg="Default for '{0}' did not match.".format(key)) # Make sure that when at least one argument is given, # connect() is called class FakeMySQLConnection(connection.MySQLConnection): def connect(self, **kwargs): self._database = kwargs['database'] exp = 'test' cnx = FakeMySQLConnection(database=exp) self.assertEqual(exp, cnx._database) def test__get_self(self): """Return self""" self.assertEqual(self.cnx, self.cnx._get_self()) def test__send_cmd(self): """Send a command to MySQL""" cmd = constants.ServerCmd.QUERY arg = 'SELECT 1'.encode('utf-8') pktnr = 2 self.cnx._socket.sock = None self.assertRaises(errors.OperationalError, self.cnx._send_cmd, cmd, arg, pktnr) self.cnx._socket.sock = tests.DummySocket() exp = b'\x07\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00' self.cnx._socket.sock.add_packet(exp) res = self.cnx._send_cmd(cmd, arg, pktnr) self.assertEqual(exp, res) # Send an unknown command, the result should be an error packet exp = b'\x18\x00\x00\x01\xff\x17\x04\x23\x30\x38\x53\x30\x31\x55'\ b'\x6e\x6b\x6e\x6f\x77\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(exp) res = self.cnx._send_cmd(90, b'spam', 0) def test__handle_server_status(self): """Handle the server/status flags""" cases = [ # (serverflag, attribute_name, value when set, value when unset) (constants.ServerFlag.MORE_RESULTS_EXISTS, '_have_next_result', True, False), (constants.ServerFlag.STATUS_IN_TRANS, '_in_transaction', True, False), ] for (flag, attr, when_set, when_unset) in cases: setattr(self.cnx, attr, when_unset) self.cnx._handle_server_status(flag) self.assertEqual(when_set, getattr(self.cnx, attr)) self.cnx._handle_server_status(0) self.assertEqual(when_unset, getattr(self.cnx, attr)) def test__handle_ok(self): """Handle an OK-packet sent by MySQL""" self.assertEqual(OK_PACKET_RESULT, self.cnx._handle_ok(OK_PACKET)) self.assertRaises(errors.ProgrammingError, self.cnx._handle_ok, ERR_PACKET) self.assertRaises(errors.InterfaceError, self.cnx._handle_ok, EOF_PACKET) # Test for multiple results self.cnx._have_next_result = False packet = OK_PACKET[:-4] + b'\x08' + OK_PACKET[-3:] self.cnx._handle_ok(packet) self.assertTrue(self.cnx._have_next_result) def test__handle_eof(self): """Handle an EOF-packet sent by MySQL""" self.assertEqual(EOF_PACKET_RESULT, self.cnx._handle_eof(EOF_PACKET)) self.assertRaises(errors.ProgrammingError, self.cnx._handle_eof, ERR_PACKET) self.assertRaises(errors.InterfaceError, self.cnx._handle_eof, OK_PACKET) # Test for multiple results self.cnx._have_next_result = False packet = EOF_PACKET[:-2] + b'\x08' + EOF_PACKET[-1:] self.cnx._handle_eof(packet) self.assertTrue(self.cnx._have_next_result) def test__handle_result(self): """Handle the result after sending a command to MySQL""" self.assertRaises(errors.InterfaceError, self.cnx._handle_result, '\x00') self.assertRaises(errors.InterfaceError, self.cnx._handle_result, None) self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packets([ b'\x17\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01' b'\x31\x00\x0c\x3f\x00\x01\x00\x00\x00\x08\x81\x00' b'\x00\x00\x00', b'\x05\x00\x00\x03\xfe\x00\x00\x00\x00']) exp = { 'eof': {'status_flag': 0, 'warning_count': 0}, 'columns': [('1', 8, None, None, None, None, 0, 129)] } res = self.cnx._handle_result(b'\x01\x00\x00\x01\x01') self.assertEqual(exp, res) self.assertEqual(EOF_PACKET_RESULT, self.cnx._handle_result(EOF_PACKET)) self.cnx._unread_result = False # Handle LOAD DATA INFILE self.cnx._socket.sock.reset() packet = ( b'\x1A\x00\x00\x01\xfb' b'\x74\x65\x73\x74\x73\x2f\x64\x61\x74\x61\x2f\x6c\x6f' b'\x63\x61\x6c\x5f\x64\x61\x74\x61\x2e\x63\x73\x76') self.cnx._socket.sock.add_packet( b'\x37\x00\x00\x04\x00\x06\x00\x01\x00\x00\x00\x2f\x52' b'\x65\x63\x6f\x72\x64\x73\x3a\x20\x36\x20\x20\x44\x65' b'\x6c\x65\x74\x65\x64\x3a\x20\x30\x20\x20\x53\x6b\x69' b'\x70\x70\x65\x64\x3a\x20\x30\x20\x20\x57\x61\x72\x6e' b'\x69\x6e\x67\x73\x3a\x20\x30') exp = { 'info_msg': 'Records: 6 Deleted: 0 Skipped: 0 Warnings: 0', 'insert_id': 0, 'field_count': 0, 'warning_count': 0, 'server_status': 1, 'affected_rows': 6} self.assertEqual(exp, self.cnx._handle_result(packet)) exp = [ (b'\x47\x00\x00\x04\x31\x09\x63\x31\x5f\x31\x09\x63\x32' b'\x5f\x31\x0a\x32\x09\x63\x31\x5f\x32\x09\x63\x32\x5f' b'\x32\x0a\x33\x09\x63\x31\x5f\x33\x09\x63\x32\x5f\x33' b'\x0a\x34\x09\x63\x31\x5f\x34\x09\x63\x32\x5f\x34\x0a' b'\x35\x09\x63\x31\x5f\x35\x09\x63\x32\x5f\x35\x0a\x36' b'\x09\x63\x31\x5f\x36\x09\x63\x32\x5f\x36'), b'\x00\x00\x00\x05'] self.assertEqual(exp, self.cnx._socket.sock._client_sends) # Column count is invalid (is None) self.cnx._socket.sock.reset() packet = b'\x01\x00\x00\x01\xfa\xa3\x00\xa3' self.assertRaises(errors.InterfaceError, self.cnx._handle_result, packet) # First byte in first packet is wrong self.cnx._socket.sock.add_packets([ b'\x00\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01' b'\x31\x00\x0c\x3f\x00\x01\x00\x00\x00\x08\x81\x00' b'\x00\x00\x00', b'\x05\x00\x00\x03\xfe\x00\x00\x00\x00']) self.assertRaises(errors.InterfaceError, self.cnx._handle_result, b'\x01\x00\x00\x01\x00') def __helper_get_rows_buffer(self, toggle_next_result=False): self.cnx._socket.sock.reset() packets = [ b'\x07\x00\x00\x04\x06\x4d\x79\x49\x53\x41\x4d', b'\x07\x00\x00\x05\x06\x49\x6e\x6e\x6f\x44\x42', b'\x0a\x00\x00\x06\x09\x42\x4c\x41\x43\x4b\x48\x4f\x4c\x45', b'\x04\x00\x00\x07\x03\x43\x53\x56', b'\x07\x00\x00\x08\x06\x4d\x45\x4d\x4f\x52\x59', b'\x0a\x00\x00\x09\x09\x46\x45\x44\x45\x52\x41\x54\x45\x44', b'\x08\x00\x00\x0a\x07\x41\x52\x43\x48\x49\x56\x45', b'\x0b\x00\x00\x0b\x0a\x4d\x52\x47\x5f\x4d\x59\x49\x53\x41\x4d', b'\x05\x00\x00\x0c\xfe\x00\x00\x20\x00', ] if toggle_next_result: packets[-1] = packets[-1][:-2] + b'\x08' + packets[-1][-1:] self.cnx._socket.sock.add_packets(packets) self.cnx.unread_result = True def test_get_rows(self): """Get rows from the MySQL resultset""" self.cnx._socket.sock = tests.DummySocket() self.__helper_get_rows_buffer() exp = ( [(b'MyISAM',), (b'InnoDB',), (b'BLACKHOLE',), (b'CSV',), (b'MEMORY',), (b'FEDERATED',), (b'ARCHIVE',), (b'MRG_MYISAM',)], {'status_flag': 32, 'warning_count': 0} ) res = self.cnx.get_rows() self.assertEqual(exp, res) self.__helper_get_rows_buffer() rows = exp[0] i = 0 while i < len(rows): exp = (rows[i:i + 2], None) res = self.cnx.get_rows(2) self.assertEqual(exp, res) i += 2 exp = ([], {'status_flag': 32, 'warning_count': 0}) self.assertEqual(exp, self.cnx.get_rows()) # Test unread results self.cnx.unread_result = False self.assertRaises(errors.InternalError, self.cnx.get_rows) # Test multiple results self.cnx._have_next_results = False self.__helper_get_rows_buffer(toggle_next_result=True) exp = {'status_flag': 8, 'warning_count': 0} self.assertEqual(exp, self.cnx.get_rows()[-1]) self.assertTrue(self.cnx._have_next_result) def test_get_row(self): """Get a row from the MySQL resultset""" self.cnx._socket.sock = tests.DummySocket() self.__helper_get_rows_buffer() expall = ( [(b'MyISAM',), (b'InnoDB',), (b'BLACKHOLE',), (b'CSV',), (b'MEMORY',), (b'FEDERATED',), (b'ARCHIVE',), (b'MRG_MYISAM',)], {'status_flag': 32, 'warning_count': 0} ) rows = expall[0] for row in rows: res = self.cnx.get_row() exp = (row, None) self.assertEqual(exp, res) exp = ([], {'status_flag': 32, 'warning_count': 0}) self.assertEqual(exp, self.cnx.get_rows()) def test_cmd_init_db(self): """Send the Init_db-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) self.assertEqual(OK_PACKET_RESULT, self.cnx.cmd_init_db('test')) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet( b'\x2c\x00\x00\x01\xff\x19\x04\x23\x34\x32\x30\x30' b'\x30\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x64\x61\x74' b'\x61\x62\x61\x73\x65\x20\x27\x75\x6e\x6b\x6e\x6f' b'\x77\x6e\x5f\x64\x61\x74\x61\x62\x61\x73\x65\x27' ) self.assertRaises(errors.ProgrammingError, self.cnx.cmd_init_db, 'unknown_database') def test_cmd_query(self): """Send a query to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) res = self.cnx.cmd_query("SET AUTOCOMMIT = OFF") self.assertEqual(OK_PACKET_RESULT, res) packets = [ b'\x01\x00\x00\x01\x01', b'\x17\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01' b'\x31\x00\x0c\x3f\x00\x01\x00\x00\x00\x08\x81\x00' b'\x00\x00\x00', b'\x05\x00\x00\x03\xfe\x00\x00\x00\x00' ] # query = "SELECT 1" self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets(packets) exp = { 'eof': {'status_flag': 0, 'warning_count': 0}, 'columns': [('1', 8, None, None, None, None, 0, 129)] } res = self.cnx.cmd_query("SELECT 1") self.assertEqual(exp, res) self.assertRaises(errors.InternalError, self.cnx.cmd_query, 'SELECT 2') self.cnx.unread_result = False # Forge the packets so the multiple result flag is set packets[-1] = packets[-1][:-2] + b'\x08' + packets[-1][-1:] self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets(packets) self.assertRaises(errors.InterfaceError, self.cnx.cmd_query, "SELECT 1") def test_cmd_query_iter(self): """Send queries to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) res = next(self.cnx.cmd_query_iter( "SET AUTOCOMMIT = OFF")) self.assertEqual(OK_PACKET_RESULT, res) packets = [ b'\x01\x00\x00\x01\x01', b'\x17\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01' b'\x31\x00\x0c\x3f\x00\x01\x00\x00\x00\x08\x81\x00' b'\x00\x00\x00', b'\x05\x00\x00\x03\xfe\x00\x00\x08\x00', b'\x02\x00\x00\x04\x01\x31', b'\x05\x00\x00\x05\xfe\x00\x00\x08\x00', b'\x07\x00\x00\x06\x00\x01\x00\x08\x00\x00\x00', b'\x01\x00\x00\x07\x01', b'\x17\x00\x00\x08\x03\x64\x65\x66\x00\x00\x00\x01' b'\x32\x00\x0c\x3f\x00\x01\x00\x00\x00\x08\x81\x00' b'\x00\x00\x00', b'\x05\x00\x00\x09\xfe\x00\x00\x00\x00', b'\x02\x00\x00\x0a\x01\x32', b'\x05\x00\x00\x0b\xfe\x00\x00\x00\x00', ] exp = [ {'columns': [('1', 8, None, None, None, None, 0, 129)], 'eof': {'status_flag': 8, 'warning_count': 0}}, ([(b'1',)], {'status_flag': 8, 'warning_count': 0}), {'affected_rows': 1, 'field_count': 0, 'insert_id': 0, 'server_status': 8, 'warning_count': 0}, {'columns': [('2', 8, None, None, None, None, 0, 129)], 'eof': {'status_flag': 0, 'warning_count': 0}}, ([(b'2',)], {'status_flag': 0, 'warning_count': 0}), ] self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets(packets) results = [] stmt = "SELECT 1; SELECT 2".encode('utf-8') for result in self.cnx.cmd_query_iter(stmt): results.append(result) if 'columns' in result: results.append(self.cnx.get_rows()) self.assertEqual(exp, results) def test_cmd_refresh(self): """Send the Refresh-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) refresh = constants.RefreshOption.LOG | constants.RefreshOption.THREADS self.assertEqual(OK_PACKET_RESULT, self.cnx.cmd_refresh(refresh)) def test_cmd_quit(self): """Send the Quit-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.assertEqual(b'\x01', self.cnx.cmd_quit()) def test_cmd_shutdown(self): """Send the Shutdown-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(EOF_PACKET) self.assertEqual(EOF_PACKET_RESULT, self.cnx.cmd_shutdown()) exp = [b'\x02\x00\x00\x00\x08\x00'] self.assertEqual(exp, self.cnx._socket.sock._client_sends) self.cnx._socket.sock.reset() self.assertRaises(errors.InterfaceError, self.cnx.cmd_shutdown, 99) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(EOF_PACKET) self.cnx.cmd_shutdown( constants.ShutdownType.SHUTDOWN_WAIT_CONNECTIONS) exp = [b'\x02\x00\x00\x00\x08\x01'] self.assertEqual(exp, self.cnx._socket.sock._client_sends) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet( b'\x4a\x00\x00\x01\xff\xcb\x04\x23\x34\x32\x30\x30' b'\x30\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69' b'\x65\x64\x3b\x20\x79\x6f\x75\x20\x6e\x65\x65\x64' b'\x20\x74\x68\x65\x20\x53\x48\x55\x54\x44\x4f\x57' b'\x4e\x20\x70\x72\x69\x76\x69\x6c\x65\x67\x65\x20' b'\x66\x6f\x72\x20\x74\x68\x69\x73\x20\x6f\x70\x65' b'\x72\x61\x74\x69\x6f\x6e' ) self.assertRaises(errors.ProgrammingError, self.cnx.cmd_shutdown) def test_cmd_statistics(self): """Send the Statistics-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() goodpkt = b'\x88\x00\x00\x01\x55\x70\x74\x69\x6d\x65\x3a\x20'\ b'\x31\x34\x36\x32\x34\x35\x20\x20\x54\x68\x72\x65'\ b'\x61\x64\x73\x3a\x20\x32\x20\x20\x51\x75\x65\x73'\ b'\x74\x69\x6f\x6e\x73\x3a\x20\x33\x36\x33\x35\x20'\ b'\x20\x53\x6c\x6f\x77\x20\x71\x75\x65\x72\x69\x65'\ b'\x73\x3a\x20\x30\x20\x20\x4f\x70\x65\x6e\x73\x3a'\ b'\x20\x33\x39\x32\x20\x20\x46\x6c\x75\x73\x68\x20'\ b'\x74\x61\x62\x6c\x65\x73\x3a\x20\x31\x20\x20\x4f'\ b'\x70\x65\x6e\x20\x74\x61\x62\x6c\x65\x73\x3a\x20'\ b'\x36\x34\x20\x20\x51\x75\x65\x72\x69\x65\x73\x20'\ b'\x70\x65\x72\x20\x73\x65\x63\x6f\x6e\x64\x20\x61'\ b'\x76\x67\x3a\x20\x30\x2e\x32\x34' self.cnx._socket.sock.add_packet(goodpkt) exp = { 'Uptime': 146245, 'Open tables': 64, 'Queries per second avg': Decimal('0.24'), 'Slow queries': 0, 'Threads': 2, 'Questions': 3635, 'Flush tables': 1, 'Opens': 392 } self.assertEqual(exp, self.cnx.cmd_statistics()) badpkt = b'\x88\x00\x00\x01\x55\x70\x74\x69\x6d\x65\x3a\x20'\ b'\x31\x34\x36\x32\x34\x35\x20\x54\x68\x72\x65'\ b'\x61\x64\x73\x3a\x20\x32\x20\x20\x51\x75\x65\x73'\ b'\x74\x69\x6f\x6e\x73\x3a\x20\x33\x36\x33\x35\x20'\ b'\x20\x53\x6c\x6f\x77\x20\x71\x75\x65\x72\x69\x65'\ b'\x73\x3a\x20\x30\x20\x20\x4f\x70\x65\x6e\x73\x3a'\ b'\x20\x33\x39\x32\x20\x20\x46\x6c\x75\x73\x68\x20'\ b'\x74\x61\x62\x6c\x65\x73\x3a\x20\x31\x20\x20\x4f'\ b'\x70\x65\x6e\x20\x74\x61\x62\x6c\x65\x73\x3a\x20'\ b'\x36\x34\x20\x20\x51\x75\x65\x72\x69\x65\x73\x20'\ b'\x70\x65\x72\x20\x73\x65\x63\x6f\x6e\x64\x20\x61'\ b'\x76\x67\x3a\x20\x30\x2e\x32\x34' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(badpkt) self.assertRaises(errors.InterfaceError, self.cnx.cmd_statistics) badpkt = b'\x88\x00\x00\x01\x55\x70\x74\x69\x6d\x65\x3a\x20'\ b'\x55\x70\x36\x32\x34\x35\x20\x20\x54\x68\x72\x65'\ b'\x61\x64\x73\x3a\x20\x32\x20\x20\x51\x75\x65\x73'\ b'\x74\x69\x6f\x6e\x73\x3a\x20\x33\x36\x33\x35\x20'\ b'\x20\x53\x6c\x6f\x77\x20\x71\x75\x65\x72\x69\x65'\ b'\x73\x3a\x20\x30\x20\x20\x4f\x70\x65\x6e\x73\x3a'\ b'\x20\x33\x39\x32\x20\x20\x46\x6c\x75\x73\x68\x20'\ b'\x74\x61\x62\x6c\x65\x73\x3a\x20\x31\x20\x20\x4f'\ b'\x70\x65\x6e\x20\x74\x61\x62\x6c\x65\x73\x3a\x20'\ b'\x36\x34\x20\x20\x51\x75\x65\x72\x69\x65\x73\x20'\ b'\x70\x65\x72\x20\x73\x65\x63\x6f\x6e\x64\x20\x61'\ b'\x76\x67\x3a\x20\x30\x2e\x32\x34' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(badpkt) self.assertRaises(errors.InterfaceError, self.cnx.cmd_statistics) def test_cmd_process_info(self): """Send the Process-Info-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.assertRaises(errors.NotSupportedError, self.cnx.cmd_process_info) def test_cmd_process_kill(self): """Send the Process-Kill-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) self.assertEqual(OK_PACKET_RESULT, self.cnx.cmd_process_kill(1)) pkt = b'\x1f\x00\x00\x01\xff\x46\x04\x23\x48\x59\x30\x30'\ b'\x30\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x74\x68\x72'\ b'\x65\x61\x64\x20\x69\x64\x3a\x20\x31\x30\x30' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(pkt) self.assertRaises(errors.DatabaseError, self.cnx.cmd_process_kill, 100) pkt = b'\x29\x00\x00\x01\xff\x47\x04\x23\x48\x59\x30\x30'\ b'\x30\x59\x6f\x75\x20\x61\x72\x65\x20\x6e\x6f\x74'\ b'\x20\x6f\x77\x6e\x65\x72\x20\x6f\x66\x20\x74\x68'\ b'\x72\x65\x61\x64\x20\x31\x36\x30\x35' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(pkt) self.assertRaises(errors.DatabaseError, self.cnx.cmd_process_kill, 1605) def test_cmd_debug(self): """Send the Debug-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() pkt = b'\x05\x00\x00\x01\xfe\x00\x00\x00\x00' self.cnx._socket.sock.add_packet(pkt) exp = { 'status_flag': 0, 'warning_count': 0 } self.assertEqual(exp, self.cnx.cmd_debug()) pkt = b'\x47\x00\x00\x01\xff\xcb\x04\x23\x34\x32\x30\x30'\ b'\x30\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69'\ b'\x65\x64\x3b\x20\x79\x6f\x75\x20\x6e\x65\x65\x64'\ b'\x20\x74\x68\x65\x20\x53\x55\x50\x45\x52\x20\x70'\ b'\x72\x69\x76\x69\x6c\x65\x67\x65\x20\x66\x6f\x72'\ b'\x20\x74\x68\x69\x73\x20\x6f\x70\x65\x72\x61\x74'\ b'\x69\x6f\x6e' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(pkt) self.assertRaises(errors.ProgrammingError, self.cnx.cmd_debug) def test_cmd_ping(self): """Send the Ping-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._socket.sock.add_packet(OK_PACKET) self.assertEqual(OK_PACKET_RESULT, self.cnx.cmd_ping()) self.assertRaises(errors.Error, self.cnx.cmd_ping) def test_cmd_change_user(self): """Send the Change-User-command to MySQL""" self.cnx._socket.sock = tests.DummySocket() self.cnx._handshake = { 'protocol': 10, 'server_version_original': '5.0.30-enterprise-gpl-log', 'charset': 8, 'server_threadid': 265, 'capabilities': 41516, 'server_status': 2, 'scramble': b'h4i6oP!OLng9&PD@WrYH' } self.cnx._socket.sock.add_packet(OK_PACKET) exp = OK_PACKET_RESULT.copy() exp['server_status'] = 2 self.cnx.cmd_change_user(username='ham', password='spam', database='python') self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet( b'\x45\x00\x00\x01\xff\x14\x04\x23\x34\x32\x30\x30' b'\x30\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69' b'\x65\x64\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20' b'\x27\x68\x61\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c' b'\x68\x6f\x73\x74\x27\x20\x74\x6f\x20\x64\x61\x74' b'\x61\x62\x61\x73\x65\x20\x27\x6d\x79\x73\x71\x6c' b'\x27') self.assertRaises(errors.ProgrammingError, self.cnx.cmd_change_user, username='ham', password='spam', database='mysql') def test__do_handshake(self): """Handle the handshake-packet sent by MySQL""" self.cnx._socket.sock = tests.DummySocket() handshake = \ b'\x47\x00\x00\x00\x0a\x35\x2e\x30\x2e\x33\x30\x2d'\ b'\x65\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67'\ b'\x70\x6c\x2d\x6c\x6f\x67\x00\x09\x01\x00\x00\x68'\ b'\x34\x69\x36\x6f\x50\x21\x4f\x00\x2c\xa2\x08\x02'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72'\ b'\x59\x48\x00' exp = { 'protocol': 10, 'server_version_original': b'5.0.30-enterprise-gpl-log', 'charset': 8, 'server_threadid': 265, 'capabilities': 41516, 'server_status': 2, 'scramble': b'h4i6oP!OLng9&PD@WrYH' } self.cnx._socket.sock.add_packet(handshake) self.cnx._do_handshake() self.assertEqual(exp, self.cnx._handshake) self.assertRaises(errors.InterfaceError, self.cnx._do_handshake) # Handshake with version set to Z.Z.ZZ to simulate bad version false_handshake = \ b'\x47\x00\x00\x00\x0a\x5a\x2e\x5a\x2e\x5a\x5a\x2d'\ b'\x65\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67'\ b'\x70\x6c\x2d\x6c\x6f\x67\x00\x09\x01\x00\x00\x68'\ b'\x34\x69\x36\x6f\x50\x21\x4f\x00\x2c\xa2\x08\x02'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72'\ b'\x59\x48\x00' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(false_handshake) self.assertRaises(errors.InterfaceError, self.cnx._do_handshake) # Handshake with version set to 4.0.23 unsupported_handshake = \ b'\x47\x00\x00\x00\x0a\x34\x2e\x30\x2e\x32\x33\x2d'\ b'\x65\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67'\ b'\x70\x6c\x2d\x6c\x6f\x67\x00\x09\x01\x00\x00\x68'\ b'\x34\x69\x36\x6f\x50\x21\x4f\x00\x2c\xa2\x08\x02'\ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ b'\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72'\ b'\x59\x48\x00' self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(unsupported_handshake) self.assertRaises(errors.InterfaceError, self.cnx._do_handshake) def test__do_auth(self): """Authenticate with the MySQL server""" self.cnx._socket.sock = tests.DummySocket() flags = constants.ClientFlag.get_default() kwargs = { 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 33, 'client_flags': flags, } self.cnx._socket.sock.add_packet(OK_PACKET) self.assertEqual(True, self.cnx._do_auth(**kwargs)) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(b'\x01\x00\x00\x02\xfe') self.assertRaises(errors.NotSupportedError, self.cnx._do_auth, **kwargs) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ b'\x07\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00', b'\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00']) self.cnx.set_client_flags([-constants.ClientFlag.CONNECT_WITH_DB]) self.assertEqual(True, self.cnx._do_auth(**kwargs)) # Using an unknown database should raise an error self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ b'\x07\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00', b'\x24\x00\x00\x01\xff\x19\x04\x23\x34\x32\x30\x30' b'\x30\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x64\x61\x74' b'\x61\x62\x61\x73\x65\x20\x27\x61\x73\x64\x66\x61' b'\x73\x64\x66\x27']) flags &= ~constants.ClientFlag.CONNECT_WITH_DB kwargs['client_flags'] = flags self.assertRaises(errors.ProgrammingError, self.cnx._do_auth, **kwargs) @unittest.skipIf(not tests.SSL_AVAILABLE, "Python has no SSL support") def test__do_auth_ssl(self): """Authenticate with the MySQL server using SSL""" self.cnx._socket.sock = tests.DummySocket() flags = constants.ClientFlag.get_default() flags |= constants.ClientFlag.SSL kwargs = { 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 33, 'client_flags': flags, 'ssl_options': { 'ca': os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem'), 'cert': os.path.join(tests.SSL_DIR, 'tests_client_cert.pem'), 'key': os.path.join(tests.SSL_DIR, 'tests_client_key.pem'), }, } self.cnx._handshake['scramble'] = b'h4i6oP!OLng9&PD@WrYH' # We check if do_auth send the autherization for SSL and the # normal authorization. exp = [ self.cnx._protocol.make_auth_ssl( charset=kwargs['charset'], client_flags=kwargs['client_flags']), self.cnx._protocol.make_auth( self.cnx._handshake['scramble'], kwargs['username'], kwargs['password'], kwargs['database'], charset=kwargs['charset'], client_flags=kwargs['client_flags']), ] self.cnx._socket.switch_to_ssl = lambda ca, cert, key: None self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ b'\x07\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00', b'\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00']) self.cnx._do_auth(**kwargs) self.assertEqual( exp, [p[4:] for p in self.cnx._socket.sock._client_sends]) def test_config(self): """Configure the MySQL connection These tests do not actually connect to MySQL, but they make sure everything is setup before calling _open_connection() and _post_connection(). """ cnx = _DummyMySQLConnection() default_config = connection.DEFAULT_CONFIGURATION.copy() # Should fail because 'dsn' is given self.assertRaises(errors.NotSupportedError, cnx.config, **default_config) # Remove unsupported arguments del default_config['dsn'] default_config.update({ 'ssl_ca': 'CACert', 'ssl_cert': 'ServerCert', 'ssl_key': 'ServerKey', 'ssl_verify_cert': False }) try: cnx.config(**default_config) except AttributeError as err: self.fail("Config does not accept a supported" " argument: {}".format(str(err))) # Add an argument which we don't allow default_config['spam'] = 'SPAM' self.assertRaises(AttributeError, cnx.config, **default_config) # We do not support dsn self.assertRaises(errors.NotSupportedError, cnx.connect, dsn='ham') exp = { 'host': 'localhost.local', 'port': 3306, 'unix_socket': '/tmp/mysql.sock' } cnx.config(**exp) self.assertEqual(exp['port'], cnx._port) self.assertEqual(exp['host'], cnx._host) self.assertEqual(exp['unix_socket'], cnx._unix_socket) exp = (None, 'test', 'mysql ') for database in exp: cnx.config(database=database) if database is not None: database = database.strip() failmsg = "Failed setting database to '{0}'".format(database) self.assertEqual(database, cnx._database, msg=failmsg) cnx.config(user='ham') self.assertEqual('ham', cnx._user) cnx.config(raise_on_warnings=True) self.assertEqual(True, cnx._raise_on_warnings) cnx.config(get_warnings=False) self.assertEqual(False, cnx._get_warnings) cnx.config(connection_timeout=123) self.assertEqual(123, cnx._connection_timeout) for toggle in [True, False]: cnx.config(buffered=toggle) self.assertEqual(toggle, cnx._buffered) cnx.config(raw=toggle) self.assertEqual(toggle, cnx._raw) for toggle in [False, True]: cnx.config(use_unicode=toggle) self.assertEqual(toggle, cnx._use_unicode) # Test client flags cnx = _DummyMySQLConnection() cnx.set_client_flags(constants.ClientFlag.get_default()) flag = exp = constants.ClientFlag.COMPRESS cnx.config(client_flags=flag) self.assertEqual(exp, cnx._client_flags) # Setting client flags using a list cnx = _DummyMySQLConnection() cnx.set_client_flags(constants.ClientFlag.get_default()) flags = [constants.ClientFlag.COMPRESS, constants.ClientFlag.FOUND_ROWS] exp = constants.ClientFlag.get_default() for flag in flags: exp |= flag cnx.config(client_flags=flags) self.assertEqual(exp, cnx._client_flags) # and unsetting client flags again exp = constants.ClientFlag.get_default() flags = [-constants.ClientFlag.COMPRESS, -constants.ClientFlag.FOUND_ROWS] cnx.config(client_flags=flags) self.assertEqual(exp, cnx._client_flags) # Test compress argument cnx.config(compress=True) exp = constants.ClientFlag.COMPRESS self.assertEqual(exp, cnx._client_flags & constants.ClientFlag.COMPRESS) # Test character set # utf8 is default, which is mapped to 33 self.assertEqual(33, cnx._charset_id) cnx.config(charset='latin1') self.assertEqual(8, cnx._charset_id) cnx.config(charset='latin1', collation='latin1_general_ci') self.assertEqual(48, cnx._charset_id) cnx.config(collation='latin1_general_ci') self.assertEqual(48, cnx._charset_id) # Test converter class class TestConverter(MySQLConverterBase): def __init__(self, charset=None, unicode=True): pass self.cnx.config(converter_class=TestConverter) self.assertTrue(isinstance(self.cnx.converter, TestConverter)) self.assertEqual(self.cnx._converter_class, TestConverter) class TestConverterWrong(object): def __init__(self, charset, unicode): pass self.assertRaises(AttributeError, self.cnx.config, converter_class=TestConverterWrong) # Test SSL configuration exp = { 'ca': 'CACert', 'cert': 'ServerCert', 'key': 'ServerKey', 'verify_cert': False } cnx.config(ssl_ca=exp['ca'], ssl_cert=exp['cert'], ssl_key=exp['key']) self.assertEqual(exp, cnx._ssl) exp['verify_cert'] = True cnx.config(ssl_ca=exp['ca'], ssl_cert=exp['cert'], ssl_key=exp['key'], ssl_verify_cert=exp['verify_cert']) self.assertEqual(exp, cnx._ssl) # Missing SSL configuration should raise an AttributeError cnx._ssl = {} try: cnx.config(ssl_ca=exp['ca']) except AttributeError as err: errmsg = str(err) self.assertTrue('ssl_cert' in errmsg and 'ssl_key' in errmsg) else: self.fail("Testing SSL attributes failed.") cnx._ssl = {} try: cnx.config(ssl_ca=exp['ca'], ssl_cert=exp['cert']) except AttributeError as err: errmsg = str(err) self.assertTrue('ssl_key' in errmsg) else: self.fail("Testing SSL attributes failed.") cnx._ssl = {} try: cnx.config(ssl_verify_cert=True) except AttributeError as err: errmsg = str(err) self.assertTrue('ssl_key' in errmsg and 'ssl_cert' in errmsg and 'ssl_ca' in errmsg) else: self.fail("Testing SSL attributes failed.") # Compatibility tests: MySQLdb cnx = _DummyMySQLConnection() cnx.connect(db='mysql', passwd='spam', connect_timeout=123) self.assertEqual('mysql', cnx._database) self.assertEqual('spam', cnx._password) self.assertEqual(123, cnx._connection_timeout) def test__get_connection(self): """Get connection based on configuration""" if os.name != 'nt': res = self.cnx._get_connection() self.assertTrue(isinstance(res, network.MySQLUnixSocket)) self.cnx._unix_socket = None self.cnx._connection_timeout = 123 res = self.cnx._get_connection() self.assertTrue(isinstance(res, network.MySQLTCPSocket)) self.assertEqual(self.cnx._connection_timeout, res._connection_timeout) def test__open_connection(self): """Open the connection to the MySQL server""" # Force TCP Connection self.cnx._unix_socket = None self.cnx._open_connection() self.assertTrue(isinstance(self.cnx._socket, network.MySQLTCPSocket)) self.cnx.close() self.cnx._client_flags |= constants.ClientFlag.COMPRESS self.cnx._open_connection() self.assertEqual(self.cnx._socket.recv_compressed, self.cnx._socket.recv) self.assertEqual(self.cnx._socket.send_compressed, self.cnx._socket.send) def test__post_connection(self): """Executes commands after connection has been established""" self.cnx._charset_id = 33 self.cnx._autocommit = True self.cnx._time_zone = "-09:00" self.cnx._sql_mode = "NO_ZERO_DATE" self.cnx._post_connection() self.assertEqual('utf8', self.cnx.charset) self.assertEqual(self.cnx._autocommit, self.cnx.autocommit) self.assertEqual(self.cnx._time_zone, self.cnx.time_zone) self.assertEqual(self.cnx._sql_mode, self.cnx.sql_mode) def test_connect(self): """Connect to the MySQL server""" config = tests.get_mysql_config() config['unix_socket'] = None config['connection_timeout'] = 1 cnx = connection.MySQLConnection() config['host'] = tests.get_mysql_config()['host'] try: cnx.connect(**config) cnx.close() except errors.Error as err: self.fail("Failed connecting to '{}': {}".format( config['host'], str(err))) config['host'] = tests.fake_hostname() self.assertRaises(errors.InterfaceError, cnx.connect, **config) def test_is_connected(self): """Check connection to MySQL Server""" self.assertEqual(True, self.cnx.is_connected()) self.cnx.disconnect() self.assertEqual(False, self.cnx.is_connected()) def test_reconnect(self): """Reconnecting to the MySQL Server""" supported_arguments = { 'attempts': 1, 'delay': 0, } self.check_args(self.cnx.reconnect, supported_arguments) def _test_reconnect_delay(): config = { 'unix_socket': None, 'host': tests.fake_hostname(), 'connection_timeout': 1, } cnx = connection.MySQLConnection() cnx.config(**config) try: cnx.reconnect(attempts=2, delay=3) except: pass # Check the delay timer = timeit.Timer(_test_reconnect_delay) result = timer.timeit(number=1) self.assertTrue(result > 3 and result < 12, "3 <= result < 12, was {0}".format(result)) # Check reconnect stops when successful config = tests.get_mysql_config() cnx = connection.MySQLConnection() cnx.connect(**config) conn_id = cnx.connection_id cnx.reconnect(attempts=5) exp = conn_id + 1 self.assertEqual(exp, cnx.connection_id) def test_ping(self): """Ping the MySQL server""" supported_arguments = { 'reconnect': False, 'attempts': 1, 'delay': 0, } self.check_args(self.cnx.ping, supported_arguments) try: self.cnx.ping() except errors.InterfaceError: self.fail("Ping should have not raised an error") self.cnx.disconnect() self.assertRaises(errors.InterfaceError, self.cnx.ping) def test_set_converter_class(self): """Set the converter class""" class TestConverterWrong(object): def __init__(self, charset, unicode): pass self.assertRaises(TypeError, self.cnx.set_converter_class, TestConverterWrong) class TestConverter(MySQLConverterBase): def __init__(self, charset, unicode): pass self.cnx.set_converter_class(TestConverter) self.assertTrue(isinstance(self.cnx.converter, TestConverter)) self.assertEqual(self.cnx._converter_class, TestConverter) def test_get_server_version(self): """Get the MySQL version""" self.assertEqual(self.cnx._server_version, self.cnx.get_server_version()) def test_get_server_info(self): """Get the original MySQL version information""" self.assertEqual(self.cnx._handshake['server_version_original'], self.cnx.get_server_info()) del self.cnx._handshake['server_version_original'] self.assertEqual(None, self.cnx.get_server_info()) def test_connection_id(self): """MySQL connection ID""" self.assertEqual(self.cnx._handshake['server_threadid'], self.cnx.connection_id) del self.cnx._handshake['server_threadid'] self.assertEqual(None, self.cnx.connection_id) def test_set_login(self): """Set login information for MySQL""" exp = ('Ham ', ' Spam ') self.cnx.set_login(*exp) self.assertEqual(exp[0].strip(), self.cnx._user) self.assertEqual(exp[1].strip(), self.cnx._password) self.cnx.set_login() self.assertEqual('', self.cnx._user) self.assertEqual('', self.cnx._password) def test__set_unread_result(self): """Toggle unread result set""" self.cnx._set_unread_result(True) self.assertEqual(True, self.cnx._unread_result) self.cnx._set_unread_result(False) self.assertEqual(False, self.cnx._unread_result) self.assertRaises(ValueError, self.cnx._set_unread_result, 1) def test__get_unread_result(self): """Check for unread result set""" self.cnx._unread_result = True self.assertEqual(True, self.cnx._get_unread_result()) self.cnx._unread_result = False self.assertEqual(False, self.cnx._get_unread_result()) def test_unread_results(self): """Check and toggle unread result using property""" self.cnx.unread_result = True self.assertEqual(True, self.cnx._unread_result) self.cnx.unread_result = False self.assertEqual(False, self.cnx._unread_result) try: self.cnx.unread_result = 1 except ValueError: pass # Expected except: self.fail("Expected ValueError to be raised") def test__set_getwarnings(self): """Toggle whether to get warnings""" self.cnx._set_getwarnings(True) self.assertEqual(True, self.cnx._get_warnings) self.cnx._set_getwarnings(False) self.assertEqual(False, self.cnx._get_warnings) self.assertRaises(ValueError, self.cnx._set_getwarnings, 1) def test__get_getwarnings(self): """Check whether we need to get warnings""" self.cnx._get_warnings = True self.assertEqual(True, self.cnx._get_getwarnings()) self.cnx._get_warnings = False self.assertEqual(False, self.cnx._get_getwarnings()) def test_get_warnings(self): """Check and toggle the get_warnings property""" self.cnx.get_warnings = True self.assertEqual(True, self.cnx._get_warnings) self.cnx.get_warnings = False self.assertEqual(False, self.cnx._get_warnings) try: self.cnx.get_warnings = 1 except ValueError: pass # Expected except: self.fail("Expected ValueError to be raised") def test_set_charset_collation(self): """Set the character set and collation""" self.cnx.set_charset_collation('latin1') self.assertEqual(8, self.cnx._charset_id) self.cnx.set_charset_collation('latin1', 'latin1_general_ci') self.assertEqual(48, self.cnx._charset_id) self.cnx.set_charset_collation('latin1', None) self.assertEqual(8, self.cnx._charset_id) self.cnx.set_charset_collation(collation='greek_bin') self.assertEqual(70, self.cnx._charset_id) self.assertRaises(errors.ProgrammingError, self.cnx.set_charset_collation, 666) self.assertRaises(errors.ProgrammingError, self.cnx.set_charset_collation, 'spam') self.assertRaises(errors.ProgrammingError, self.cnx.set_charset_collation, 'latin1', 'spam') self.assertRaises(errors.ProgrammingError, self.cnx.set_charset_collation, None, 'spam') self.assertRaises(ValueError, self.cnx.set_charset_collation, object()) def test_charset(self): """Get character set name""" self.cnx.set_charset_collation('latin1', 'latin1_general_ci') self.assertEqual('latin1', self.cnx.charset) self.cnx._charset_id = 70 self.assertEqual('greek', self.cnx.charset) self.cnx._charset_id = 9 self.assertEqual('latin2', self.cnx.charset) self.cnx._charset_id = 1234567 try: self.cnx.charset except errors.ProgrammingError: pass # This is expected except: self.fail("Expected errors.ProgrammingError to be raised") def test_collation(self): """Get collation name""" exp = 'latin2_general_ci' self.cnx.set_charset_collation(collation=exp) self.assertEqual(exp, self.cnx.collation) self.cnx._charset_id = 70 self.assertEqual('greek_bin', self.cnx.collation) self.cnx._charset_id = 9 self.assertEqual('latin2_general_ci', self.cnx.collation) self.cnx._charset_id = 1234567 try: self.cnx.collation except errors.ProgrammingError: pass # This is expected except: self.fail("Expected errors.ProgrammingError to be raised") def test_set_client_flags(self): """Set the client flags""" self.assertRaises(errors.ProgrammingError, self.cnx.set_client_flags, 'Spam') self.assertRaises(errors.ProgrammingError, self.cnx.set_client_flags, 0) default_flags = constants.ClientFlag.get_default() exp = default_flags self.assertEqual(exp, self.cnx.set_client_flags(exp)) self.assertEqual(exp, self.cnx._client_flags) exp = default_flags exp |= constants.ClientFlag.SSL exp |= constants.ClientFlag.FOUND_ROWS exp &= ~constants.ClientFlag.MULTI_RESULTS flags = [ constants.ClientFlag.SSL, constants.ClientFlag.FOUND_ROWS, -constants.ClientFlag.MULTI_RESULTS ] self.assertEqual(exp, self.cnx.set_client_flags(flags)) self.assertEqual(exp, self.cnx._client_flags) def test_user(self): exp = 'ham' self.cnx._user = exp self.assertEqual(exp, self.cnx.user) def test_host(self): exp = 'ham' self.cnx._host = exp self.assertEqual(exp, self.cnx.server_host) def test_port(self): exp = 'ham' self.cnx._port = exp self.assertEqual(exp, self.cnx.server_port) def test_unix_socket(self): exp = 'ham' self.cnx._unix_socket = exp self.assertEqual(exp, self.cnx.unix_socket) def test_set_database(self): exp = 'mysql' self.cnx.set_database(exp) self.assertEqual(exp, self.cnx._info_query("SELECT DATABASE()")[0]) def test_get_database(self): exp = self.cnx._info_query("SELECT DATABASE()")[0] self.assertEqual(exp, self.cnx.get_database()) def test_database(self): exp = 'mysql' self.cnx.database = exp self.assertEqual(exp, self.cnx.database) def test_set_time_zone(self): """Set the time zone for current MySQL session""" cnx = _DummyMySQLConnection() exp = "-09:00" cnx.connect(time_zone=exp) self.assertEqual(exp, cnx._time_zone) exp = "+03:00" self.cnx.set_time_zone(exp) self.assertEqual(exp, self.cnx._time_zone) res = self.cnx._info_query("SELECT @@session.time_zone")[0] self.assertEqual(exp, res) def test_get_time_zone(self): """Get the time zone from current MySQL Session""" exp = "-08:00" self.cnx._info_query("SET @@session.time_zone = '{0}'".format(exp)) self.assertEqual(exp, self.cnx.get_time_zone()) def test_time_zone(self): """Set and get the time zone through property""" exp = "+05:00" self.cnx.time_zone = exp self.assertEqual(exp, self.cnx._time_zone) self.assertEqual(exp, self.cnx.time_zone) self.assertEqual(self.cnx.get_time_zone(), self.cnx.time_zone) def test_set_sql_mode(self): """Set SQL Mode""" # Use an unknown SQL Mode self.assertRaises( errors.ProgrammingError, self.cnx.set_sql_mode, 'HAM') # Set an SQL Mode try: self.cnx.set_sql_mode('TRADITIONAL') except errors.Error: self.fail("Failed setting SQL Mode") # Set SQL Mode to a list of modes exp = ('STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,' 'NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,' 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION') try: self.cnx.set_sql_mode(exp) result = self.cnx.get_sql_mode() except errors.Error as err: self.fail( "Failed setting SQL Mode with multiple modes: {0}".format( str(err))) self.assertEqual(exp, result) exp = sorted([ constants.SQLMode.NO_ZERO_DATE, constants.SQLMode.REAL_AS_FLOAT ]) self.cnx.sql_mode = exp self.assertEqual(exp, sorted(self.cnx.sql_mode.split(','))) def test_get_sql_mode(self): """Get SQL Mode""" config = tests.get_mysql_config() config['sql_mode'] = '' self.cnx = connection.MySQLConnection(**config) # SQL Modes must be empty self.assertEqual('', self.cnx.get_sql_mode()) # Set SQL Mode and check sql_mode = exp = 'NO_ZERO_IN_DATE' self.cnx.set_sql_mode(sql_mode) self.assertEqual(exp, self.cnx.get_sql_mode()) # Unset the SQL Mode again self.cnx.set_sql_mode('') self.assertEqual('', self.cnx.get_sql_mode()) def test_sql_mode(self): """Set and get SQL Mode through property""" config = tests.get_mysql_config() config['sql_mode'] = '' self.cnx = connection.MySQLConnection(**config) sql_mode = exp = 'NO_ZERO_IN_DATE' self.cnx.sql_mode = sql_mode self.assertEqual(exp, self.cnx.sql_mode) def test_set_autocommit(self): self.cnx.set_autocommit(True) res = self.cnx._info_query("SELECT @@session.autocommit")[0] self.assertEqual(1, res) self.cnx.set_autocommit(0) res = self.cnx._info_query("SELECT @@session.autocommit")[0] self.assertEqual(0, res) def test_get_autocommit(self): cases = [False, True] for exp in cases: self.cnx.set_autocommit(exp) res = self.cnx._info_query("SELECT @@session.autocommit")[0] self.assertEqual(exp, cases[res]) def test_autocommit(self): for exp in [False, True]: self.cnx.autocommit = exp self.assertEqual(exp, self.cnx.autocommit) def test__set_raise_on_warnings(self): """Toggle whether to get warnings""" self.cnx._set_raise_on_warnings(True) self.assertEqual(True, self.cnx._raise_on_warnings) self.cnx._set_raise_on_warnings(False) self.assertEqual(False, self.cnx._raise_on_warnings) self.assertRaises(ValueError, self.cnx._set_raise_on_warnings, 1) def test__get_raise_on_warnings(self): """Check whether we need to get warnings""" self.cnx._raise_on_warnings = True self.assertEqual(True, self.cnx._get_raise_on_warnings()) self.cnx._raise_on_warnings = False self.assertEqual(False, self.cnx._get_raise_on_warnings()) def test_raise_on_warnings(self): """Check and toggle the get_warnings property""" self.cnx.raise_on_warnings = True self.assertEqual(True, self.cnx._get_raise_on_warnings()) self.cnx.raise_on_warnings = False self.assertEqual(False, self.cnx._get_raise_on_warnings()) try: self.cnx.raise_on_warnings = 1 except ValueError: pass # Expected except: self.fail("Expected ValueError to be raised") def test_cursor(self): class FalseCursor(object): pass class TrueCursor(cursor.CursorBase): def __init__(self, connection=None): if sys.version_info[0] == 2: super(TrueCursor, self).__init__() else: super().__init__() self.assertRaises(errors.ProgrammingError, self.cnx.cursor, cursor_class=FalseCursor) self.assertTrue(isinstance(self.cnx.cursor(cursor_class=TrueCursor), TrueCursor)) cases = [ ({}, cursor.MySQLCursor), ({'buffered': True}, cursor.MySQLCursorBuffered), ({'raw': True}, cursor.MySQLCursorRaw), ({'buffered': True, 'raw': True}, cursor.MySQLCursorBufferedRaw), ] for kwargs, exp in cases: self.assertTrue(isinstance(self.cnx.cursor(**kwargs), exp)) # Test when connection is closed self.cnx.close() self.assertRaises(errors.OperationalError, self.cnx.cursor) def test__send_data(self): self.assertRaises(ValueError, self.cnx._send_data, 'spam') self.cnx._socket.sock = tests.DummySocket() data = b"1\tham\t'ham spam'\n2\tfoo\t'foo bar'" fp = io.BytesIO(data) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(OK_PACKET) exp = [ b"\x20\x00\x00\x02\x31\x09\x68\x61\x6d\x09\x27\x68\x61\x6d" b"\x20\x73\x70\x61\x6d\x27\x0a\x32\x09\x66\x6f\x6f\x09\x27" b"\x66\x6f\x6f\x20\x62\x61\x72\x27" ] self.assertEqual(OK_PACKET, self.cnx._send_data(fp, False)) self.assertEqual(exp, self.cnx._socket.sock._client_sends) fp = io.BytesIO(data) self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packet(OK_PACKET) exp.append(b'\x00\x00\x00\x03') self.assertEqual(OK_PACKET, self.cnx._send_data(fp, True)) self.assertEqual(exp, self.cnx._socket.sock._client_sends) fp = io.BytesIO(data) self.cnx._socket = None self.assertRaises(errors.OperationalError, self.cnx._send_data, fp, False) # Nothing to read, but try to send empty packet self.assertRaises(errors.OperationalError, self.cnx._send_data, fp, True) def test_in_transaction(self): self.cnx.cmd_query('START TRANSACTION') self.assertTrue(self.cnx.in_transaction) self.cnx.cmd_query('ROLLBACK') self.assertFalse(self.cnx.in_transaction) # AUTO_COMMIT turned ON self.cnx.autocommit = True self.assertFalse(self.cnx.in_transaction) self.cnx.cmd_query('START TRANSACTION') self.assertTrue(self.cnx.in_transaction) def test_start_transaction(self): self.cnx.start_transaction() self.assertTrue(self.cnx.in_transaction) self.cnx.rollback() self.cnx.start_transaction(consistent_snapshot=True) self.assertTrue(self.cnx.in_transaction) self.assertRaises(errors.ProgrammingError, self.cnx.start_transaction) self.cnx.rollback() levels = ['READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ', 'SERIALIZABLE', 'READ-UNCOMMITTED', 'READ-COMMITTED', 'REPEATABLE-READ', 'SERIALIZABLE'] for level in levels: level = level.replace(' ', '-') self.cnx.start_transaction(isolation_level=level) self.assertTrue(self.cnx.in_transaction) self.cnx.rollback() self.assertRaises(ValueError, self.cnx.start_transaction, isolation_level='spam') def test__handle_binary_ok(self): """Handle a Binary OK packet""" packet = ( b'\x0c\x00\x00\x01' b'\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ) exp = { 'num_params': 0, 'statement_id': 1, 'warning_count': 0, 'num_columns': 0 } self.assertEqual(exp, self.cnx._handle_binary_ok(packet)) # Raise an error packet = ( b'\x2a\x00\x00\x01\xff\x19\x05\x23\x34\x32\x30\x30\x30\x46\x55' b'\x4e\x43\x54\x49\x4f\x4e\x20\x74\x65\x73\x74\x2e\x53\x50\x41' b'\x4d\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x65\x78\x69\x73\x74' ) self.assertRaises(errors.ProgrammingError, self.cnx._handle_binary_ok, packet) def test_cmd_stmt_prepare(self): """Prepare a MySQL statement""" self.cnx._socket.sock = tests.DummySocket() stmt = b"SELECT CONCAT(?, ?) AS c1" self.cnx._socket.sock.add_packets([ b'\x0c\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00', b'\x17\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01\x3f\x00\x0c' b'\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00', b'\x17\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x01\x3f\x00\x0c' b'\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00', EOF_PACKET, b'\x18\x00\x00\x05\x03\x64\x65\x66\x00\x00\x00\x02\x63\x31\x00' b'\x0c\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x1f\x00\x00', EOF_PACKET ]) exp = { 'num_params': 2, 'statement_id': 1, 'parameters': [ ('?', 253, None, None, None, None, 1, 128), ('?', 253, None, None, None, None, 1, 128) ], 'warning_count': 0, 'num_columns': 1, 'columns': [('c1', 253, None, None, None, None, 1, 128)] } self.assertEqual(exp, self.cnx.cmd_stmt_prepare(stmt)) stmt = b"DO 1" self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ b'\x0c\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ]) exp = { 'num_params': 0, 'statement_id': 1, 'parameters': [], 'warning_count': 0, 'num_columns': 0, 'columns': [] } self.assertEqual(exp, self.cnx.cmd_stmt_prepare(stmt)) # Raise an error using illegal SPAM() MySQL function stmt = b"SELECT SPAM(?) AS c1" self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ b'\x2a\x00\x00\x01\xff\x19\x05\x23\x34\x32\x30\x30\x30\x46\x55' b'\x4e\x43\x54\x49\x4f\x4e\x20\x74\x65\x73\x74\x2e\x53\x50\x41' b'\x4d\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x65\x78\x69\x73\x74' ]) self.assertRaises(errors.ProgrammingError, self.cnx.cmd_stmt_prepare, stmt) def test__handle_binary_result(self): self.cnx._socket.sock = tests.DummySocket() self.assertRaises(errors.InterfaceError, self.cnx._handle_binary_result, None) self.assertRaises(errors.InterfaceError, self.cnx._handle_binary_result, b'\x00\x00\x00') self.assertEqual(OK_PACKET_RESULT, self.cnx._handle_binary_result(OK_PACKET)) self.assertEqual(EOF_PACKET_RESULT, self.cnx._handle_binary_result(EOF_PACKET)) self.assertRaises(errors.ProgrammingError, self.cnx._handle_binary_result, ERR_PACKET) # handle result set self.cnx._socket.sock.reset() self.cnx._socket.sock.add_packets([ (b'\x18\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x02\x63\x31\x00' b'\x0c\x21\x00\x09\x00\x00\x00\xfd\x01\x00\x00\x00\x00'), EOF_PACKET, ]) exp = ( 1, [('c1', 253, None, None, None, None, 0, 1)], {'status_flag': 0, 'warning_count': 0} ) self.assertEqual( exp, self.cnx._handle_binary_result(b'\x01\x00\x00\x01\x01')) def test_cmd_stmt_execute(self): stmt = b"SELECT ? as c1" params = ( 1, ('ham',), [('c1', 253, None, None, None, None, 1, 128)], 0 ) # statement does not exists self.assertRaises(errors.DatabaseError, self.cnx.cmd_stmt_execute, *params) # prepare and execute self.cnx.cmd_stmt_prepare(stmt) exp = ( 1, [('c1', 253, None, None, None, None, 0, 1)], {'status_flag': 0, 'warning_count': 0} ) self.assertEqual(exp, self.cnx.cmd_stmt_execute(*params)) def test_cmd_stmt_close(self): # statement does not exists, does not return or raise anything try: self.cnx.cmd_stmt_close(99) except errors.Error as err: self.fail("cmd_stmt_close raised: {0}".format(err)) # after closing, should not be able to execute stmt_info = self.cnx.cmd_stmt_prepare(b"SELECT ? as c1") self.cnx.cmd_stmt_close(stmt_info['statement_id']) params = ( stmt_info['statement_id'], ('ham',), stmt_info['parameters'], 0 ) self.assertRaises(errors.ProgrammingError, self.cnx.cmd_stmt_execute, *params) mysql-connector-python-1.1.6/tests/test_pooling.py0000644001577100000120000003165012276514013021671 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.pooling """ import uuid try: from Queue import Queue except ImportError: # Python 3 from queue import Queue import tests import mysql.connector as myconn from mysql.connector import errors from mysql.connector.connection import MySQLConnection from mysql.connector import pooling class PoolingTests(tests.MySQLConnectorTests): def test_generate_pool_name(self): self.assertRaises(errors.PoolError, pooling.generate_pool_name) config = {'host': 'ham', 'database': 'spam'} self.assertEqual('ham_spam', pooling.generate_pool_name(**config)) config = {'database': 'spam', 'port': 3377, 'host': 'example.com'} self.assertEqual('example.com_3377_spam', pooling.generate_pool_name(**config)) config = { 'user': 'ham', 'database': 'spam', 'port': 3377, 'host': 'example.com'} self.assertEqual('example.com_3377_ham_spam', pooling.generate_pool_name(**config)) class PooledMySQLConnectionTests(tests.MySQLConnectorTests): def test___init__(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=1, **dbconfig) self.assertRaises(TypeError, pooling.PooledMySQLConnection) cnx = MySQLConnection(**dbconfig) pcnx = pooling.PooledMySQLConnection(cnxpool, cnx) self.assertEqual(cnxpool, pcnx._cnx_pool) self.assertEqual(cnx, pcnx._cnx) self.assertRaises(AttributeError, pooling.PooledMySQLConnection, None, None) self.assertRaises(AttributeError, pooling.PooledMySQLConnection, cnxpool, None) def test___getattr__(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=1, pool_name='test') cnx = MySQLConnection(**dbconfig) pcnx = pooling.PooledMySQLConnection(cnxpool, cnx) exp_attrs = { '_connection_timeout': dbconfig['connection_timeout'], '_database': dbconfig['database'], '_host': dbconfig['host'], '_password': dbconfig['password'], '_port': dbconfig['port'], '_unix_socket': dbconfig['unix_socket'] } for attr, value in exp_attrs.items(): self.assertEqual( value, getattr(pcnx, attr), "Attribute {0} of reference connection not correct".format( attr)) self.assertEqual(pcnx.connect, cnx.connect) def test_close(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=1, **dbconfig) cnxpool._original_cnx = None def dummy_add_connection(self, cnx=None): self._original_cnx = cnx cnxpool.add_connection = dummy_add_connection.__get__( cnxpool, pooling.MySQLConnectionPool) pcnx = pooling.PooledMySQLConnection(cnxpool, MySQLConnection(**dbconfig)) cnx = pcnx._cnx pcnx.close() self.assertEqual(cnx, cnxpool._original_cnx) def test_config(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=1, **dbconfig) cnx = cnxpool.get_connection() self.assertRaises(errors.PoolError, cnx.config, user='spam') class MySQLConnectionPoolTests(tests.MySQLConnectorTests): def test___init__(self): dbconfig = tests.get_mysql_config() self.assertRaises(errors.PoolError, pooling.MySQLConnectionPool) self.assertRaises(AttributeError, pooling.MySQLConnectionPool, pool_name='test', pool_size=-1) self.assertRaises(AttributeError, pooling.MySQLConnectionPool, pool_name='test', pool_size=0) self.assertRaises(AttributeError, pooling.MySQLConnectionPool, pool_name='test', pool_size=(pooling.CNX_POOL_MAXSIZE + 1)) cnxpool = pooling.MySQLConnectionPool(pool_name='test') self.assertEqual(5, cnxpool._pool_size) self.assertEqual('test', cnxpool._pool_name) self.assertEqual({}, cnxpool._cnx_config) self.assertTrue(isinstance(cnxpool._cnx_queue, Queue)) self.assertTrue(isinstance(cnxpool._config_version, uuid.UUID)) self.assertTrue(True, cnxpool._reset_session) cnxpool = pooling.MySQLConnectionPool(pool_size=10, pool_name='test') self.assertEqual(10, cnxpool._pool_size) cnxpool = pooling.MySQLConnectionPool(pool_size=10, **dbconfig) self.assertEqual(dbconfig, cnxpool._cnx_config, "Connection configuration not saved correctly") self.assertEqual(10, cnxpool._cnx_queue.qsize()) self.assertTrue(isinstance(cnxpool._config_version, uuid.UUID)) cnxpool = pooling.MySQLConnectionPool(pool_size=1, pool_name='test', pool_reset_session=False) self.assertFalse(cnxpool._reset_session) def test_pool_name(self): """Test MySQLConnectionPool.pool_name property""" pool_name = 'ham' cnxpool = pooling.MySQLConnectionPool(pool_name=pool_name) self.assertEqual(pool_name, cnxpool.pool_name) def test_pool_size(self): """Test MySQLConnectionPool.pool_size property""" pool_size = 4 cnxpool = pooling.MySQLConnectionPool(pool_name='test', pool_size=pool_size) self.assertEqual(pool_size, cnxpool.pool_size) def test_reset_session(self): """Test MySQLConnectionPool.reset_session property""" cnxpool = pooling.MySQLConnectionPool(pool_name='test', pool_reset_session=False) self.assertFalse(cnxpool.reset_session) cnxpool._reset_session = True self.assertTrue(cnxpool.reset_session) def test__set_pool_size(self): cnxpool = pooling.MySQLConnectionPool(pool_name='test') self.assertRaises(AttributeError, cnxpool._set_pool_size, -1) self.assertRaises(AttributeError, cnxpool._set_pool_size, 0) self.assertRaises(AttributeError, cnxpool._set_pool_size, pooling.CNX_POOL_MAXSIZE + 1) cnxpool._set_pool_size(pooling.CNX_POOL_MAXSIZE - 1) self.assertEqual(pooling.CNX_POOL_MAXSIZE - 1, cnxpool._pool_size) def test__set_pool_name(self): cnxpool = pooling.MySQLConnectionPool(pool_name='test') self.assertRaises(AttributeError, cnxpool._set_pool_name, 'pool name') self.assertRaises(AttributeError, cnxpool._set_pool_name, 'pool%%name') self.assertRaises(AttributeError, cnxpool._set_pool_name, 'long_pool_name' * pooling.CNX_POOL_MAXNAMESIZE) def test_add_connection(self): cnxpool = pooling.MySQLConnectionPool(pool_name='test') self.assertRaises(errors.PoolError, cnxpool.add_connection) dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=2, pool_name='test') cnxpool.set_config(**dbconfig) cnxpool.add_connection() pcnx = pooling.PooledMySQLConnection( cnxpool, cnxpool._cnx_queue.get(block=False)) self.assertTrue(isinstance(pcnx._cnx, MySQLConnection)) self.assertEqual(cnxpool, pcnx._cnx_pool) self.assertEqual(cnxpool._config_version, pcnx._cnx._pool_config_version) cnx = pcnx._cnx pcnx.close() # We should get the same connectoin back self.assertEqual(cnx, cnxpool._cnx_queue.get(block=False)) cnxpool.add_connection(cnx) # reach max connections cnxpool.add_connection() self.assertRaises(errors.PoolError, cnxpool.add_connection) # fail connecting cnxpool._remove_connections() cnxpool._cnx_config['port'] = 9999999 cnxpool._cnx_config['unix_socket'] = '/ham/spam/foobar.socket' self.assertRaises(errors.InterfaceError, cnxpool.add_connection) self.assertRaises(errors.PoolError, cnxpool.add_connection, cnx=str) def test_set_config(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_name='test') # No configuration changes config_version = cnxpool._config_version cnxpool.set_config() self.assertEqual(config_version, cnxpool._config_version) self.assertEqual({}, cnxpool._cnx_config) # Valid configuration changes config_version = cnxpool._config_version cnxpool.set_config(**dbconfig) self.assertEqual(dbconfig, cnxpool._cnx_config) self.assertNotEqual(config_version, cnxpool._config_version) # Invalid configuration changes config_version = cnxpool._config_version wrong_dbconfig = dbconfig.copy() wrong_dbconfig['spam'] = 'ham' self.assertRaises(errors.PoolError, cnxpool.set_config, **wrong_dbconfig) self.assertEqual(dbconfig, cnxpool._cnx_config) self.assertEqual(config_version, cnxpool._config_version) def test_get_connection(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool(pool_size=2, pool_name='test') self.assertRaises(errors.PoolError, cnxpool.get_connection) cnxpool = pooling.MySQLConnectionPool(pool_size=1, **dbconfig) # Get connection from pool pcnx = cnxpool.get_connection() self.assertTrue(isinstance(pcnx, pooling.PooledMySQLConnection)) self.assertRaises(errors.PoolError, cnxpool.get_connection) self.assertEqual(pcnx._cnx._pool_config_version, cnxpool._config_version) prev_config_version = pcnx._pool_config_version prev_thread_id = pcnx.connection_id pcnx.close() # Change configuration config_version = cnxpool._config_version cnxpool.set_config(autocommit=True) self.assertNotEqual(config_version, cnxpool._config_version) pcnx = cnxpool.get_connection() self.assertNotEqual( pcnx._cnx._pool_config_version, prev_config_version) self.assertNotEqual(prev_thread_id, pcnx.connection_id) self.assertEqual(1, pcnx.autocommit) pcnx.close() def test__remove_connections(self): dbconfig = tests.get_mysql_config() cnxpool = pooling.MySQLConnectionPool( pool_size=2, pool_name='test', **dbconfig) pcnx = cnxpool.get_connection() self.assertEqual(1, cnxpool._remove_connections()) pcnx.close() self.assertEqual(1, cnxpool._remove_connections()) self.assertEqual(0, cnxpool._remove_connections()) self.assertRaises(errors.PoolError, cnxpool.get_connection) class ModuleConnectorPoolingTests(tests.MySQLConnectorTests): def test__connection_pools(self): self.assertEqual(myconn._CONNECTION_POOLS, {}) def test_connect(self): dbconfig = tests.get_mysql_config() myconn._CONNECTION_POOLS.update({'spam': 'ham'}) self.assertRaises(errors.InterfaceError, myconn.connect, pool_name='spam') myconn._CONNECTION_POOLS = {} myconn.connect(pool_name='ham', **dbconfig) self.assertTrue('ham' in myconn._CONNECTION_POOLS) cnxpool = myconn._CONNECTION_POOLS['ham'] self.assertTrue(isinstance(cnxpool, pooling.MySQLConnectionPool)) self.assertEqual('ham', cnxpool.pool_name) myconn.connect(pool_size=5, **dbconfig) pool_name = pooling.generate_pool_name(**dbconfig) self.assertTrue(pool_name in myconn._CONNECTION_POOLS) myconn._CONNECTION_POOLS = {} mysql-connector-python-1.1.6/tests/test_examples.py0000644001577100000120000001447512276514013022046 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for examples """ import tests import mysql.connector class TestExamples(tests.MySQLConnectorTests): def setUp(self): config = tests.get_mysql_config() self.cnx = mysql.connector.connect(**config) def tearDown(self): self.cnx.close() def _exec_main(self, example): try: return example.main(tests.get_mysql_config()) except Exception as err: self.fail(err) def test_dates(self): """examples/dates.py""" try: import examples.dates as example except Exception as err: self.fail(err) output = example.main(tests.get_mysql_config()) exp = [' 1 | 1977-06-14 | 1977-06-14 21:10:00 | 21:10:00 |', ' 2 | None | None | 0:00:00 |', ' 3 | None | None | 0:00:00 |'] self.assertEqual(output, exp) example.DATA.append(('0000-00-00', None, '00:00:00'),) self.assertRaises(mysql.connector.errors.IntegrityError, example.main, tests.get_mysql_config()) def test_engines(self): """examples/engines.py""" try: import examples.engines as example except: self.fail() output = self._exec_main(example) # Can't check output as it might be different per MySQL instance # We check only if MyISAM is present found = False for line in output: if line.find('MyISAM') > -1: found = True break self.assertTrue(found, 'MyISAM engine not found in output') def test_inserts(self): """examples/inserts.py""" try: import examples.inserts as example except Exception as err: self.fail(err) output = self._exec_main(example) exp = ['1 | Geert | 30\nInfo: c..\n', '2 | Jan | 30\nInfo: c..\n', '3 | Michel | 30\nInfo: c..\n'] self.assertEqual(output, exp, 'Output was not correct') def test_transactions(self): """examples/transactions.py""" db = mysql.connector.connect(**tests.get_mysql_config()) r = tests.have_engine(db, 'InnoDB') db.close() if not r: return try: import examples.transaction as example except Exception as e: self.fail(e) output = self._exec_main(example) exp = ['Inserting data', 'Rolling back transaction', 'No data, all is fine.', 'Data before commit:', '4 | Geert', '5 | Jan', '6 | Michel', 'Data after commit:', '4 | Geert', '5 | Jan', '6 | Michel'] self.assertEqual(output, exp, 'Output was not correct') def test_unicode(self): """examples/unicode.py""" try: import examples.unicode as example except Exception as e: self.fail(e) output = self._exec_main(example) exp = ['Unicode string: ¿Habla español?', 'Unicode string coming from db: ¿Habla español?'] self.assertEqual(output, exp) # ,'Output was not correct') def test_warnings(self): """examples/warnings.py""" try: import examples.warnings as example except Exception as e: self.fail(e) output = self._exec_main(example) exp = ["Executing 'SELECT 'abc'+1'", "1292: Truncated incorrect DOUBLE value: 'abc'"] self.assertEqual(output, exp, 'Output was not correct') example.STMT = "SELECT 'abc'" self.assertRaises(Exception, example.main, tests.get_mysql_config()) def test_multi_resultsets(self): """examples/multi_resultsets.py""" try: import examples.multi_resultsets as example except Exception as e: self.fail(e) output = self._exec_main(example) exp = ['Inserted 1 row', 'Number of rows: 1', 'Inserted 2 rows', 'Names in table: Geert Jan Michel'] self.assertEqual(output, exp, 'Output was not correct') def test_microseconds(self): """examples/microseconds.py""" try: import examples.microseconds as example except Exception as e: self.fail(e) output = self._exec_main(example) if self.cnx.get_server_version() < (5, 6, 4): exp = "does not support fractional precision for timestamps." self.assertTrue(output[0].endswith(exp)) else: exp = [ ' 1 | 1 | 0:00:47.510000', ' 1 | 2 | 0:00:47.020000', ' 1 | 3 | 0:00:47.650000', ' 1 | 4 | 0:00:46.060000', ] self.assertEqual(output, exp, 'Output was not correct') def test_prepared_statements(self): """examples/prepared_statements.py""" try: import examples.prepared_statements as example except Exception as e: self.fail(e) output = self._exec_main(example) exp = [ 'Inserted data', '1 | Geert', '2 | Jan', '3 | Michel', ] self.assertEqual(output, exp, 'Output was not correct') mysql-connector-python-1.1.6/tests/test_errorcode.py0000644001577100000120000000536212276514013022207 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.errorcode """ from datetime import datetime import tests from mysql.connector import errorcode class ErrorCodeTests(tests.MySQLConnectorTests): def test__GENERATED_ON(self): self.assertTrue(isinstance(errorcode._GENERATED_ON, str)) try: generatedon = datetime.strptime(errorcode._GENERATED_ON, '%Y-%m-%d').date() except ValueError as err: self.fail(err) delta = (datetime.now().date() - generatedon).days self.assertTrue( delta < 120, "errorcode.py is more than 120 days old ({0})".format(delta)) def test__MYSQL_VERSION(self): minimum = (5, 6, 6) self.assertTrue(isinstance(errorcode._MYSQL_VERSION, tuple)) self.assertTrue(len(errorcode._MYSQL_VERSION) == 3) self.assertTrue(errorcode._MYSQL_VERSION >= minimum) def _check_code(self, code, num): try: self.assertEqual(getattr(errorcode, code), num) except AttributeError as err: self.fail(err) def test_server_error_codes(self): cases = { 'ER_HASHCHK': 1000, 'ER_TRG_INVALID_CREATION_CTX': 1604, 'ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION': 1792, } for code, num in cases.items(): self._check_code(code, num) def test_client_error_codes(self): cases = { 'CR_UNKNOWN_ERROR': 2000, 'CR_PROBE_SLAVE_STATUS': 2022, 'CR_AUTH_PLUGIN_CANNOT_LOAD': 2059, } for code, num in cases.items(): self._check_code(code, num) mysql-connector-python-1.1.6/tests/test_cursor.py0000644001577100000120000001774012276514013021543 0ustar pb2userwheel# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Incur., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Test module for bugs Bug test cases specific to a particular Python (major) version are loaded from py2.bugs or py3.bugs. This module was originally located in python2/tests and python3/tests. It should contain bug test cases which work for both Python v2 and v3. Whenever a bug is bout to a specific Python version, put the test cases in tests/py2/bugs.py or tests/py3/bugs.py. It might be that these files need to be created first. """ import os import re import sys import tests if sys.version_info[0] == 2: from .py2.cursor import * else: from .py3.cursor import * from mysql.connector import (connection, cursor, conversion, protocol, utils, errors, constants) class CursorModule(tests.MySQLConnectorTests): """ Tests for the cursor module functions and attributes """ def test_RE_SQL_INSERT_VALUES(self): regex = cursor.RE_SQL_INSERT_VALUES cases = [ ("(%s, %s)", "INSERT INTO t1 VALUES (%s, %s)"), ("( %s, \n %s )", "INSERT INTO t1 VALUES ( %s, \n %s )"), ("(%(c1)s, %(c2)s)", "INSERT INTO t1 VALUES (%(c1)s, %(c2)s)"), ("(\n%(c1)s\n, \n%(c2)s\n)", "INSERT INTO t1 VALUES \n(\n%(c1)s\n, \n%(c2)s\n)"), ("( %(c1)s , %(c2)s )", "INSERT INTO t1 VALUES ( %(c1)s , %(c2)s ) ON DUPLICATE"), ("(%s, %s, NOW())", "INSERT INTO t1 VALUES (%s, %s, NOW())"), ("(%s, CONCAT('a', 'b'), %s, NOW())", "INSERT INTO t1 VALUES (%s, CONCAT('a', 'b'), %s, NOW())"), ("( NOW(), %s, \n, CONCAT('a', 'b'), %s )", "INSERT INTO t1 VALUES " " ( NOW(), %s, \n, CONCAT('a', 'b'), %s )"), ("(%(c1)s, NOW(6), %(c2)s)", "INSERT INTO t1 VALUES (%(c1)s, NOW(6), %(c2)s)"), ("(\n%(c1)s\n, \n%(c2)s, REPEAT('a', 20)\n)", "INSERT INTO t1 VALUES " "\n(\n%(c1)s\n, \n%(c2)s, REPEAT('a', 20)\n)"), ("( %(c1)s ,NOW(),REPEAT('a', 20)\n), %(c2)s )", "INSERT INTO t1 VALUES " " ( %(c1)s ,NOW(),REPEAT('a', 20)\n), %(c2)s ) ON DUPLICATE"), ("( %(c1)s, %(c2)s )", "INSERT INTO `values` VALUES " " ( %(c1)s, %(c2)s ) ON DUPLICATE"), ] for exp, stmt in cases: self.assertEqual(exp, re.search(regex, stmt).group(1)) class CursorBaseTests(tests.MySQLConnectorTests): def setUp(self): self.cur = cursor.CursorBase() def test___init__(self): exp = { '_description': None, '_rowcount': -1, 'arraysize': 1, } for key, value in exp.items(): self.assertEqual(value, getattr(self.cur, key), msg="Default for '%s' did not match." % key) def test_callproc(self): """CursorBase object callproc()-method""" self.check_method(self.cur, 'callproc') try: self.cur.callproc('foo', args=(1, 2, 3)) except (SyntaxError, TypeError): self.fail("Cursor callproc(): wrong arguments") def test_close(self): """CursorBase object close()-method""" self.check_method(self.cur, 'close') def test_execute(self): """CursorBase object execute()-method""" self.check_method(self.cur, 'execute') try: self.cur.execute('select', params=(1, 2, 3)) except (SyntaxError, TypeError): self.fail("Cursor execute(): wrong arguments") def test_executemany(self): """CursorBase object executemany()-method""" self.check_method(self.cur, 'executemany') try: self.cur.executemany('select', [()]) except (SyntaxError, TypeError): self.fail("Cursor executemany(): wrong arguments") def test_fetchone(self): """CursorBase object fetchone()-method""" self.check_method(self.cur, 'fetchone') def test_fetchmany(self): """CursorBase object fetchmany()-method""" self.check_method(self.cur, 'fetchmany') try: self.cur.fetchmany(size=1) except (SyntaxError, TypeError): self.fail("Cursor fetchmany(): wrong arguments") def test_fetchall(self): """CursorBase object fetchall()-method""" self.check_method(self.cur, 'fetchall') def test_nextset(self): """CursorBase object nextset()-method""" self.check_method(self.cur, 'nextset') def test_setinputsizes(self): """CursorBase object setinputsizes()-method""" self.check_method(self.cur, 'setinputsizes') try: self.cur.setinputsizes((1,)) except (SyntaxError, TypeError): self.fail("CursorBase setinputsizes(): wrong arguments") def test_setoutputsize(self): """CursorBase object setoutputsize()-method""" self.check_method(self.cur, 'setoutputsize') try: self.cur.setoutputsize(1, column=None) except (SyntaxError, TypeError): self.fail("CursorBase setoutputsize(): wrong arguments") def test_description(self): self.assertEqual(None, self.cur.description) self.assertEqual(self.cur._description, self.cur.description) self.cur._description = 'ham' self.assertEqual('ham', self.cur.description) if tests.OLD_UNITTEST: try: self.cur.description = 'spam' except AttributeError as err: # Exception should be raised pass else: self.fail("AttributeError was not raised") else: with self.assertRaises(AttributeError): self.cur.description = 'spam' def test_rowcount(self): self.assertEqual(-1, self.cur.rowcount) self.assertEqual(self.cur._rowcount, self.cur.rowcount) self.cur._rowcount = 2 self.assertEqual(2, self.cur.rowcount) if tests.OLD_UNITTEST: try: self.cur.description = 'spam' except AttributeError as err: # Exception should be raised pass else: self.fail("AttributeError was not raised") else: with self.assertRaises(AttributeError): self.cur.rowcount = 3 def test_last_insert_id(self): self.assertEqual(None, self.cur.lastrowid) self.assertEqual(self.cur._last_insert_id, self.cur.lastrowid) self.cur._last_insert_id = 2 self.assertEqual(2, self.cur.lastrowid) if tests.OLD_UNITTEST: try: self.cur.description = 'spam' except AttributeError as err: # Exception should be raised pass else: self.fail("AttributeError was not raised") else: with self.assertRaises(AttributeError): self.cur.lastrowid = 3 mysql-connector-python-1.1.6/tests/py2/0000755001577100000120000000000012276514327017326 5ustar pb2userwheelmysql-connector-python-1.1.6/tests/py2/connection.py0000644001577100000120000000356112276514013022034 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for mysql.connector.connection specific to Python v2 """ OK_PACKET = '\x07\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00' OK_PACKET_RESULT = { 'insert_id': 0, 'affected_rows': 0, 'field_count': 0, 'warning_count': 0, 'server_status': 0 } ERR_PACKET = '\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\ '\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\ '\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\ '\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\ '\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\ '\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29' EOF_PACKET = '\x05\x00\x00\x00\xfe\x00\x00\x00\x00' EOF_PACKET_RESULT = {'status_flag': 0, 'warning_count': 0} mysql-connector-python-1.1.6/tests/py2/bugs.py0000644001577100000120000001150112276514013020626 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for bugs specific to Python v2 """ import os import tests from mysql.connector import connection, errors class BugOra14843456(tests.MySQLConnectorTests): """BUG#14843456: UNICODE USERNAME AND/OR PASSWORD FAILS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() if config['unix_socket'] and os.name != 'nt': self.host = 'localhost' else: self.host = config['host'] grant = u"CREATE USER '{user}'@'{host}' IDENTIFIED BY '{password}'" self._credentials = [ (u'Herne', u'Herne'), (u'\u0141owicz', u'\u0141owicz'), ] for user, password in self._credentials: self.cursor.execute(grant.format( user=user, host=self.host, password=password)) def tearDown(self): for user, password in self._credentials: self.cursor.execute(u"DROP USER '{user}'@'{host}'".format( user=user, host=self.host)) def test_unicode_credentials(self): config = tests.get_mysql_config() for user, password in self._credentials: config['user'] = user config['password'] = password config['database'] = None try: cnx = connection.MySQLConnection(**config) except (UnicodeDecodeError, errors.InterfaceError): self.fail('Failed using unicode username or password') else: cnx.close() class Bug499410(tests.MySQLConnectorTests): def test_use_unicode(self): """lp:499410 Disabling unicode does not work""" config = tests.get_mysql_config() config['use_unicode'] = False cnx = connection.MySQLConnection(**config) self.assertEqual(False, cnx._use_unicode) cnx.close() def test_charset(self): config = tests.get_mysql_config() config['use_unicode'] = False charset = 'greek' config['charset'] = charset cnx = connection.MySQLConnection(**config) data = ['\xe1\xed\xf4\xdf\xef'] # Bye in Greek exp_unicode = [(u'\u03b1\u03bd\u03c4\u03af\u03bf',), ] exp_nonunicode = [(data[0],)] cur = cnx.cursor() tbl = '{0}test'.format(charset) try: cur.execute('DROP TABLE IF EXISTS {0}'.format(tbl)) cur.execute( 'CREATE TABLE {0} (c1 VARCHAR(60)) charset={1}'.format( tbl, charset)) except errors.Error as err: self.fail("Failed creating test table: {0}".format(err)) try: stmt = 'INSERT INTO {0} VALUES (%s)'.format(tbl) for line in data: cur.execute(stmt, (line.strip(),)) except: self.fail("Failed populating test table.") cur.execute("SELECT * FROM {0}".format(tbl)) res_nonunicode = cur.fetchall() cnx.set_unicode(True) cur.execute("SELECT * FROM {0}".format(tbl)) res_unicode = cur.fetchall() try: cur.execute('DROP TABLE IF EXISTS {0}'.format(tbl)) except: self.fail("Failed cleaning up test table.") cnx.close() self.assertEqual(exp_nonunicode, res_nonunicode) self.assertEqual(exp_unicode, res_unicode) class BugOra17079344Extra(object): """Extras for test case test_bugs.BugOra17079344""" data_gbk = [u'赵孟頫', u'赵\孟\頫\\', u'遜',] data_sjis = [u'\u005c'] data_big5 = [u'\u5C62'] class BugOra17780576Extra(object): """Extras for test case test_bugs.BugOra17780576""" data_utf8mb4 = [u'😉😍', u'😃😊', u'😄😘😚',] mysql-connector-python-1.1.6/tests/py2/test_utils.py0000644001577100000120000002201512276514013022067 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.utils """ import struct import tests from mysql.connector import utils class UtilsTests(tests.MySQLConnectorTests): """Testing the helper functions in the utils module. These tests should not make a connection to the database. """ def _check_int_result(self, result, exp, data): if not isinstance(result, str): self.fail("Wrong result. Expected {0}, we got {1}".format( (type(exp), type(result)))) elif exp != result: self.fail("Wrong result. Expected {0}, we got {1}".format( (data, result))) def test_intread(self): """Use intread to read from valid strings.""" try: for i in range(4): utils.intread(b'a' * (i + 1)) except ValueError as err: self.fail("intread failed calling 'int{0}read: {1}".format( int(i) + 1, err)) def test_int1store(self): """Use int1store to pack an integer (2^8) as a string.""" data = 2 ** (8 - 1) exp = struct.pack(', like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for bugs using __future__ """ from __future__ import unicode_literals import tests from mysql.connector import (connection, errors) class BugOra16655208(tests.MySQLConnectorTests): """BUG#16655208:UNICODE DATABASE NAMES FAILS WHEN USING UNICODE_LITERALS """ def test_unicode_database(self): config = tests.get_mysql_config() config['database'] = 'データベース' self.assertRaises(errors.DatabaseError, connection.MySQLConnection, **config) mysql-connector-python-1.1.6/tests/py2/test_protocol.py0000644001577100000120000005366212276514013022604 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.protocol """ import struct import decimal import datetime import tests from mysql.connector import (protocol, errors) from mysql.connector.constants import (ClientFlag, FieldType, FieldFlag) OK_PACKET = '\x07\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00' OK_PACKET_RESULT = { 'insert_id': 0, 'affected_rows': 1, 'field_count': 0, 'warning_count': 1, 'server_status': 0 } ERR_PACKET = '\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\ '\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\ '\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\ '\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\ '\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\ '\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29' EOF_PACKET = '\x05\x00\x00\x00\xfe\x00\x00\x00\x00' EOF_PACKET_RESULT = {'status_flag': 0, 'warning_count': 0} SEED = '\x3b\x55\x78\x7d\x2c\x5f\x7c\x72\x49\x52'\ '\x3f\x28\x47\x6f\x77\x28\x5f\x28\x46\x69' class MySQLProtocolTests(tests.MySQLConnectorTests): def setUp(self): self._protocol = protocol.MySQLProtocol() def test__scramble_password(self): """Scramble a password ready to send to MySQL""" password = 'spam' hashed = '\x3a\x07\x66\xba\xba\x01\xce\xbe\x55\xe6'\ '\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91\x5b' res = self._protocol._scramble_password(password, SEED) self.assertEqual(hashed, res) def test_make_auth(self): """Make a MySQL authentication packet""" exp = { 'allset': '\x0d\xa2\x03\x00\x00\x00\x00\x40' '\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x68\x61\x6d\x00\x14\x3a\x07\x66\xba\xba\x01\xce' '\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' '\x5b\x74\x65\x73\x74\x00', 'nopass': '\x0d\xa2\x03\x00\x00\x00\x00\x40' '\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x68\x61\x6d\x00\x00\x74\x65\x73\x74\x00', 'nouser': '\x0d\xa2\x03\x00\x00\x00\x00\x40' '\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x14\x3a\x07\x66\xba\xba\x01\xce' '\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' '\x5b\x74\x65\x73\x74\x00', 'nodb': '\x0d\xa2\x03\x00\x00\x00\x00\x40' '\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x68\x61\x6d\x00\x14\x3a\x07\x66\xba\xba\x01\xce' '\xbe\x55\xe6\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91' '\x5b\x00', } flags = ClientFlag.get_default() kwargs = { 'seed': None, 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 33, 'client_flags': flags} self.assertRaises(errors.ProgrammingError, self._protocol.make_auth, **kwargs) kwargs['seed'] = SEED res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['allset'], res) kwargs['password'] = None res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nopass'], res) kwargs['password'] = 'spam' kwargs['database'] = None res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nodb'], res) kwargs['username'] = None kwargs['database'] = 'test' res = self._protocol.make_auth(**kwargs) self.assertEqual(exp['nouser'], res) def test_make_auth_ssl(self): """Make a SSL authentication packet""" cases = [ ({}, '\x00\x00\x00\x00\x00\x00\x00\x40\x21\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00'), ({'charset': 8}, '\x00\x00\x00\x00\x00\x00\x00\x40\x08\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00'), ({'client_flags': 240141}, '\x0d\xaa\x03\x00\x00\x00\x00\x40\x21\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00'), ({'charset': 8, 'client_flags': 240141, 'max_allowed_packet': 2147483648}, '\x0d\xaa\x03\x00\x00\x00\x00\x80\x08\x00\x00\x00\x00\x00' '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00\x00\x00\x00'), ] for kwargs, exp in cases: self.assertEqual(exp, self._protocol.make_auth_ssl(**kwargs)) def test_make_command(self): """Make a generic MySQL command packet""" exp = '\x01\x68\x61\x6d' res = self._protocol.make_command(1, 'ham') self.assertEqual(exp, res) res = self._protocol.make_command(1, argument='ham') self.assertEqual(exp, res) exp = '\x03' res = self._protocol.make_command(3) self.assertEqual(exp, res) def test_make_change_user(self): """Make a change user MySQL packet""" exp = { 'allset': '\x11\x68\x61\x6d\x00\x14\x3a\x07' '\x66\xba\xba\x01\xce\xbe\x55\xe6\x29\x88\xaa\xae' '\xdb\x00\xb3\x4d\x91\x5b\x74\x65\x73\x74\x00\x08' '\x00', 'nopass': '\x11\x68\x61\x6d\x00\x00\x74\x65' '\x73\x74\x00\x08\x00', } kwargs = { 'seed': None, 'username': 'ham', 'password': 'spam', 'database': 'test', 'charset': 8, 'client_flags': ClientFlag.get_default() } self.assertRaises(errors.ProgrammingError, self._protocol.make_change_user, **kwargs) kwargs['seed'] = SEED res = self._protocol.make_change_user(**kwargs) self.assertEqual(exp['allset'], res) kwargs['password'] = None res = self._protocol.make_change_user(**kwargs) self.assertEqual(exp['nopass'], res) def test_parse_handshake(self): """Parse handshake-packet sent by MySQL""" handshake = \ '\x47\x00\x00\x00\x0a\x35\x2e\x30\x2e\x33\x30\x2d'\ '\x65\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67'\ '\x70\x6c\x2d\x6c\x6f\x67\x00\x09\x01\x00\x00\x68'\ '\x34\x69\x36\x6f\x50\x21\x4f\x00\x2c\xa2\x08\x02'\ '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ '\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72'\ '\x59\x48\x00' exp = { 'protocol': 10, 'server_version_original': '5.0.30-enterprise-gpl-log', 'charset': 8, 'server_threadid': 265, 'capabilities': 41516, 'server_status': 2, 'scramble': 'h4i6oP!OLng9&PD@WrYH' } res = self._protocol.parse_handshake(handshake) self.assertEqual(exp, res) def test_parse_ok(self): """Parse OK-packet sent by MySQL""" res = self._protocol.parse_ok(OK_PACKET) self.assertEqual(OK_PACKET_RESULT, res) okpkt = OK_PACKET + '\x04spam' exp = OK_PACKET_RESULT.copy() exp['info_msg'] = 'spam' res = self._protocol.parse_ok(okpkt) self.assertEqual(exp, res) def test_parse_column_count(self): """Parse the number of columns""" packet = '\x01\x00\x00\x01\x03' res = self._protocol.parse_column_count(packet) self.assertEqual(3, res) packet = '\x01\x00' self.assertRaises(errors.InterfaceError, self._protocol.parse_column_count, packet) def test_parse_column(self): """Parse field-packet sent by MySQL""" column_packet = \ '\x1a\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x04'\ '\x53\x70\x61\x6d\x00\x0c\x21\x00\x09\x00\x00\x00'\ '\xfd\x01\x00\x1f\x00\x00' exp = ('Spam', 253, None, None, None, None, 0, 1) res = self._protocol.parse_column(column_packet) self.assertEqual(exp, res) def test_parse_eof(self): """Parse EOF-packet sent by MySQL""" res = self._protocol.parse_eof(EOF_PACKET) self.assertEqual(EOF_PACKET_RESULT, res) def test_read_text_result(self): # Tested by MySQLConnectionTests.test_get_rows() and .test_get_row() pass def test_parse_binary_prepare_ok(self): """Parse Prepare OK packet""" cases = [ # SELECT CONCAT(?, ?) AS c1 ('\x0c\x00\x00\x01' '\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00', {'num_params': 2, 'statement_id': 1, 'warning_count': 0, 'num_columns': 1 } ), # DO 1 ('\x0c\x00\x00\x01' '\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', {'num_params': 0, 'statement_id': 1, 'warning_count': 0, 'num_columns': 0 } ), ] for packet, exp in cases: self.assertEqual(exp, self._protocol.parse_binary_prepare_ok(packet)) def test__parse_binary_integer(self): """Parse an integer from a binary packet""" # Case = Expected value; pack format; field type; field flag cases = [ (-128, 'b', FieldType.TINY, 0), (-32768, 'h', FieldType.SHORT, 0), (-2147483648, 'i', FieldType.LONG, 0), (-9999999999, 'q', FieldType.LONGLONG, 0), (255, 'B', FieldType.TINY, FieldFlag.UNSIGNED), (65535, 'H', FieldType.SHORT, FieldFlag.UNSIGNED), (4294967295, 'I', FieldType.LONG, FieldFlag.UNSIGNED), (9999999999, 'Q', FieldType.LONGLONG, FieldFlag.UNSIGNED), ] field_info = [None] * 8 field_info[0] = 'c1' for exp, fmt, field_type, flag in cases: field_info[1] = field_type field_info[7] = flag data = struct.pack(fmt, exp) + '\x00\x00' res = self._protocol._parse_binary_integer(data, field_info) self.assertEqual(('\x00\x00', exp), res, "Failed parsing binary integer '{0}'".format(exp)) def test__parse_binary_float(self): """Parse a float/double from a binary packet""" # Case = Expected value; data; field type cases = [ (-3.14159, '\x6e\x86\x1b\xf0\xf9\x21\x09\xc0', FieldType.DOUBLE), (3.14159, '\x6e\x86\x1b\xf0\xf9\x21\x09\x40', FieldType.DOUBLE), (-3.14, '\xc3\xf5\x48\xc0', FieldType.FLOAT), (3.14, '\xc3\xf5\x48\x40', FieldType.FLOAT), ] field_info = [None] * 8 field_info[0] = 'c1' for exp, data, field_type in cases: field_info[1] = field_type res = self._protocol._parse_binary_float(data + '\x00\x00', field_info) self.assertEqual('\x00\x00', res[0], "Failed parsing binary float '{0}'".format(exp)) self.assertAlmostEqual( exp, res[1], places=5, msg="Failed parsing binary float '{0}'".format(exp)) def test__parse_binary_timestamp(self): """Parse a timestamp from a binary packet""" # Case = Expected value; data cases = [ (datetime.date(1977, 6, 14), '\x04\xb9\x07\x06\x0e'), (datetime.datetime(1977, 6, 14, 21, 33, 14), '\x07\xb9\x07\x06\x0e\x15\x21\x0e'), (datetime.datetime(1977, 6, 14, 21, 33, 14, 345), '\x0b\xb9\x07\x06\x0e\x15\x21\x0e\x59\x01\x00\x00') ] for exp, data in cases: res = self._protocol._parse_binary_timestamp(data + '\x00\x00', None) self.assertEqual(('\x00\x00', exp), res, "Failed parsing timestamp '{0}'".format(exp)) def test__parse_binary_time(self): """Parse a time value from a binary packet""" cases = [ (datetime.timedelta(0, 44130), '\x08\x00\x00\x00\x00\x00\x0c\x0f\x1e'), (datetime.timedelta(14, 15330), '\x08\x00\x0e\x00\x00\x00\x04\x0f\x1e'), (datetime.timedelta(-14, 15330), '\x08\x01\x0e\x00\x00\x00\x04\x0f\x1e'), (datetime.timedelta(10, 58530, 230000), '\x0c\x00\x0a\x00\x00\x00\x10\x0f\x1e\x70\x82\x03\x00'), ] for exp, data in cases: res = self._protocol._parse_binary_time(data + '\x00\x00', None) self.assertEqual(('\x00\x00', exp), res, "Failed parsing time '{0}'".format(exp)) def test__parse_binary_values(self): """Parse values from a binary result packet""" # Test is using following statement. # stmt = ("SELECT 'abc' AS aStr," # "3.14 AS aFloat," # "-3.14159 AS aDouble, " # "MAKEDATE(2003, 31) AS aDate, " # "TIMESTAMP('1977-06-14', '21:33:14') AS aDateTime, " # "MAKETIME(256,15,30.23) AS aTime, " # "NULL AS aNull" # ) fields = [('aStr', 253, None, None, None, None, 0, 1), ('aFloat', 246, None, None, None, None, 0, 129), ('aDouble', 246, None, None, None, None, 0, 129), ('aDate', 10, None, None, None, None, 1, 128), ('aDateTime', 12, None, None, None, None, 1, 128), ('aTime', 11, None, None, None, None, 1, 128), ('aNull', 6, None, None, None, None, 1, 128)] packet = ('\x00\x01\x03\x61\x62\x63\x04\x33\x2e\x31\x34\x08' '\x2d\x33\x2e\x31\x34\x31\x35\x39\x04\xd3\x07' '\x01\x1f\x07\xb9\x07\x06\x0e\x15\x21\x0e\x0c' '\x00\x0a\x00\x00\x00\x10\x0f\x1e\x70\x82\x03\x00') # float/double are returned as DECIMAL by MySQL exp = ('abc', '3.14', '-3.14159', datetime.date(2003, 1, 31), datetime.datetime(1977, 6, 14, 21, 33, 14), datetime.timedelta(10, 58530, 230000), None) res = self._protocol._parse_binary_values(fields, packet) self.assertEqual(exp, res) def test_read_binary_result(self): """Read MySQL binary protocol result""" def test__prepare_binary_integer(self): """Prepare an integer for the MySQL binary protocol""" # Case = Data; expected value cases = [ (-128, (struct.pack('b', -128), FieldType.TINY, 0)), (-32768, (struct.pack('h', -32768), FieldType.SHORT, 0)), (-2147483648, (struct.pack('i', -2147483648), FieldType.LONG, 0)), (-9999999999, (struct.pack('q', -9999999999), FieldType.LONGLONG, 0)), (255, (struct.pack('B', 255), FieldType.TINY, 128)), (65535, (struct.pack('H', 65535), FieldType.SHORT, 128)), (4294967295, (struct.pack('I', 4294967295), FieldType.LONG, 128)), (9999999999, (struct.pack('Q', 9999999999), FieldType.LONGLONG, 128)), ] for data, exp in cases: res = self._protocol._prepare_binary_integer(data) self.assertEqual(exp, res, "Failed preparing value '{0}'".format(data)) def test__prepare_binary_timestamp(self): """Prepare a timestamp object for the MySQL binary protocol""" cases = [ (datetime.date(1977, 6, 14), ('\x04\xb9\x07\x06\x0e', 10)), (datetime.datetime(1977, 6, 14), ('\x07\xb9\x07\x06\x0e\x00\x00\x00', 12)), (datetime.datetime(1977, 6, 14, 21, 33, 14), ('\x07\xb9\x07\x06\x0e\x15\x21\x0e', 12)), (datetime.datetime(1977, 6, 14, 21, 33, 14, 345), ('\x0b\xb9\x07\x06\x0e\x15\x21\x0e\x59\x01\x00\x00', 12)), ] for data, exp in cases: self.assertEqual(exp, self._protocol._prepare_binary_timestamp(data), "Failed preparing value '{0}'".format(data)) # Raise an error self.assertRaises(ValueError, self._protocol._prepare_binary_timestamp, 'spam') def test__prepare_binary_time(self): """Prepare a time object for the MySQL binary protocol""" cases = [ (datetime.timedelta(hours=123, minutes=45, seconds=16), ('\x08\x00\x05\x00\x00\x00\x03\x2d\x10', 11)), (datetime.timedelta(hours=-123, minutes=45, seconds=16), ('\x08\x01\x06\x00\x00\x00\x15\x2d\x10', 11)), (datetime.timedelta(hours=123, minutes=45, seconds=16, microseconds=345), ('\x0c\x00\x05\x00\x00\x00\x03\x2d\x10\x59\x01\x00\x00', 11)), (datetime.timedelta(days=123, minutes=45, seconds=16), ('\x08\x00\x7b\x00\x00\x00\x00\x2d\x10', 11)), (datetime.time(14, 53, 36), ('\x08\x00\x00\x00\x00\x00\x0e\x35\x24', 11)), (datetime.time(14, 53, 36, 345), ('\x0c\x00\x00\x00\x00\x00\x0e\x35\x24\x59\x01\x00\x00', 11)) ] for data, exp in cases: self.assertEqual(exp, self._protocol._prepare_binary_time(data), "Failed preparing value '%s'" % data) # Raise an error self.assertRaises(ValueError, self._protocol._prepare_binary_time, 'spam') def test_make_stmt_execute(self): """Make a MySQL packet with the STMT_EXECUTE command""" statement_id = 1 self.assertRaises(errors.InterfaceError, self._protocol.make_stmt_execute, statement_id, ('ham', 'spam'), (1, 2, 3)) data = ('ham', 'spam') exp = ( '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x0f' '\x00\x0f\x00\x03\x68\x61\x6d\x04\x73\x70\x61\x6d' ) res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) # Testing types cases = [ ('ham', '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' '\x01\x0f\x00\x03\x68\x61\x6d'), (decimal.Decimal('3.14'), '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' '\x01\x00\x00\x04\x33\x2e\x31\x34'), (255, '\x01\x00\x00\x00\x80\x01\x00\x00\x00\x00\x01\x01\x80\xff'), (-128, '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x01\x00\x80'), (datetime.datetime(1977, 6, 14, 21, 20, 30), '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00' '\x01\x0c\x00\x07\xb9\x07\x06\x0e\x15\x14\x1e'), (datetime.time(14, 53, 36, 345), '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x0b\x00' '\x0c\x00\x00\x00\x00\x00\x0e\x35\x24\x59\x01\x00\x00'), (3.14, '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01\x05\x00' '\x1f\x85\xeb\x51\xb8\x1e\x09\x40'), ] for data, exp in cases: res = self._protocol.make_stmt_execute(statement_id, (data,), (1,)) self.assertEqual( exp, res, "Failed preparing statement with '{0}'".format(data)) # Testing null bitmap data = (None, None) exp = '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x03\x01' res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) data = (None, 'Ham') exp = ( '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x01\x0f\x00' '\x03\x48\x61\x6d' ) res = self._protocol.make_stmt_execute(statement_id, data, (1, 2)) self.assertEqual(exp, res) data = ('a',) * 11 exp = ( '\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01' '\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00' '\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x01\x61\x01\x61\x01\x61' '\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61\x01\x61' '\x01\x61' ) res = self._protocol.make_stmt_execute(statement_id, data, (1,) * 11) self.assertEqual(exp, res) # Raise an error passing an unsupported object as parameter value class UnSupportedObject(object): pass data = (UnSupportedObject(), UnSupportedObject()) self.assertRaises(errors.ProgrammingError, self._protocol.make_stmt_execute, statement_id, data, (1, 2)) mysql-connector-python-1.1.6/tests/py2/__init__.py0000644001577100000120000000710412276514013021431 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import errno import socket from functools import wraps import types class SkipTest(Exception): """Exception compatible with SkipTest of Python v2.7 and later""" def _id(obj): """Function defined in unittest.case which is needed for decorators""" return obj def test_skip(reason): """Skip test This decorator is used by Python v2.6 code to keep compatible with Python v2.7 (and later) unittest.skip. """ def decorator(test): if not isinstance(test, (type, types.ClassType)): @wraps(test) def wrapper(*args, **kwargs): raise SkipTest(reason) test = wrapper test.__unittest_skip__ = True test.__unittest_skip_why__ = reason return test return decorator def test_skip_if(condition, reason): """Skip test if condition is true This decorator is used by Python v2.6 code to keep compatible with Python v2.7 (and later) unittest.skipIf. """ if condition: return test_skip(reason) return _id class DummySocket(object): """Dummy socket class This class helps to test socket connection without actually making any network activity. It is a proxy class using socket.socket. """ def __init__(self, *args): self._socket = socket.socket(*args) self._server_replies = '' self._client_sends = [] self._raise_socket_error = 0 def __getattr__(self, attr): return getattr(self._socket, attr) def raise_socket_error(self, err=errno.EPERM): self._raise_socket_error = err def recv(self, bufsize=4096, flags=0): if self._raise_socket_error: raise socket.error(self._raise_socket_error) res = self._server_replies[0:bufsize] self._server_replies = self._server_replies[bufsize:] return res def send(self, string, flags=0): if self._raise_socket_error: raise socket.error(self._raise_socket_error) self._client_sends.append(string) return len(string) def sendall(self, string, flags=0): self._client_sends.append(string) return None def add_packet(self, packet): self._server_replies += packet def add_packets(self, packets): for packet in packets: self._server_replies += packet def reset(self): self._raise_socket_error = 0 self._server_replies = '' self._client_sends = [] def get_address(self): return 'dummy' mysql-connector-python-1.1.6/tests/py2/cursor.py0000644001577100000120000011251512276514013021212 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for mysql.connector.cursor specific to Python v2 """ import itertools from decimal import Decimal import time import datetime import new import tests from mysql.connector import (connection, cursor, errors) class MySQLCursorTests(tests.TestsCursor): def setUp(self): self.cur = cursor.MySQLCursor(connection=None) self.cnx = None def test_init(self): """MySQLCursor object init""" try: cur = cursor.MySQLCursor(connection=None) except (SyntaxError, TypeError) as err: self.fail("Failed initializing MySQLCursor; {0}".format(err)) exp = { '_connection': None, '_stored_results': [], '_nextrow': (None, None), '_warnings': None, '_warning_count': 0, '_executed': None, '_executed_list': [], } for key, value in exp.items(): self.assertEqual( value, getattr(cur, key), msg="Default for '{0}' did not match.".format(key)) self.assertRaises(errors.InterfaceError, cursor.MySQLCursor, connection='foo') def test__set_connection(self): """MySQLCursor object _set_connection()-method""" self.check_method(self.cur, '_set_connection') self.assertRaises(errors.InterfaceError, self.cur._set_connection, 'foo') self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur._set_connection(self.connection) self.cur.close() def test__reset_result(self): """MySQLCursor object _reset_result()-method""" self.check_method(self.cur, '_reset_result') def reset(self): self._test = "Reset called" self.cur.reset = new.instancemethod(reset, self.cur, cursor.MySQLCursor) exp = { 'rowcount': -1, '_stored_results': [], '_nextrow': (None, None), '_warnings': None, '_warning_count': 0, '_executed': None, '_executed_list': [], } self.cur._reset_result() for key, value in exp.items(): self.assertEqual(value, getattr(self.cur, key), msg="'{0}' was not reset.".format(key)) # MySQLCursor._reset_result() must call MySQLCursor.reset() self.assertEqual('Reset called', self.cur._test) def test__have_unread_result(self): """MySQLCursor object _have_unread_result()-method""" self.check_method(self.cur, '_have_unread_result') class FakeConnection(object): def __init__(self): self.unread_result = False self.cur = cursor.MySQLCursor() self.cur._connection = FakeConnection() self.cur._connection.unread_result = True self.assertTrue(self.cur._have_unread_result()) self.cur._connection.unread_result = False self.assertFalse(self.cur._have_unread_result()) def test_next(self): """MySQLCursor object next()-method""" self.check_method(self.cur, 'next') self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = cursor.MySQLCursor(self.connection) self.assertRaises(StopIteration, self.cur.next) self.cur.execute("SELECT SHA1('myconnpy')") exp = (u'c5e24647dbb63447682164d81b34fe493a83610b',) self.assertEqual(exp, self.cur.next()) self.cur.close() def test_close(self): """MySQLCursor object close()-method""" self.check_method(self.cur, 'close') self.assertEqual(False, self.cur.close(), "close() should return False with no connection") self.assertEqual(None, self.cur._connection) def test__process_params(self): """MySQLCursor object _process_params()-method""" self.check_method(self.cur, '_process_params') self.assertRaises( errors.ProgrammingError, self.cur._process_params, 'foo') self.assertRaises(errors.ProgrammingError, self.cur._process_params, ()) st_now = time.localtime() data = ( None, int(128), long(1281288), float(3.14), Decimal('3.14'), r'back\slash', 'newline\n', 'return\r', "'single'", '"double"', 'windows\032', str("Strings are sexy"), u'\u82b1', datetime.datetime(2008, 5, 7, 20, 0o1, 23), datetime.date(2008, 5, 7), datetime.time(20, 0o3, 23), st_now, datetime.timedelta(hours=40, minutes=30, seconds=12), ) exp = ( 'NULL', '128', '1281288', '3.14', "'3.14'", "'back\\\\slash'", "'newline\\n'", "'return\\r'", "'\\'single\\''", '\'\\"double\\"\'', "'windows\\\x1a'", "'Strings are sexy'", "'\xe8\x8a\xb1'", "'2008-05-07 20:01:23'", "'2008-05-07'", "'20:03:23'", "'" + time.strftime('%Y-%m-%d %H:%M:%S', st_now) + "'", "'40:30:12'", ) self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.assertEqual((), self.cur._process_params(()), "_process_params() should return a tuple") res = self.cur._process_params(data) for (i, exped) in enumerate(exp): self.assertEqual(exped, res[i]) self.cur.close() def test__process_params_dict(self): """MySQLCursor object _process_params_dict()-method""" self.check_method(self.cur, '_process_params') self.assertRaises( errors.ProgrammingError, self.cur._process_params, 'foo') self.assertRaises(errors.ProgrammingError, self.cur._process_params, ()) st_now = time.localtime() data = { 'a': None, 'b': int(128), 'c': long(1281288), 'd': float(3.14), 'e': Decimal('3.14'), 'f': 'back\slash', # pylint: disable=W1401 'g': 'newline\n', 'h': 'return\r', 'i': "'single'", 'j': '"double"', 'k': 'windows\032', 'l': str("Strings are sexy"), 'm': u'\u82b1', 'n': datetime.datetime(2008, 5, 7, 20, 0o1, 23), 'o': datetime.date(2008, 5, 7), 'p': datetime.time(20, 0o3, 23), 'q': st_now, 'r': datetime.timedelta(hours=40, minutes=30, seconds=12), } exp = { 'a': 'NULL', 'b': '128', 'c': '1281288', 'd': '3.14', 'e': "'3.14'", 'f': "'back\\\\slash'", 'g': "'newline\\n'", 'h': "'return\\r'", 'i': "'\\'single\\''", 'j': '\'\\"double\\"\'', 'k': "'windows\\\x1a'", 'l': "'Strings are sexy'", 'm': "'\xe8\x8a\xb1'", 'n': "'2008-05-07 20:01:23'", 'o': "'2008-05-07'", 'p': "'20:03:23'", 'q': "'" + time.strftime('%Y-%m-%d %H:%M:%S', st_now) + "'", 'r': "'40:30:12'", } self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.assertEqual({}, self.cur._process_params_dict({}), "_process_params_dict() should return a dict") self.assertEqual(exp, self.cur._process_params_dict(data)) self.cur.close() def test__fetch_warnings(self): """MySQLCursor object _fetch_warnings()-method""" self.check_method(self.cur, '_fetch_warnings') self.assertRaises(errors.InterfaceError, self.cur._fetch_warnings) config = tests.get_mysql_config() config['get_warnings'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchone() exp = [ (u'Warning', 1292, u"Truncated incorrect DOUBLE value: 'a'"), (u'Warning', 1292, u"Truncated incorrect DOUBLE value: 'b'") ] self.assertTrue(tests.cmp_result(exp, self.cur._fetch_warnings())) self.assertEqual(len(exp), self.cur._warning_count) def test__handle_noresultset(self): """MySQLCursor object _handle_noresultset()-method""" self.check_method(self.cur, '_handle_noresultset') self.assertRaises(errors.ProgrammingError, self.cur._handle_noresultset, None) data = { 'affected_rows': 1, 'insert_id': 10, 'warning_count': 100, 'server_status': 8, } self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.cur._handle_noresultset(data) self.assertEqual(data['affected_rows'], self.cur.rowcount) self.assertEqual(data['insert_id'], self.cur._last_insert_id) self.assertEqual(data['warning_count'], self.cur._warning_count) self.cur.close() def test__handle_result(self): """MySQLCursor object _handle_result()-method""" self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.assertRaises(errors.InterfaceError, self.cur._handle_result, None) self.assertRaises(errors.InterfaceError, self.cur._handle_result, 'spam') self.assertRaises(errors.InterfaceError, self.cur._handle_result, {'spam': 5}) cases = [ {'affected_rows': 99999, 'insert_id': 10, 'warning_count': 100, 'server_status': 8, }, {'eof': {'status_flag': 0, 'warning_count': 0}, 'columns': [('1', 8, None, None, None, None, 0, 129)] }, ] self.cur._handle_result(cases[0]) self.assertEqual(cases[0]['affected_rows'], self.cur.rowcount) self.assertFalse(self.cur._connection.unread_result) self.assertFalse(self.cur._have_unread_result()) self.cur._handle_result(cases[1]) self.assertEqual(cases[1]['columns'], self.cur.description) self.assertTrue(self.cur._connection.unread_result) self.assertTrue(self.cur._have_unread_result()) def test_execute(self): """MySQLCursor object execute()-method""" self.check_method(self.cur, 'execute') self.assertEqual(None, self.cur.execute(None, None)) config = tests.get_mysql_config() config['get_warnings'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() self.assertRaises(errors.ProgrammingError, self.cur.execute, 'SELECT %s,%s,%s', ('foo', 'bar',)) self.assertRaises(errors.ProgrammingError, self.cur.execute, 'SELECT %s,%s', ('foo', 'bar', 'foobar')) self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchone() exp = [ (u'Warning', 1292, u"Truncated incorrect DOUBLE value: 'a'"), (u'Warning', 1292, u"Truncated incorrect DOUBLE value: 'b'") ] self.assertTrue(tests.cmp_result(exp, self.cur._warnings)) self.cur.execute("SELECT BINARY 'myconnpy'") exp = [(u'myconnpy',)] self.assertEqual(exp, self.cur.fetchall()) self.cur.close() tbl = 'myconnpy_cursor' self._test_execute_setup(self.connection, tbl) stmt_insert = "INSERT INTO {0} (col1,col2) VALUES (%s,%s)".format(tbl) self.cur = self.connection.cursor() res = self.cur.execute(stmt_insert, (1, 100)) self.assertEqual(None, res, "Return value of execute() is wrong.") stmt_select = "SELECT col1,col2 FROM {0} ORDER BY col1".format(tbl) self.cur.execute(stmt_select) self.assertEqual([(1, u'100')], self.cur.fetchall(), "Insert test failed") data = {'id': 2} stmt = "SELECT * FROM {0} WHERE col1 <= %(id)s".format(tbl) self.cur.execute(stmt, data) self.assertEqual([(1, u'100')], self.cur.fetchall()) self._test_execute_cleanup(self.connection, tbl) self.cur.close() def test_executemany(self): """MySQLCursor object executemany()-method""" self.check_method(self.cur, 'executemany') self.assertEqual(None, self.cur.executemany(None, [])) config = tests.get_mysql_config() config['get_warnings'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() self.assertRaises(errors.InterfaceError, self.cur.executemany, 'foo', None) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'foo', 'foo') self.assertEqual(None, self.cur.executemany('foo', [])) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'foo', ['foo']) self.assertRaises(errors.ProgrammingError, self.cur.executemany, 'SELECT %s', [('foo',), 'foo']) self.assertRaises(errors.ProgrammingError, self.cur.executemany, "INSERT INTO t1 1 %s", [(1,), (2,)]) self.cur.executemany("SELECT SHA1(%s)", [('foo',), ('bar',)]) self.assertEqual(None, self.cur.fetchone()) self.cur.close() tbl = 'myconnpy_cursor' self._test_execute_setup(self.connection, tbl) stmt_insert = "INSERT INTO {0} (col1,col2) VALUES (%s,%s)".format(tbl) stmt_select = "SELECT col1,col2 FROM {0} ORDER BY col1".format(tbl) self.cur = self.connection.cursor() self.cur.executemany(stmt_insert, [(1, 100), (2, 200), (3, 300)]) self.assertEqual(3, self.cur.rowcount) self.cur.executemany("SELECT %s", [('f',), ('o',), ('o',)]) self.assertEqual(3, self.cur.rowcount) data = [{'id': 2}, {'id': 3}] stmt = "SELECT * FROM {0} WHERE col1 <= %(id)s".format(tbl) self.cur.executemany(stmt, data) self.assertEqual(5, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(1, u'100'), (2, u'200'), (3, u'300')], self.cur.fetchall(), "Multi insert test failed") data = [{'id': 2}, {'id': 3}] stmt = "DELETE FROM {0} WHERE col1 = %(id)s".format(tbl) self.cur.executemany(stmt, data) self.assertEqual(2, self.cur.rowcount) stmt = "TRUNCATE TABLE {0}".format(tbl) self.cur.execute(stmt) stmt = ( "/*comment*/INSERT/*comment*/INTO/*comment*/{0}(col1,col2)VALUES" "/*comment*/(%s,%s/*comment*/)/*comment()*/ON DUPLICATE KEY UPDATE" " col1 = VALUES(col1)" ).format(tbl) self.cur.executemany(stmt, [(4, 100), (5, 200), (6, 300)]) self.assertEqual(3, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(4, u'100'), (5, u'200'), (6, u'300')], self.cur.fetchall(), "Multi insert test failed") stmt = "TRUNCATE TABLE {0}".format(tbl) self.cur.execute(stmt) stmt = ( "/*comment*/INSERT/*comment*/INTO/*comment*/{0}(col1,col2)VALUES" "/*comment*/(%s,'/*100*/')/*comment()*/ON DUPLICATE KEY UPDATE " "col1 = VALUES(col1)" ).format(tbl) self.cur.executemany(stmt, [(4,), (5,)]) self.assertEqual(2, self.cur.rowcount) self.cur.execute(stmt_select) self.assertEqual([(4, u'/*100*/'), (5, u'/*100*/')], self.cur.fetchall(), "Multi insert test failed") self._test_execute_cleanup(self.connection, tbl) self.cur.close() def test_fetchwarnings(self): """MySQLCursor object fetchwarnings()-method""" self.check_method(self.cur, 'fetchwarnings') self.assertEqual(None, self.cur.fetchwarnings(), "There should be no warnings after initiating cursor.") exp = ['A warning'] self.cur._warnings = exp self.cur._warning_count = len(self.cur._warnings) self.assertEqual(exp, self.cur.fetchwarnings()) self.cur.close() def test_stored_results(self): """MySQLCursor object stored_results()-method""" self.check_method(self.cur, 'stored_results') self.assertEqual([], self.cur._stored_results) self.assertTrue(hasattr(self.cur.stored_results(), '__iter__')) self.cur._stored_results.append('abc') self.assertEqual('abc', self.cur.stored_results().next()) try: _ = self.cur.stored_results().next() except StopIteration: pass except: self.fail("StopIteration not raised") def _test_callproc_setup(self, connection): self._test_callproc_cleanup(connection) stmt_create1 = ( "CREATE PROCEDURE myconnpy_sp_1" "(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) " "BEGIN SET pProd := pFac1 * pFac2; END;") stmt_create2 = ( "CREATE PROCEDURE myconnpy_sp_2" "(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) " "BEGIN SELECT 'abc'; SELECT 'def'; SET pProd := pFac1 * pFac2; END;" ) stmt_create3 = ( "CREATE PROCEDURE myconnpy_sp_3" "(IN pStr1 VARCHAR(20), IN pStr2 VARCHAR(20), " "OUT pConCat VARCHAR(100)) " "BEGIN SET pConCat := CONCAT(pStr1, pStr2); END;") try: cursor = connection.cursor() cursor.execute(stmt_create1) cursor.execute(stmt_create2) cursor.execute(stmt_create3) except errors.Error as err: self.fail("Failed setting up test stored routine; {0}".format(err)) cursor.close() def _test_callproc_cleanup(self, connection): sp_names = ('myconnpy_sp_1', 'myconnpy_sp_2', 'myconnpy_sp_3') stmt_drop = "DROP PROCEDURE IF EXISTS {procname}" try: cursor = connection.cursor() for sp_name in sp_names: cursor.execute(stmt_drop.format(procname=sp_name)) except errors.Error as err: self.fail( "Failed cleaning up test stored routine; {0}".format(err)) cursor.close() def test_callproc(self): """MySQLCursor object callproc()-method""" self.check_method(self.cur, 'callproc') self.assertRaises(ValueError, self.cur.callproc, None) self.assertRaises(ValueError, self.cur.callproc, 'sp1', None) config = tests.get_mysql_config() config['get_warnings'] = True self.connection = connection.MySQLConnection(**config) self._test_callproc_setup(self.connection) self.cur = self.connection.cursor() exp = (5, 4, 20) result = self.cur.callproc('myconnpy_sp_1', (exp[0], exp[1], 0)) self.assertEqual([], self.cur._stored_results) self.assertEqual(exp, result) exp = (6, 5, 30) result = self.cur.callproc('myconnpy_sp_2', (exp[0], exp[1], 0)) self.assertTrue(isinstance(self.cur._stored_results, list)) self.assertEqual(exp, result) exp_results = [ ('abc',), ('def',) ] for result, exp in itertools.izip(self.cur.stored_results(), iter(exp_results)): self.assertEqual(exp, result.fetchone()) exp = ('ham', 'spam', 'hamspam') result = self.cur.callproc('myconnpy_sp_3', (exp[0], exp[1], '')) self.assertTrue(isinstance(self.cur._stored_results, list)) self.assertEqual(exp, result) self._test_callproc_cleanup(self.connection) self.cur.close() def test_fetchone(self): """MySQLCursor object fetchone()-method""" self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.cur.execute("SELECT SHA1('myconnpy')") exp = (u'c5e24647dbb63447682164d81b34fe493a83610b',) self.assertEqual(exp, self.cur.fetchone()) self.assertEqual(None, self.cur.fetchone()) self.cur.close() def test_fetchmany(self): """MySQLCursor object fetchmany()-method""" self.check_method(self.cur, 'fetchmany') self.assertEqual([], self.cur.fetchmany()) self.connection = connection.MySQLConnection(**tests.get_mysql_config()) tbl = 'myconnpy_fetch' self._test_execute_setup(self.connection, tbl) stmt_insert = ( "INSERT INTO {table} (col1,col2) " "VALUES (%s,%s)".format(table=tbl)) stmt_select = ( "SELECT col1,col2 FROM {table} " "ORDER BY col1 DESC".format(table=tbl)) self.cur = self.connection.cursor() nrrows = 10 data = [(i, str(i * 100)) for i in range(0, nrrows)] self.cur.executemany(stmt_insert, data) self.cur.execute(stmt_select) exp = [(9, u'900'), (8, u'800'), (7, u'700'), (6, u'600')] rows = self.cur.fetchmany(4) self.assertTrue(tests.cmp_result(exp, rows), "Fetching first 4 rows test failed.") exp = [(5, u'500'), (4, u'400'), (3, u'300')] rows = self.cur.fetchmany(3) self.assertTrue(tests.cmp_result(exp, rows), "Fetching next 3 rows test failed.") exp = [(2, u'200'), (1, u'100'), (0, u'0')] rows = self.cur.fetchmany(3) self.assertTrue(tests.cmp_result(exp, rows), "Fetching next 3 rows test failed.") self.assertEqual([], self.cur.fetchmany()) self._test_execute_cleanup(self.connection, tbl) self.cur.close() def test_fetchall(self): """MySQLCursor object fetchall()-method""" self.check_method(self.cur, 'fetchall') self.assertRaises(errors.InterfaceError, self.cur.fetchall) self.connection = connection.MySQLConnection(**tests.get_mysql_config()) tbl = 'myconnpy_fetch' self._test_execute_setup(self.connection, tbl) stmt_insert = ( "INSERT INTO {table} (col1,col2) " "VALUES (%s,%s)".format(table=tbl)) stmt_select = ( "SELECT col1,col2 FROM {table} " "ORDER BY col1 ASC".format(table=tbl)) self.cur = self.connection.cursor() self.cur.execute("SELECT * FROM {table}".format(table=tbl)) self.assertEqual([], self.cur.fetchall(), "fetchall() with empty result should return []") nrrows = 10 data = [(i, str(i * 100)) for i in range(0, nrrows)] self.cur.executemany(stmt_insert, data) self.cur.execute(stmt_select) self.assertTrue(tests.cmp_result(data, self.cur.fetchall()), "Fetching all rows failed.") self.assertEqual(None, self.cur.fetchone()) self._test_execute_cleanup(self.connection, tbl) self.cur.close() def test_raise_on_warning(self): self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.connection.raise_on_warnings = True self.cur = self.connection.cursor() try: self.cur.execute("SELECT 'a' + 'b'") self.cur.fetchall() except errors.Error: pass else: self.fail("Did not get exception while raising warnings.") def test__unicode__(self): """MySQLCursor object __unicode__()-method""" self.assertEqual("MySQLCursor: (Nothing executed yet)", str(self.cur.__unicode__())) self.connection = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.connection.cursor() self.cur.execute("SELECT VERSION()") self.cur.fetchone() self.assertEqual("MySQLCursor: SELECT VERSION()", str(self.cur.__unicode__())) stmt = "SELECT VERSION(),USER(),CURRENT_TIME(),NOW(),SHA1('myconnpy')" self.cur.execute(stmt) self.cur.fetchone() self.assertEqual("MySQLCursor: {0}..".format(stmt[:30]), str(self.cur.__unicode__())) self.cur.close() def test__str__(self): self.assertEqual("'MySQLCursor: (Nothing executed yet)'", self.cur.__str__()) def test_column_names(self): self.cnx = connection.MySQLConnection(**tests.get_mysql_config()) self.cur = self.cnx.cursor() stmt = "SELECT NOW() as now, 'The time' as label, 123 FROM dual" exp = (u'now', u'label', u'123') self.cur.execute(stmt) self.cur.fetchone() self.assertEqual(exp, self.cur.column_names) self.cur.close() def test_statement(self): self.cur = cursor.MySQLCursor() exp = 'SELECT * FROM ham' self.cur._executed = exp self.assertEqual(exp, self.cur.statement) self.cur._executed = ' ' + exp + ' ' self.assertEqual(exp, self.cur.statement) def test_with_rows(self): self.cur = cursor.MySQLCursor() self.assertFalse(self.cur.with_rows) self.cur._description = ('ham', 'spam') self.assertTrue(self.cur.with_rows) class MySQLCursorBufferedTests(tests.TestsCursor): def setUp(self): self.cur = cursor.MySQLCursorBuffered(connection=None) self.connection = None def test_init(self): """MySQLCursorBuffered object init""" try: cur = cursor.MySQLCursorBuffered(connection=None) except (SyntaxError, TypeError) as err: self.fail("Failed initializing MySQLCursorBuffered; {0}".format( err)) else: cur.close() self.assertRaises(errors.InterfaceError, cursor.MySQLCursorBuffered, connection='foo') def test__next_row(self): """MySQLCursorBuffered object _next_row-attribute""" self.check_attr(self.cur, '_next_row', 0) def test__rows(self): """MySQLCursorBuffered object _rows-attribute""" self.check_attr(self.cur, '_rows', None) def test_execute(self): """MySQLCursorBuffered object execute()-method """ self.check_method(self.cur, 'execute') self.assertEqual(None, self.cur.execute(None, None)) config = tests.get_mysql_config() config['buffered'] = True config['get_warnings'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() self.assertEqual(True, isinstance(self.cur, cursor.MySQLCursorBuffered)) self.cur.execute("SELECT 1") self.assertEqual([('1',)], self.cur._rows) def test_raise_on_warning(self): config = tests.get_mysql_config() config['buffered'] = True config['raise_on_warnings'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() try: self.cur.execute("SELECT 'a' + 'b'") except errors.Error: pass else: self.fail("Did not get exception while raising warnings.") def test_with_rows(self): cur = cursor.MySQLCursorBuffered() self.assertFalse(cur.with_rows) cur._rows = [('ham',)] self.assertTrue(cur.with_rows) class MySQLCursorRawTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() def tearDown(self): self.cur.close() self.connection.close() def test_fetchone(self): self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = ('1', 'string', '2010-12-31', '2.5') self.assertEqual(exp, self.cur.fetchone()) class MySQLCursorRawBufferedTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True config['buffered'] = True self.connection = connection.MySQLConnection(**config) self.cur = self.connection.cursor() def tearDown(self): self.cur.close() self.connection.close() def test_fetchone(self): self.check_method(self.cur, 'fetchone') self.assertEqual(None, self.cur.fetchone()) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = ('1', 'string', '2010-12-31', '2.5') self.assertEqual(exp, self.cur.fetchone()) def test_fetchall(self): self.check_method(self.cur, 'fetchall') self.assertRaises(errors.InterfaceError, self.cur.fetchall) self.cur.execute("SELECT 1, 'string', MAKEDATE(2010,365), 2.5") exp = [('1', 'string', '2010-12-31', '2.5')] self.assertEqual(exp, self.cur.fetchall()) class MySQLCursorPreparedTests(tests.TestsCursor): def setUp(self): config = tests.get_mysql_config() config['raw'] = True config['buffered'] = True self.cnx = connection.MySQLConnection(**config) def test_callproc(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertRaises(errors.NotSupportedError, cur.callproc) def test_close(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) cur.close() self.assertEqual(None, cur._prepared) def test_fetch_row(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertEqual(None, cur._fetch_row()) cur._description = [('c1', 5, None, None, None, None, 1, 128)] # Monkey patch the get_row method of the connection for testing def _get_row(binary, columns): # pylint: disable=W0613 try: row = self.cnx._test_fetch_row[0] self.cnx._test_fetch_row = self.cnx._test_fetch_row[1:] except IndexError: return None return row self.cnx.get_row = _get_row eof_info = {'status_flag': 0, 'warning_count': 2} self.cnx.unread_result = True self.cnx._test_fetch_row = [('1', None), (None, eof_info)] self.assertEqual('1', cur._fetch_row()) self.assertEqual((None, None), cur._nextrow) self.assertEqual(eof_info['warning_count'], cur._warning_count) cur._reset_result() self.cnx.unread_result = True self.cnx._test_fetch_row = [(None, eof_info)] self.assertEqual(None, cur._fetch_row()) self.assertEqual((None, None), cur._nextrow) self.assertEqual(eof_info['warning_count'], cur._warning_count) def test_execute(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) cur2 = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) # No 1 stmt = "SELECT (? * 2) AS c1" cur.execute(stmt, (5,)) self.assertEqual(stmt, cur._executed) exp = { 'num_params': 1, 'statement_id': 1, 'parameters': [('?', 253, None, None, None, None, 1, 128)], 'warning_count': 0, 'num_columns': 1, 'columns': [('c1', 5, None, None, None, None, 1, 128)] } self.assertEqual(exp, cur._prepared) # No 2 stmt = "SELECT (? * 3) AS c2" # first, execute should fail, because unread results of No 1 self.assertRaises(errors.InternalError, cur2.execute, stmt) cur.fetchall() # We call with wrong number of values for paramaters self.assertRaises(errors.ProgrammingError, cur2.execute, stmt, (1, 3)) cur2.execute(stmt, (5,)) self.assertEqual(stmt, cur2._executed) exp = { 'num_params': 1, 'statement_id': 2, 'parameters': [('?', 253, None, None, None, None, 1, 128)], 'warning_count': 0, 'num_columns': 1, 'columns': [('c2', 5, None, None, None, None, 1, 128)] } self.assertEqual(exp, cur2._prepared) self.assertEqual([(15,)], cur2.fetchall()) # No 3 data = (3, 4) exp = [(5.0,)] stmt = "SELECT SQRT(POW(?, 2) + POW(?, 2)) AS hypotenuse" cur.execute(stmt, data) self.assertEqual(3, cur._prepared['statement_id']) self.assertEqual(exp, cur.fetchall()) # Execute the already prepared statement data = (4, 5) exp = (6.4031242374328485,) cur.execute(stmt, data) self.assertEqual(3, cur._prepared['statement_id']) self.assertEqual(exp, cur.fetchone()) def test_executemany(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.assertEqual(None, cur.executemany(None, [])) self.assertRaises(errors.InterfaceError, cur.executemany, 'ham', None) self.assertRaises(errors.ProgrammingError, cur.executemany, 'ham', 'ham') self.assertEqual(None, cur.executemany('ham', [])) self.assertRaises(errors.ProgrammingError, cur.executemany, 'ham', ['ham']) cur.executemany("SELECT SHA1(%s)", [('ham',), ('bar',)]) self.assertEqual(None, cur.fetchone()) cur.close() cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) tbl = 'myconnpy_cursor' self._test_execute_setup(self.cnx, tbl) stmt_insert = "INSERT INTO {table} (col1,col2) VALUES (%s, %s)".format( table=tbl) stmt_select = "SELECT col1,col2 FROM {table} ORDER BY col1".format( table=tbl) cur.executemany(stmt_insert, [(1, 100), (2, 200), (3, 300)]) self.assertEqual(3, cur.rowcount) cur.executemany("SELECT %s", [('h',), ('a',), ('m',)]) self.assertEqual(3, cur.rowcount) cur.execute(stmt_select) self.assertEqual([(1, u'100'), (2, u'200'), (3, u'300')], cur.fetchall(), "Multi insert test failed") data = [(2,), (3,)] stmt = "DELETE FROM {table} WHERE col1 = %s".format(table=tbl) cur.executemany(stmt, data) self.assertEqual(2, cur.rowcount) self._test_execute_cleanup(self.cnx, tbl) cur.close() def test_fetchone(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _fetch_row(): try: row = cur._test_fetch_row[0] cur._test_fetch_row = cur._test_fetch_row[1:] except IndexError: return None return row cur._fetch_row = _fetch_row cur._test_fetch_row = [('ham',)] self.assertEqual(('ham',), cur.fetchone()) self.assertEqual(None, cur.fetchone()) def test_fetchmany(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _fetch_row(): try: row = cur._test_fetch_row[0] cur._test_fetch_row = cur._test_fetch_row[1:] except IndexError: return None return row cur._fetch_row = _fetch_row rows = [(1, 100), (2, 200), (3, 300)] cur._test_fetch_row = rows self.cnx.unread_result = True self.assertEqual(rows[0:2], cur.fetchmany(2)) self.assertEqual([rows[2]], cur.fetchmany(2)) self.assertEqual([], cur.fetchmany()) def test_fetchall(self): cur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) def _get_rows(binary, columns): # pylint: disable=W0613 self.unread_result = False # pylint: disable=W0201 return ( self.cnx._test_fetch_row, {'status_flag': 0, 'warning_count': 3} ) self.cnx.get_rows = _get_rows rows = [(1, 100), (2, 200), (3, 300)] self.cnx._test_fetch_row = rows self.cnx.unread_result = True self.assertEqual(rows, cur.fetchall()) self.assertEqual(len(rows), cur._rowcount) self.assertEqual(3, cur._warning_count) self.assertRaises(errors.InterfaceError, cur.fetchall) mysql-connector-python-1.1.6/tests/py2/test_network.py0000644001577100000120000004217012276514013022424 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.network """ import os import socket import logging from collections import deque import unittest import tests from mysql.connector import (network, errors, constants) LOGGER = logging.getLogger(tests.LOGGER_NAME) class NetworkTests(tests.MySQLConnectorTests): """Testing mysql.connector.network functions""" def test__prepare_packets(self): """Prepare packets for sending""" data = ('abcdefghijklmn', 1) exp = ['\x0e\x00\x00\x01abcdefghijklmn'] self.assertEqual(exp, network._prepare_packets(*(data))) data = ('a' * (constants.MAX_PACKET_LENGTH + 1000), 2) exp = [ '\xff\xff\xff\x02' + ('a' * constants.MAX_PACKET_LENGTH), '\xe8\x03\x00\x03' + ('a' * 1000) ] self.assertEqual(exp, network._prepare_packets(*(data))) class BaseMySQLSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network.BaseMySQLSocket""" def setUp(self): config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] self.cnx = network.BaseMySQLSocket() def tearDown(self): try: self.cnx.close_connection() except: pass def _get_socket(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) LOGGER.debug("Get socket for {host}:{port}".format( host=self._host, port=self._port)) sock.connect((self._host, self._port)) return sock def test_init(self): """MySQLSocket initialization""" exp = { 'sock': None, '_connection_timeout': None, '_packet_number': -1, '_packet_queue': deque(), 'recvsize': 1024 * 8, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_next_packet_number(self): """Test packet number property""" self.assertEqual(0, self.cnx.next_packet_number) self.assertEqual(0, self.cnx._packet_number) self.assertEqual(1, self.cnx.next_packet_number) self.assertEqual(1, self.cnx._packet_number) self.cnx._packet_number = 255 self.assertEqual(0, self.cnx.next_packet_number) def test_open_connection(self): """Opening a connection""" self.assertRaises(NotImplementedError, self.cnx.open_connection) def test_get_address(self): """Get the address of a connection""" self.assertRaises(NotImplementedError, self.cnx.get_address) def test_close_connection(self): """Closing a connection""" self.cnx.close_connection() self.assertEqual(None, self.cnx.sock) self.assertRaises(TypeError, self.cnx._packet_queue) def test_send_plain(self): """Send plain data through the socket""" data = 'asddfasdfasdf' self.assertRaises(errors.OperationalError, self.cnx.send_plain, data, 0) self.cnx.sock = tests.DummySocket() data = [ ('\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1), ('\x03\x53\x45\x4c\x45\x43\x54\x20\x22' + ('\x61' * (constants.MAX_PACKET_LENGTH + 1000)) + '\x22', 2)] self.assertRaises(Exception, self.cnx.send_plain, None, None) for buf in data: exp = network._prepare_packets(*buf) try: self.cnx.send_plain(*buf) except errors.Error as err: self.fail("Failed sending pktnr {0}: {1}".format( d[1], str(err))) self.assertEqual(exp, self.cnx.sock._client_sends) self.cnx.sock.reset() def test_send_compressed(self): """Send compressed data through the socket""" data = 'asddfasdfasdf' self.assertRaises(errors.OperationalError, self.cnx.send_compressed, data, 0) self.cnx.sock = tests.DummySocket() self.assertRaises(Exception, self.cnx.send_compressed, None, None) # Small packet data = ('\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1) exp = ['\x11\x00\x00\x00\x00\x00\x00\r\x00\x00\x01\x03SELECT "abc"'] try: self.cnx.send_compressed(*data) except errors.Error as err: self.fail("Failed sending pktnr {0}: {1}".format(data[1], err)) self.assertEqual(exp, self.cnx.sock._client_sends) self.cnx.sock.reset() # Slightly bigger packet (not getting compressed) data = ('\x03\x53\x45\x4c\x45\x43\x54\x20\x22\x61\x62\x63\x22', 1) exp = (24, '\x11\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x01\x03' '\x53\x45\x4c\x45\x43\x54\x20\x22') try: self.cnx.send_compressed(*data) except errors.Error as err: self.fail("Failed sending pktnr {0}: {1}".format(data[1], err)) received = self.cnx.sock._client_sends[0] self.assertEqual(exp, (len(received), received[:20])) self.cnx.sock.reset() # Big packet data = ('\x03\x53\x45\x4c\x45\x43\x54\x20\x22' + '\x61' * (constants.MAX_PACKET_LENGTH + 1000) + '\x22', 2) exp = [ (63, '\x38\x00\x00\x00\x00\x40\x00\x78\x9c\xed\xc1\x31' '\x0d\x00\x20\x0c\x00\xb0\x04\x8c'), (16322, '\xbb\x3f\x00\x01\xf9\xc3\xff\x78\x9c\xec\xc1\x81' '\x00\x00\x00\x00\x80\x20\xd6\xfd')] try: self.cnx.send_compressed(*data) except Exception as err: self.fail("Failed sending pktnr {0}: {1}".format(data[1], err)) received = [(len(r), r[:20]) for r in self.cnx.sock._client_sends] self.assertEqual(exp, received) self.cnx.sock.reset() def test_recv_plain(self): """Receive data from the socket""" self.cnx.sock = tests.DummySocket() def get_address(): return 'dummy' self.cnx.get_address = get_address # Receive a packet which is not 4 bytes long self.cnx.sock.add_packet('\01\01\01') self.assertRaises(errors.InterfaceError, self.cnx.recv_plain) # Receive the header of a packet, but nothing more self.cnx.sock.add_packet('\01\00\00\00') self.assertRaises(errors.InterfaceError, self.cnx.recv_plain) # Socket fails to receive and produces an error self.cnx.sock.raise_socket_error() self.assertRaises(errors.OperationalError, self.cnx.recv_plain) # Receive packets after a query, SELECT "Ham" exp = [ '\x01\x00\x00\x01\x01', '\x19\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x03\x48\x61\x6d\x00' '\x0c\x21\x00\x09\x00\x00\x00\xfd\x01\x00\x1f\x00\x00', '\x05\x00\x00\x03\xfe\x00\x00\x02\x00', '\x04\x00\x00\x04\x03\x48\x61\x6d', '\x05\x00\x00\x05\xfe\x00\x00\x02\x00', ] self.cnx.sock.reset() self.cnx.sock.add_packets(exp) length_exp = len(exp) result = [] packet = self.cnx.recv_plain() while packet: result.append(packet) if length_exp == len(result): break packet = self.cnx.recv_plain() self.assertEqual(exp, result) def test_recv_compressed(self): """Receive compressed data from the socket""" self.cnx.sock = tests.DummySocket() def get_address(): return 'dummy' self.cnx.get_address = get_address # Receive a packet which is not 7 bytes long self.cnx.sock.add_packet('\01\01\01\01\01\01') self.assertRaises(errors.InterfaceError, self.cnx.recv_compressed) # Receive the header of a packet, but nothing more self.cnx.sock.add_packet('\01\00\00\00\00\00\00') self.assertRaises(errors.InterfaceError, self.cnx.recv_compressed) # Socket fails to receive and produces an error self.cnx.sock.raise_socket_error() self.assertRaises(errors.OperationalError, self.cnx.recv_compressed) # Receive result of query SELECT REPEAT('a',1*1024*1024), 'XYZ' packets = ( "\x80\x00\x00\x01\x00\x40\x00\x78\x9c\xed\xcb\xbd\x0a\x81\x01" "\x14\xc7\xe1\xff\xeb\xa5\x28\x83\x4d\x26\x99\x7c\x44\x21\x37" "\x60\xb0\x4b\x06\x6c\x0a\xd7\xe3\x7a\x15\x79\xc9\xec\x0a\x9e" "\x67\x38\x9d\xd3\xaf\x53\x24\x45\x6d\x96\xd4\xca\xcb\xf5\x96" "\xa4\xbb\xdb\x6c\x37\xeb\xfd\x68\x78\x1e\x4e\x17\x93\xc5\x7c" "\xb9\xfa\x8e\x71\xda\x83\xaa\xde\xf3\x28\xd2\x4f\x7a\x49\xf9" "\x7b\x28\x0f\xc7\xd3\x27\xb6\xaa\xfd\xf9\x8d\x8d\xa4\xfe\xaa" "\xae\x34\xd3\x69\x3c\x93\xce\x19\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xeb\x0d\xe7\xa5\x29\xb8", "\x05\x04\x00\x02\x68\xc0\x0f\x78\x9c\xed\xc1\x31\x01\x00\x00" "\x08\x03\xa0\xc3\x92\xea\xb7\xfe\x25\x8c\x60\x01\x20\x01" + "\x00" * 999 + "\xe0\x53\x3d\x7b\x0a\x29\x40\x7b" ) exp = [ "\x01\x00\x00\x01\x02", "\x2d\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x17\x52\x45\x50" "\x45\x41\x54\x28\x27\x61\x27\x2c\x31\x2a\x31\x30\x32\x34\x2a" "\x31\x30\x32\x34\x29\x00\x0c\x21\x00\x00\x00\x90\x00\xfa\x01" "\x00\x1f\x00\x00", "\x19\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x03\x58\x59\x5a" "\x00\x0c\x21\x00\x09\x00\x00\x00\xfd\x01\x00\x1f\x00\x00", "\x05\x00\x00\x04\xfe\x00\x00\x00\x00", "\x08\x00\x10\x05\xfd\x00\x00\x10" + "\x61" * 1 * 1024 * 1024 + "\x03\x58\x59\x5a" ] self.cnx.sock.reset() self.cnx.sock.add_packets(packets) length_exp = len(exp) packet = self.cnx.recv_compressed() counter = 0 while packet and counter < length_exp: self.assertEqual(exp[counter], packet) packet = self.cnx.recv_compressed() counter += 1 def test_set_connection_timeout(self): """Set the connection timeout""" exp = 5 self.cnx.set_connection_timeout(exp) self.assertEqual(exp, self.cnx._connection_timeout) @unittest.skipIf(os.name == 'nt', "Skip UNIX Socket tests on Windows") class MySQLUnixSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network.MySQLUnixSocket""" def setUp(self): config = tests.get_mysql_config() self._unix_socket = config['unix_socket'] self.cnx = network.MySQLUnixSocket(unix_socket=config['unix_socket']) def tearDown(self): try: self.cnx.close_connection() except: pass def test_init(self): """MySQLUnixSocket initialization""" exp = { '_unix_socket': self._unix_socket, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_get_address(self): """Get path to the Unix socket""" exp = self._unix_socket self.assertEqual(exp, self.cnx.get_address()) def test_open_connection(self): """Open a connection using a Unix socket""" if os.name == 'nt': self.assertRaises(errors.InterfaceError, self.cnx.open_connection) else: try: self.cnx.open_connection() except errors.Error as err: self.fail(str(err)) @unittest.skipIf(not tests.SSL_AVAILABLE, "Skipped switch to SSL; Python has no SSL support") def test_switch_to_ssl(self): args = { 'ca': os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem'), 'cert': os.path.join(tests.SSL_DIR, 'tests_client_cert.pem'), 'key': os.path.join(tests.SSL_DIR, 'tests_client_key.pem'), } self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) # Handshake failure sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(4) sock.connect(self._unix_socket) self.cnx.sock = sock self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) class MySQLTCPSocketTests(tests.MySQLConnectorTests): """Testing mysql.connector.network..MySQLTCPSocket""" def setUp(self): config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] self.cnx = network.MySQLTCPSocket(host=self._host, port=self._port) def tearDown(self): try: self.cnx.close_connection() except: pass def test_init(self): """MySQLTCPSocket initialization""" exp = { 'server_host': self._host, 'server_port': self._port, 'force_ipv6': False, '_family': 0, } for key, value in exp.items(): self.assertEqual(value, self.cnx.__dict__[key]) def test_get_address(self): """Get TCP/IP address""" exp = "%s:%s" % (self._host, self._port) self.assertEqual(exp, self.cnx.get_address()) @unittest.skipIf(tests.IPV6_AVAILABLE, "Testing IPv6, not testing IPv4") def test_open_connection__ipv4(self): """Open a connection using TCP""" try: self.cnx.open_connection() except errors.Error as err: self.fail(str(err)) config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] cases = [ # Address, Expected Family, Should Raise, Force IPv6 (tests.get_mysql_config()['host'], socket.AF_INET, False, False), ] for case in cases: self._test_open_connection(*case) @unittest.skipIf(not tests.IPV6_AVAILABLE, "IPv6 testing disabled") def test_open_connection__ipv6(self): """Open a connection using TCP""" config = tests.get_mysql_config() self._host = config['host'] self._port = config['port'] cases = [ # Address, Expected Family, Should Raise, Force IPv6 ('::1', socket.AF_INET6, False, False), ('2001::14:06:77', socket.AF_INET6, True, False), ('xx:00:xx', socket.AF_INET6, True, False), ] for case in cases: self._test_open_connection(*case) def _test_open_connection(self, addr, family, should_raise, force): try: sock = network.MySQLTCPSocket(host=addr, port=self._port, force_ipv6=force) sock.set_connection_timeout(1) sock.open_connection() except (errors.InterfaceError, socket.error): if not should_raise: self.fail('{0} incorrectly raised socket.error'.format( addr)) else: if should_raise: self.fail('{0} should have raised socket.error'.format( addr)) else: self.assertEqual(family, sock._family, "Family for {0} did not match".format( addr, family, sock._family)) sock.close_connection() @unittest.skipIf(not tests.SSL_AVAILABLE, "Skipped switch to SSL; Python has no SSL support") def test_switch_to_ssl(self): """Switch the socket to use SSL""" args = { 'ca': os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem'), 'cert': os.path.join(tests.SSL_DIR, 'tests_client_cert.pem'), 'key': os.path.join(tests.SSL_DIR, 'tests_client_key.pem'), } self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) # Handshake failure (family, socktype, proto) = socket.getaddrinfo(self._host, self._port)[0][0:3] sock = socket.socket(family, socktype, proto) sock.settimeout(4) sock.connect((self._host, self._port)) self.cnx.sock = sock self.assertRaises(errors.InterfaceError, self.cnx.switch_to_ssl, **args) mysql-connector-python-1.1.6/tests/py2/test_conversion.py0000644001577100000120000004007112276514013023116 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.conversion """ from decimal import Decimal import datetime import time import tests from mysql.connector import conversion, constants class MySQLConverterBaseTests(tests.MySQLConnectorTests): def test_init(self): cnv = conversion.MySQLConverterBase() self.assertEqual('utf8', cnv.charset) self.assertEqual(True, cnv.use_unicode) def test_init2(self): cnv = conversion.MySQLConverterBase(charset='latin1', use_unicode=False) self.assertEqual('latin1', cnv.charset) self.assertEqual(False, cnv.use_unicode) def test_set_charset(self): cnv = conversion.MySQLConverterBase() cnv.set_charset('latin2') self.assertEqual('latin2', cnv.charset) def test_set_useunicode(self): cnv = conversion.MySQLConverterBase() cnv.set_unicode(False) self.assertEqual(False, cnv.use_unicode) def test_to_mysql(self): cnv = conversion.MySQLConverterBase() self.assertEqual('a value', cnv.to_mysql('a value')) def test_to_python(self): cnv = conversion.MySQLConverterBase() self.assertEqual('a value', cnv.to_python('nevermind', 'a value')) def test_escape(self): cnv = conversion.MySQLConverterBase() self.assertEqual("'a value'", cnv.escape("'a value'")) def test_quote(self): cnv = conversion.MySQLConverterBase() self.assertEqual("'a value'", cnv.escape("'a value'")) class MySQLConverterTests(tests.MySQLConnectorTests): def setUp(self): self.cnv = conversion.MySQLConverter() def tearDown(self): pass def test_init(self): pass def test_escape(self): """Making strings ready for MySQL operations""" data = ( None, # should stay the same int(128), # should stay the same long(1281288), # should stay the same float(3.14), # should stay the same Decimal('3.14'), # should stay a Decimal r'back\slash', 'newline\n', 'return\r', "'single'", '"double"', 'windows\032', ) exp = ( None, 128, 1281288, float(3.14), Decimal("3.14"), 'back\\\\slash', 'newline\\n', 'return\\r', "\\'single\\'", '\\"double\\"', 'windows\\\x1a' ) res = tuple([self.cnv.escape(v) for v in data]) self.failUnless(res, exp) def test_quote(self): """Quote values making them ready for MySQL operations.""" data = ( None, int(128), long(1281288), float(3.14), Decimal('3.14'), 'string A', "string B", ) exp = ( 'NULL', '128', '1281288', '3.14', '3.14', "'string A'", "'string B'", ) res = tuple([self.cnv.quote(value) for value in data]) self.failUnlessEqual(res, exp) def test_to_mysql(self): """Convert Python types to MySQL types using helper method""" st_now = time.localtime() data = ( 128, # int 1281288, # long float(3.14), # float str("Strings are sexy"), u'\u82b1', None, datetime.datetime(2008, 5, 7, 20, 0o1, 23), datetime.date(2008, 5, 7), datetime.time(20, 0o3, 23), st_now, datetime.timedelta(hours=40, minutes=30, seconds=12), Decimal('3.14'), ) exp = ( data[0], data[1], data[2], self.cnv._str_to_mysql(data[3]), self.cnv._unicode_to_mysql(data[4]), None, '2008-05-07 20:01:23', '2008-05-07', '20:03:23', time.strftime('%Y-%m-%d %H:%M:%S', st_now), '40:30:12', '3.14', ) res = tuple([self.cnv.to_mysql(value) for value in data]) self.failUnlessEqual(res, exp) def test__str_to_mysql(self): """A Python string is a MySQL string.""" data = str("Strings are sexy") res = self.cnv._str_to_mysql(data) self.assertEqual(data, res) def test__unicode_to_mysql(self): """Python unicode strings become encoded strings.""" data = u'\u82b1' res = self.cnv._unicode_to_mysql(data) exp = data.encode(self.cnv.charset) self.assertEqual(exp, res) def test__nonetype_to_mysql(self): """Python None stays None for MySQL.""" data = None res = self.cnv._nonetype_to_mysql(data) self.assertEqual(data, res) def test__datetime_to_mysql(self): """A datetime.datetime becomes formatted like Y-m-d H:M:S.f""" cases = [ (datetime.datetime(2008, 5, 7, 20, 1, 23), '2008-05-07 20:01:23'), (datetime.datetime(2012, 5, 2, 20, 1, 23, 10101), '2012-05-02 20:01:23.010101') ] for data, exp in cases: self.assertEqual(exp, self.cnv._datetime_to_mysql(data)) def test__date_to_mysql(self): """A datetime.date becomes formatted like Y-m-d""" data = datetime.date(2008, 5, 7) res = self.cnv._date_to_mysql(data) exp = data.strftime('%Y-%m-%d') self.assertEqual(exp, res) def test__time_to_mysql(self): """A datetime.time becomes formatted like Y-m-d H:M:S[.f]""" cases = [ (datetime.time(20, 3, 23), '20:03:23'), (datetime.time(20, 3, 23, 10101), '20:03:23.010101'), ] for data, exp in cases: self.assertEqual(exp, self.cnv._time_to_mysql(data)) def test__struct_time_to_mysql(self): """A time.struct_time becomes formatted like Y-m-d H:M:S[.f]""" data = time.localtime() res = self.cnv._struct_time_to_mysql(data) exp = time.strftime('%Y-%m-%d %H:%M:%S', data) self.assertEqual(exp, res) def test__timedelta_to_mysql(self): """A datetime.timedelta becomes format like 'H:M:S[.f]'""" cases = [ (datetime.timedelta(hours=40, minutes=30, seconds=12), '40:30:12'), (datetime.timedelta(hours=-40, minutes=30, seconds=12), '-40:30:12'), (datetime.timedelta(hours=40, minutes=-1, seconds=12), '39:59:12'), (datetime.timedelta(hours=-40, minutes=60, seconds=12), '-39:00:12'), (datetime.timedelta(hours=40, minutes=30, seconds=12, microseconds=10101), '40:30:12.010101'), (datetime.timedelta(hours=-40, minutes=30, seconds=12, microseconds=10101), '-40:30:12.010101'), (datetime.timedelta(hours=40, minutes=-1, seconds=12, microseconds=10101), '39:59:12.010101'), (datetime.timedelta(hours=-40, minutes=60, seconds=12, microseconds=10101), '-39:00:12.010101'), ] for data, exp in cases: self.assertEqual(exp, self.cnv._timedelta_to_mysql(data)) def test__decimal_to_mysql(self): """A decimal.Decimal becomes a string.""" data = Decimal('3.14') self.assertEqual('3.14', self.cnv._decimal_to_mysql(data)) def test_to_python(self): """Convert MySQL data to Python types using helper method""" data = ( #, None, None, None, None, True, constants.FieldFlag.NUM), ('3.14', ('float', constants.FieldType.FLOAT)), ('128', ('int', constants.FieldType.TINY)), ('1281288', ('long', constants.FieldType.LONG)), ('3.14', ('decimal', constants.FieldType.DECIMAL)), ('2008-05-07', ('date', constants.FieldType.DATE)), ('45:34:10', ('time', constants.FieldType.TIME)), ('2008-05-07 22:34:10', ('datetime', constants.FieldType.DATETIME)), ('val1,val2', ('set', constants.FieldType.SET, None, None, None, None, True, constants.FieldFlag.SET)), ('\xc3\xa4 utf8 string', ('utf8', constants.FieldType.STRING, None, None, None, None, True, 0)), ('2008', ('year', constants.FieldType.YEAR)), ('\x80\x00\x00\x00', ('bit', constants.FieldType.BIT)), ) exp = ( float(data[0][0]), int(data[1][0]), long(data[2][0]), Decimal(data[3][0]), datetime.date(2008, 5, 7), datetime.timedelta(hours=45, minutes=34, seconds=10), datetime.datetime(2008, 5, 7, 22, 34, 10), set(['val1', 'val2']), unicode(data[8][0], 'utf8'), int(data[9][0]), 2147483648, ) res = tuple([self.cnv.to_python(v[1], v[0]) for v in data]) self.failUnlessEqual(res, exp) def test__FLOAT_to_python(self): """Convert a MySQL FLOAT/DOUBLE to a Python float type""" data = '3.14' exp = float(data) res = self.cnv._FLOAT_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._FLOAT_to_python, self.cnv._DOUBLE_to_python) def test__INT_to_python(self): """Convert a MySQL TINY/SHORT/INT24/INT to a Python int type""" data = '128' exp = int(data) res = self.cnv._INT_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._INT_to_python, self.cnv._TINY_to_python) self.assertEqual(self.cnv._INT_to_python, self.cnv._SHORT_to_python) self.assertEqual(self.cnv._INT_to_python, self.cnv._INT24_to_python) def test__LONG_to_python(self): """Convert a MySQL LONG/LONGLONG to a Python long type""" data = '1281288' exp = long(data) res = self.cnv._LONG_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._LONG_to_python, self.cnv._LONGLONG_to_python) def test__DECIMAL_to_python(self): """Convert a MySQL DECIMAL to a Python decimal.Decimal type""" data = '3.14' exp = Decimal(data) res = self.cnv._DECIMAL_to_python(data) self.assertEqual(exp, res) self.assertEqual(self.cnv._DECIMAL_to_python, self.cnv._NEWDECIMAL_to_python) def test__BIT_to_python(self): """Convert a MySQL BIT to Python int""" data = [ '\x80', '\x80\x00', '\x80\x00\x00', '\x80\x00\x00\x00', '\x80\x00\x00\x00\x00', '\x80\x00\x00\x00\x00\x00', '\x80\x00\x00\x00\x00\x00\x00', '\x80\x00\x00\x00\x00\x00\x00\x00', ] exp = [128, 32768, 8388608, 2147483648, 549755813888, 140737488355328, 36028797018963968, 9223372036854775808] res = map(self.cnv._BIT_to_python, data) self.assertEqual(exp, res) def test__DATE_to_python(self): """Convert a MySQL DATE to a Python datetime.date type""" data = '2008-05-07' exp = datetime.date(2008, 5, 7) res = self.cnv._DATE_to_python(data) self.assertEqual(exp, res) res = self.cnv._DATE_to_python('0000-00-00') self.assertEqual(None, res) res = self.cnv._DATE_to_python('1000-00-00') self.assertEqual(None, res) def test__TIME_to_python(self): """Convert a MySQL TIME to a Python datetime.time type""" cases = [ ('45:34:10', datetime.timedelta(hours=45, minutes=34, seconds=10)), ('-45:34:10', datetime.timedelta(hours=-45, minutes=34, seconds=10)), ('45:34:10.010101', datetime.timedelta(hours=45, minutes=34, seconds=10, microseconds=10101)), ('-45:34:10.010101', datetime.timedelta(hours=-45, minutes=34, seconds=10, microseconds=10101)), ] for data, exp in cases: self.assertEqual(exp, self.cnv._TIME_to_python(data)) def test__DATETIME_to_python(self): """Convert a MySQL DATETIME to a Python datetime.datetime type""" cases = [ ('2008-05-07 22:34:10', datetime.datetime(2008, 5, 7, 22, 34, 10)), ('2008-05-07 22:34:10.010101', datetime.datetime(2008, 5, 7, 22, 34, 10, 10101)), ('0000-00-00 00:00:00', None), ('1000-00-00 00:00:00', None), ] for data, exp in cases: self.assertEqual(exp, self.cnv._DATETIME_to_python(data)) def test__YEAR_to_python(self): """Convert a MySQL YEAR to Python int""" data = '2008' exp = 2008 self.assertEqual(exp, self.cnv._YEAR_to_python(data)) data = 'foobar' self.assertRaises(ValueError, self.cnv._YEAR_to_python, data) def test__SET_to_python(self): """Convert a MySQL SET type to a Python sequence This actually calls hte _STRING_to_python() method since a SET is returned as string by MySQL. However, the description of the field has in it's field flags that the string is a SET. """ data = 'val1,val2' exp = set(['val1', 'val2']) desc = ('foo', constants.FieldType.STRING, 2, 3, 4, 5, 6, constants.FieldFlag.SET) res = self.cnv._STRING_to_python(data, desc) self.assertEqual(exp, res) def test__STRING_to_python_utf8(self): """Convert a UTF-8 MySQL STRING/VAR_STRING to a Python Unicode type""" self.cnv.set_charset('utf8') # default data = '\xc3\xa4 utf8 string' exp = unicode(data, 'utf8') res = self.cnv._STRING_to_python(data) self.assertEqual(exp, res) def test__STRING_to_python_latin1(self): """Convert a ISO-8859-1 MySQL STRING/VAR_STRING to a Python str""" self.cnv.set_charset('latin1') self.cnv.set_unicode(False) data = '\xe4 latin string' exp = data res = self.cnv._STRING_to_python(data) self.assertEqual(exp, res) self.cnv.set_charset('utf8') self.cnv.set_unicode(True) def test__STRING_to_python_binary(self): """Convert a STRING BINARY to Python bytes type""" data = '\x33\xfd\x34\xed' desc = ('foo', constants.FieldType.STRING, 2, 3, 4, 5, 6, constants.FieldFlag.BINARY) res = self.cnv._STRING_to_python(data, desc) self.assertEqual(data, res) def test__BLOB_to_python_binary(self): """Convert a BLOB BINARY to Python bytes type""" data = '\x33\xfd\x34\xed' desc = ('foo', constants.FieldType.BLOB, 2, 3, 4, 5, 6, constants.FieldFlag.BINARY) res = self.cnv._BLOB_to_python(data, desc) self.assertEqual(data, res) mysql-connector-python-1.1.6/tests/test_bugs.py0000644001577100000120000021335412276514013021165 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Incur., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Test module for bugs Bug test cases specific to a particular Python (major) version are loaded from py2.bugs or py3.bugs. This module was originally located in python2/tests and python3/tests. It should contain bug test cases which work for both Python v2 and v3. Whenever a bug is bout to a specific Python version, put the test cases in tests/py2/bugs.py or tests/py3/bugs.py. It might be that these files need to be created first. """ import os import sys import gc import tempfile from datetime import datetime from threading import Thread import time import unittest import tests from mysql.connector import (connection, cursor, conversion, protocol, errors, constants, pooling) from mysql.connector import connect, _CONNECTION_POOLS if sys.version_info[0] == 2: from tests.py2.bugs import * else: from tests.py3.bugs import * import mysql.connector class Bug328998Tests(tests.MySQLConnectorTests): """Tests where connection timeout has been set""" def test_set_connection_timetout(self): """Test MySQLConnection.set_connection_timeout""" config = tests.get_mysql_config() config['connection_timeout'] = 5 self.cnx = connection.MySQLConnection(**config) self.assertEqual(config['connection_timeout'], self.cnx._socket._connection_timeout) if self.cnx: self.cnx.disconnect() def test_timeout(self): """Test the connection timing out""" config = tests.get_mysql_config() config['connection_timeout'] = 1 self.cnx = connection.MySQLConnection(**config) cur = self.cnx.cursor() self.assertRaises( errors.OperationalError, cur.execute, "SELECT SLEEP({0})".format(config['connection_timeout'] + 4) ) if self.cnx: self.cnx.disconnect() class Bug437972Tests(tests.MySQLConnectorTests): def test_windows_tcp_connection(self): """lp:437972 TCP connection to Windows""" if os.name != 'nt': pass cnx = None try: cnx = connection.MySQLConnection(**tests.get_mysql_config()) except errors.InterfaceError: self.fail() if cnx: cnx.close() class Bug441430Tests(tests.MySQLConnectorTests): def test_execute_return(self): """lp:441430 cursor.execute*() should return the cursor.rowcount""" cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() tbl = "buglp44130" cur.execute("DROP TABLE IF EXISTS %s" % tbl) cur.execute("CREATE TABLE %s (id INT)" % tbl) cur.execute("INSERT INTO %s VALUES (%%s),(%%s)" % tbl, (1, 2,)) self.assertEqual(2, cur.rowcount) stmt = "INSERT INTO %s VALUES (%%s)" % tbl res = cur.executemany(stmt, [(3,), (4,), (5,), (6,), (7,), (8,)]) self.assertEqual(6, cur.rowcount) res = cur.execute("UPDATE %s SET id = id + %%s" % tbl, (10,)) self.assertEqual(8, cur.rowcount) cur.close() cnx.close() class Bug454782(tests.MySQLConnectorTests): def test_fetch_retun_values(self): """lp:454782 fetchone() does not follow pep-0249""" cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() self.assertEqual(None, cur.fetchone()) self.assertEqual([], cur.fetchmany()) self.assertRaises(errors.InterfaceError, cur.fetchall) cur.close() cnx.close() class Bug454790(tests.MySQLConnectorTests): def test_pyformat(self): """lp:454790 pyformat / other named parameters broken""" cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() data = {'name': 'Geert', 'year': 1977} cur.execute("SELECT %(name)s,%(year)s", data) self.assertEqual(('Geert', 1977), cur.fetchone()) data = [ {'name': 'Geert', 'year': 1977}, {'name': 'Marta', 'year': 1980} ] cur.executemany("SELECT %(name)s,%(year)s", data) self.assertEqual(2, cur.rowcount) cur.close() cnx.close() class Bug480360(tests.MySQLConnectorTests): def test_fetchall(self): """lp:480360: fetchall() should return [] when no result""" cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() # Trick to get empty result not needing any table cur.execute("SELECT * FROM (SELECT 1) AS t WHERE 0 = 1") self.assertEqual([], cur.fetchall()) cur.close() cnx.close() class Bug380528(tests.MySQLConnectorTests): def test_old_password(self): """lp:380528: we do not support old passwords.""" if tests.MYSQL_VERSION >= (5, 6, 6): # Test not valid for MySQL 5.6.6 and later. return config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) cur = cnx.cursor() if config['unix_socket'] and os.name != 'nt': user = "'myconnpy'@'localhost'" else: user = "'myconnpy'@'%s'" % (config['host']) try: cur.execute("GRANT SELECT ON %s.* TO %s" % (config['database'], user)) cur.execute("SET PASSWORD FOR %s = OLD_PASSWORD('fubar')" % (user)) except: self.fail("Failed executing grant.") cur.close() cnx.close() # Test using the newly created user test_config = config.copy() test_config['user'] = 'myconnpy' test_config['password'] = 'fubar' self.assertRaises(errors.NotSupportedError, connection.MySQLConnection, **test_config) cnx = connection.MySQLConnection(**config) cur = cnx.cursor() try: cur.execute("REVOKE SELECT ON %s.* FROM %s" % (config['database'], user)) cur.execute("DROP USER %s" % (user)) except: self.fail("Failed cleaning up user %s." % (user)) cur.close() cnx.close() class Bug499362(tests.MySQLConnectorTests): def test_charset(self): """lp:499362 Setting character set at connection fails""" config = tests.get_mysql_config() config['charset'] = 'latin1' cnx = connection.MySQLConnection(**config) cur = cnx.cursor() ver = cnx.get_server_version() if ver < (5, 1, 12): exp1 = [('character_set_client', 'latin1'), ('character_set_connection', 'latin1'), ('character_set_database', 'utf8'), ('character_set_filesystem', 'binary'), ('character_set_results', 'latin1'), ('character_set_server', 'utf8'), ('character_set_system', 'utf8')] exp2 = [('character_set_client', 'latin2'), ('character_set_connection', 'latin2'), ('character_set_database', 'utf8'), ('character_set_filesystem', 'binary'), ('character_set_results', 'latin2'), ('character_set_server', 'utf8'), ('character_set_system', 'utf8')] varlst = [] stmt = r"SHOW SESSION VARIABLES LIKE 'character\_set\_%%'" else: exp1 = [('CHARACTER_SET_CONNECTION', 'latin1'), ('CHARACTER_SET_CLIENT', 'latin1'), ('CHARACTER_SET_RESULTS', 'latin1')] exp2 = [('CHARACTER_SET_CONNECTION', 'latin2'), ('CHARACTER_SET_CLIENT', 'latin2'), ('CHARACTER_SET_RESULTS', 'latin2')] varlst = ['character_set_client', 'character_set_connection', 'character_set_results'] stmt = """SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME IN (%s,%s,%s)""" cur.execute(stmt, varlst) res1 = cur.fetchall() cnx.set_charset_collation('latin2') cur.execute(stmt, varlst) res2 = cur.fetchall() cur.close() cnx.close() self.assertTrue(tests.cmp_result(exp1, res1)) self.assertTrue(tests.cmp_result(exp2, res2)) class Bug501290(tests.MySQLConnectorTests): """lp:501290 Client flags are set to None when connecting""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) def tearDown(self): self.cnx.close() def test_default(self): """lp:501290 Check default client flags""" self.assertEqual(self.cnx._client_flags, constants.ClientFlag.get_default()) def test_set_unset(self): """lp:501290 Set/unset one flag, check if set/unset""" orig = self.cnx._client_flags exp = constants.ClientFlag.get_default() | \ constants.ClientFlag.COMPRESS self.cnx.set_client_flags([constants.ClientFlag.COMPRESS]) self.assertEqual(self.cnx._client_flags, exp) self.cnx.set_client_flags([-constants.ClientFlag.COMPRESS]) self.assertEqual(self.cnx._client_flags, orig) def test_isset_client_flag(self): """lp:501290 Check if client flag is set""" data = constants.ClientFlag.get_default() | \ constants.ClientFlag.COMPRESS self.cnx._client_flags = data self.assertEqual(True, self.cnx.isset_client_flag(constants.ClientFlag.COMPRESS)) class Bug507466(tests.MySQLConnectorTests): """lp:507466 BIT values are not converted correctly to Python""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) def tearDown(self): try: cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS myconnpy_bits") except: pass self.cnx.close() def test_bits(self): """lp:507466 Store bitwise values in MySQL and retrieve them""" cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS myconnpy_bits") cur.execute("""CREATE TABLE `myconnpy_bits` ( `id` int NOT NULL AUTO_INCREMENT, `c1` bit(8) DEFAULT NULL, `c2` bit(16) DEFAULT NULL, `c3` bit(24) DEFAULT NULL, `c4` bit(32) DEFAULT NULL, `c5` bit(40) DEFAULT NULL, `c6` bit(48) DEFAULT NULL, `c7` bit(56) DEFAULT NULL, `c8` bit(64) DEFAULT NULL, PRIMARY KEY (id) ) """) insert = """insert into myconnpy_bits (c1,c2,c3,c4,c5,c6,c7,c8) values (%s,%s,%s,%s,%s,%s,%s,%s)""" select = "SELECT c1,c2,c3,c4,c5,c6,c7,c8 FROM myconnpy_bits ORDER BY id" data = [] data.append((0, 0, 0, 0, 0, 0, 0, 0)) data.append(( 1 << 7, 1 << 15, 1 << 23, 1 << 31, 1 << 39, 1 << 47, 1 << 55, 1 << 63, )) cur.executemany(insert, data) cur.execute(select) rows = cur.fetchall() self.assertEqual(rows, data) class Bug519301(tests.MySQLConnectorTests): """lp:519301 Temporary connection failures with 2 exceptions""" def test_auth(self): """lp:519301 Temporary connection failures with 2 exceptions""" config = tests.get_mysql_config() config['user'] = 'ham' config['password'] = 'spam' cnx = None for _ in range(1, 100): try: cnx = connection.MySQLConnection(**config) except errors.ProgrammingError: pass except errors.Error as err: self.fail("Failing authenticating: {0}".format(str(err))) except: raise else: cnx.close() class Bug524668(tests.MySQLConnectorTests): """lp:524668 Error in server handshake with latest code""" def test_handshake(self): """lp:524668 Error in server handshake with latest code""" if sys.version_info[0] == 2: handshake = ( '\x47\x00\x00\x00\x0a\x35\x2e\x30\x2e\x33\x30\x2d\x65' '\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67\x70\x6c' '\x2d\x6c\x6f' '\x67\x00\x09\x01\x00\x00\x68\x34\x69\x36\x6f\x50\x21\x4f\x00' '\x2c\xa2\x08\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' '\x00' '\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72\x59\x48\x00' ) else: handshake = ( b'\x47\x00\x00\x00\x0a\x35\x2e\x30\x2e\x33\x30\x2d\x65' b'\x6e\x74\x65\x72\x70\x72\x69\x73\x65\x2d\x67\x70\x6c' b'\x2d\x6c\x6f' b'\x67\x00\x09\x01\x00\x00\x68\x34\x69\x36\x6f\x50\x21\x4f\x00' b'\x2c\xa2\x08\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00' b'\x00\x00\x4c\x6e\x67\x39\x26\x50\x44\x40\x57\x72\x59\x48\x00' ) prtcl = protocol.MySQLProtocol() try: prtcl.parse_handshake(handshake) except: self.fail("Failed handling handshake") class Bug571201(tests.MySQLConnectorTests): """lp:571201 Problem with more than one statement at a time""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.tbl = 'Bug571201' self.cur.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) self.cur.execute("""CREATE TABLE %s ( id INT AUTO_INCREMENT KEY, c1 INT )""" % (self.tbl)) def tearDown(self): try: cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) except: pass self.cnx.close() def test_multistmts(self): """lp:571201 Problem with more than one statement at a time""" stmts = [ "SELECT * FROM %s" % (self.tbl), "INSERT INTO %s (c1) VALUES (10),(20)" % (self.tbl), "SELECT * FROM %s" % (self.tbl), ] result_iter = self.cur.execute(';'.join(stmts), multi=True) if sys.version_info[0] == 2: self.assertEqual(None, result_iter.next().fetchone()) self.assertEqual(2, result_iter.next().rowcount) exp = [(1, 10), (2, 20)] self.assertEqual(exp, result_iter.next().fetchall()) self.assertRaises(StopIteration, result_iter.next) else: self.assertEqual(None, next(result_iter).fetchone()) self.assertEqual(2, next(result_iter).rowcount) exp = [(1, 10), (2, 20)] self.assertEqual(exp, next(result_iter).fetchall()) with self.assertRaises(StopIteration): next(result_iter) class Bug551533and586003(tests.MySQLConnectorTests): """lp: 551533 as 586003: impossible to retrieve big result sets""" def setUp(self): config = tests.get_mysql_config() config['connection_timeout'] = 20 self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.tbl = 'Bug551533' self.cur.execute("DROP TABLE IF EXISTS {table}".format(table=self.tbl)) self.cur.execute(( "CREATE TABLE {table} (" "id INT AUTO_INCREMENT KEY, " "c1 VARCHAR(100) DEFAULT 'abcabcabcabcabcabcabcabcabcabc'" ") ENGINE=INNODB" ).format(table=self.tbl) ) def tearDown(self): try: cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS {table}".format(table=self.tbl)) except: pass self.cnx.close() def test_select(self): """lp: 551533 as 586003: impossible to retrieve big result sets""" insert = "INSERT INTO {table} (id) VALUES (%s)".format(table=self.tbl) exp = 20000 self.cur.executemany(insert, [(None,)] * exp) self.cnx.commit() self.cur.execute( 'SELECT * FROM {table} LIMIT 20000'.format(table=self.tbl)) try: self.cur.fetchall() except errors.Error as err: self.fail("Failed retrieving big result set: {0}".format(err)) else: self.assertEqual(exp, self.cur.rowcount) class Bug598706(tests.MySQLConnectorTests): """lp: 598706: config file in examples doesn't return the port""" def test_getport(self): """lp: 598706: config file in examples doesn't return the port""" from examples import config exp = 3306 data = config.Config.dbinfo() self.assertEqual(exp, data['port']) class Bug675425(tests.MySQLConnectorTests): """lp: 675425: Problems with apostrophe""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.tbl = 'Bug675425' self.cur.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) self.cur.execute("""CREATE TABLE %s ( c1 VARCHAR(30), c2 VARCHAR(30) )""" % (self.tbl)) def tearDown(self): try: cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) except: pass self.cnx.close() def test_executemany_escape(self): """lp: 675425: Problems with apostrophe""" data = [ ("ham", "spam",), ("spam", "ham",), ("ham \\' spam", "spam ' ham",) ] sql = "INSERT INTO %s VALUES (%%s,%%s)" % (self.tbl) try: self.cur.executemany(sql, data) except: self.fail("Failed inserting using executemany" " and escaped strings") class Bug695514(tests.MySQLConnectorTests): """lp: 695514: Infinite recursion when setting connection client_flags""" def test_client_flags(self): """lp: 695514: Infinite recursion when setting connection client_flags """ try: config = tests.get_mysql_config() config['connection_timeout'] = 2 config['client_flags'] = constants.ClientFlag.get_default() cnx = connection.MySQLConnection(**config) cnx.close() except: self.fail("Failed setting client_flags using integer") class Bug809033(tests.MySQLConnectorTests): """lp: 809033: Lost connection causes infinite loop""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.table_name = 'Bug809033' self.cnx.cmd_query("DROP TABLE IF EXISTS {0}".format(self.table_name)) table = ( "CREATE TABLE {table} (" " id INT UNSIGNED NOT NULL AUTO_INCREMENT," " c1 VARCHAR(255) DEFAULT '{default}'," " PRIMARY KEY (id)" ")" ).format(table=self.table_name, default='a' * 255) self.cnx.cmd_query(table) stmt = "INSERT INTO {table} (id) VALUES {values}".format( table=self.table_name, values=','.join(['(NULL)'] * 1024) ) self.cnx.cmd_query(stmt) def tearDown(self): try: cnx = connection.MySQLConnection(**tests.get_mysql_config()) cnx.cmd_query( "DROP TABLE IF EXISTS {0}".format(self.table_name)) cnx.close() except: pass def test_lost_connection(self): """lp: 809033: Lost connection causes infinite loop""" def kill(connection_id): """Kill connection using separate connection""" killer = connection.MySQLConnection(**tests.get_mysql_config()) time.sleep(1) killer.cmd_query("KILL {0}".format(connection_id)) killer.close() def sleepy_select(cnx): """Execute a SELECT statement which takes a while to complete""" cur = cnx.cursor() # Ugly query ahead! stmt = "SELECT x1.*, x2.* from {table} as x1, {table} as x2".format( table=self.table_name) cur.execute(stmt) # Save the error so we can check in the calling thread cnx.test_error = None try: cur.fetchall() except errors.InterfaceError as err: cnx.test_error = err worker = Thread(target=sleepy_select, args=[self.cnx]) killer = Thread(target=kill, args=[self.cnx.connection_id]) worker.start() killer.start() worker.join() killer.join() self.assertTrue(isinstance(self.cnx.test_error, errors.InterfaceError)) class Bug865859(tests.MySQLConnectorTests): """lp: 865859: sock.recv fails to return in some cases (infinite wait)""" def test_reassign_connection(self): """lp: 865859: sock.recv fails to return in some cases (infinite wait) """ config = tests.get_mysql_config() config['connection_timeout'] = 1 cnx = connection.MySQLConnection(**config) cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS t1") cur.execute("CREATE TABLE t1 (c1 INT)") cur.execute("INSERT INTO t1 (c1) VALUES (1)") try: cnx = connection.MySQLConnection(**config) cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS t1") except errors.InterfaceError as err: self.fail( "Connection was not closed, we got timeout: {0}".format(err)) class BugOra13395083(tests.MySQLConnectorTests): def test_time_zone(self): """BUG#13395083: Using time zones""" config = tests.get_mysql_config() utc = tests.UTCTimeZone() testzone = tests.TestTimeZone(+2) # Store a datetime in UTC into a TIMESTAMP column config['time_zone'] = "+00:00" now_utc = datetime.utcnow().replace(microsecond=0, tzinfo=utc) cnx = connection.MySQLConnection(**config) cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS t1") cur.execute("CREATE TABLE t1 (c1 TIMESTAMP)") cur.execute("INSERT INTO t1 (c1) VALUES (%s)", (now_utc,)) cnx.commit() cur.execute("SELECT c1 FROM t1") row = cur.fetchone() self.assertEqual(now_utc, row[0].replace(tzinfo=utc)) cnx.set_time_zone("+02:00") cur.execute("SELECT c1 FROM t1") row = cur.fetchone() self.assertEqual(now_utc.astimezone(testzone), row[0].replace(tzinfo=testzone)) cnx.close() class BugOra13392739(tests.MySQLConnectorTests): def test_ping(self): """BUG#13392739: MySQLConnection.ping()""" config = tests.get_mysql_config() config['connection_timeout'] = 2 config['unix_socket'] = None cnx = connection.MySQLConnection() self.assertRaises(errors.InterfaceError, cnx.ping) cnx = connection.MySQLConnection(**config) try: cnx.ping() except Exception as e: self.fail("Error raised although connection should be " "available (%s)." % e) cnx.disconnect() self.assertRaises(errors.InterfaceError, cnx.ping) try: cnx.ping(reconnect=True) except Exception as e: self.fail("Error raised although ping should reconnect. (%s)" % e) # Temper with the host to which we reconnect to simulate the # MySQL not being available. cnx.disconnect() cnx._host = 'some-unknown-host-somwhere-on.mars' self.assertRaises(errors.InterfaceError, cnx.ping, reconnect=True) def test_reconnect(self): """BUG#13392739: MySQLConnection.reconnect()""" config = tests.get_mysql_config() config['connection_timeout'] = 1 config['unix_socket'] = None cnx = connection.MySQLConnection(**config) cnx.disconnect() self.assertRaises(errors.InterfaceError, cnx.ping) try: cnx.reconnect() except: self.fail("Errors raised although connection should have been " "reconnected.") cnx.disconnect() # Temper with the host to which we reconnect to simulate the # MySQL not being available. cnx._host = 'some-unknown-host-somwhere-on.mars' self.assertRaises(errors.InterfaceError, cnx.reconnect) try: cnx.reconnect(attempts=3) except errors.InterfaceError as e: self.assertTrue('3 attempt(s)' in str(e)) class BugOra13435186(tests.MySQLConnectorTests): def setUp(self): self.sample_size = 100 self.tolerate = 5 self._reset_samples() self.samples = [0, ] * self.sample_size gc.collect() def _reset_samples(self): self.samples = [0, ] * self.sample_size def _assert_flat_line(self, samples): counters = {} for value in samples: try: counters[value] = counters[value] + 1 except KeyError: counters[value] = 1 if len(counters) > self.tolerate: self.fail("Counters of collected object higher than tolerated.") def test_converter(self): for i in range(0, self.sample_size): conversion.MySQLConverter() self.samples[i] = len(gc.get_objects()) self._assert_flat_line(self.samples) def test_connection(self): config = tests.get_mysql_config() # Create a connection and close using close()-method for i in range(0, self.sample_size): cnx = connection.MySQLConnection(**config) cnx.close() self.samples[i] = len(gc.get_objects()) self._assert_flat_line(self.samples) self._reset_samples() # Create a connection and rely on destructor to close for i in range(0, self.sample_size): cnx = connection.MySQLConnection(**config) self.samples[i] = len(gc.get_objects()) self._assert_flat_line(self.samples) def test_cursor(self): config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) # Create a cursor and close using close()-method for i in range(0, self.sample_size): cursor = cnx.cursor() cursor.close() self.samples[i] = len(gc.get_objects()) self._assert_flat_line(self.samples) self._reset_samples() # Create a cursor and rely on destructor to close for i in range(0, self.sample_size): cursor = cnx.cursor() self.samples[i] = len(gc.get_objects()) self._assert_flat_line(self.samples) class BugOra14184643(tests.MySQLConnectorTests): """BUG#14184643: cmd_query() disregards waiting results""" def setUp(self): config = tests.get_mysql_config() config['connection_timeout'] = 5 self.cnx = connection.MySQLConnection(**config) def test_cmd_query(self): """BUG#14184643: cmd_query()""" self.cnx.cmd_query('SELECT 1') self.assertRaises(errors.InternalError, self.cnx.cmd_query, 'SELECT 2') def test_get_rows(self): """BUG#14184643: get_row() and get_rows()""" self.cnx.cmd_query('SELECT 1') self.cnx.get_rows() self.assertRaises(errors.InternalError, self.cnx.get_rows) self.cnx.cmd_query('SELECT 1') self.cnx.get_row() self.assertEqual(None, self.cnx.get_row()[0]) self.assertRaises(errors.InternalError, self.cnx.get_row) def test_cmd_statistics(self): """BUG#14184643: other command after cmd_query()""" self.cnx.cmd_query('SELECT 1') self.assertRaises(errors.InternalError, self.cnx.cmd_statistics) self.cnx.get_rows() class BugOra14208326(tests.MySQLConnectorTests): """BUG#14208326: cmd_query() does not handle multiple statements""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() self.table = "BugOra14208326" self.cnx.cmd_query("DROP TABLE IF EXISTS %s" % self.table) self.cnx.cmd_query("CREATE TABLE %s (id INT)" % self.table) def test_cmd_query(self): """BUG#14208326: cmd_query() should not allow multiple results""" self.assertRaises(errors.InterfaceError, self.cnx.cmd_query, 'SELECT 1; SELECT 2') def test_cmd_query_iter(self): stmt = 'SELECT 1; INSERT INTO %s VALUES (1),(2); SELECT 3' results = [] for result in self.cnx.cmd_query_iter(stmt % self.table): results.append(result) if 'columns' in result: results.append(self.cnx.get_rows()) class BugOra14201459(tests.MySQLConnectorTests): """BUG#14201459: Server error 1426 should raise ProgrammingError""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() self.tbl = 'Bug14201459' self.cursor.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) def test_error1426(self): create = "CREATE TABLE %s (c1 TIME(7))" % self.tbl try: self.cursor.execute(create) except errors.ProgrammingError as exception: if tests.MYSQL_VERSION < (5, 6, 4) and exception.errno != 1064: self.fail("ProgrammingError is not Error 1064") elif tests.MYSQL_VERSION >= (5, 6, 4) and exception.errno != 1426: self.fail("ProgrammingError is not Error 1426") else: self.fail("ProgrammingError not raised") class BugOra14231160(tests.MySQLConnectorTests): """BUG#14231160: lastrowid, description and rowcount read-only""" def test_readonly_properties(self): cur = cursor.MySQLCursor() for attr in ('description', 'rowcount', 'lastrowid'): try: setattr(cur, attr, 'spam') except AttributeError: # It's readonly, that's OK pass else: self.fail('Need read-only property: {0}'.format(attr)) class BugOra14259954(tests.MySQLConnectorTests): """BUG#14259954: ON DUPLICATE KEY UPDATE VALUE FAILS REGEX""" def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() self.tbl = 'Bug14259954' self.cursor.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) create = ("CREATE TABLE %s ( " "`id` int(11) NOT NULL AUTO_INCREMENT, " "`c1` int(11) NOT NULL DEFAULT '0', " "PRIMARY KEY (`id`,`c1`))" % (self.tbl)) self.cursor.execute(create) def test_executemany(self): query = ("INSERT INTO %s (id,c1) VALUES (%%s,%%s) " "ON DUPLICATE KEY UPDATE c1=VALUES(c1)") % self.tbl try: self.cursor.executemany(query, [(1, 1), (2, 2)]) except errors.ProgrammingError as err: self.fail("Regular expression fails with executemany(): %s" % err) class BugOra14548043(tests.MySQLConnectorTests): """BUG#14548043: ERROR MESSAGE SHOULD BE IMPROVED TO DIAGNOSE THE PROBLEM """ def test_unix_socket(self): config = tests.get_mysql_config() config['unix_socket'] = os.path.join( tempfile.gettempdir(), 'a' * 100 + 'myconnpy_bug14548043.test') exp = ("2002: Can't connect to local MySQL " "server through socket '%s' " "(AF_UNIX path too long)" % config['unix_socket'][0:100]) try: cnx = connection.MySQLConnection(**config) except errors.InterfaceError as err: self.assertEqual(exp, str(err)) class BugOra14754894(tests.MySQLConnectorTests): """ """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() self.tbl = 'BugOra14754894' self.cursor.execute("DROP TABLE IF EXISTS %s" % (self.tbl)) self.cursor.execute("CREATE TABLE %s (c1 INT)" % (self.tbl)) def test_executemany(self): insert = "INSERT INTO %s (c1) VALUES (%%(c1)s)" % (self.tbl) data = [{'c1': 1}] self.cursor.executemany(insert, [{'c1': 1}]) try: self.cursor.executemany(insert, [{'c1': 1}]) except ValueError as err: self.fail(err) self.cursor.execute("SELECT c1 FROM %s" % self.tbl) self.assertEqual(data[0]['c1'], self.cursor.fetchone()[0]) class BugOra13808727(tests.MySQLConnectorTests): """BUG#13808727: ERROR UNCLEAR WHEN TCP PORT IS NOT AN INTEGER """ def test_portnumber(self): config = tests.get_mysql_config() try: config['port'] = str(config['port']) connection.MySQLConnection(**config) except: self.fail("Port number as string is not accepted.") self.assertRaises(errors.InterfaceError, connection.MySQLConnection, port="spam") @unittest.skipIf(not tests.IPV6_AVAILABLE, "IPv6 testing disabled") class BugOra15876886(tests.MySQLConnectorTests): """BUG#15876886: CONNECTOR/PYTHON CAN NOT CONNECT TO MYSQL THROUGH IPV6 """ def test_ipv6(self): config = tests.get_mysql_config() config['host'] = '::1' config['unix_socket'] = None try: cnx = connection.MySQLConnection(**config) except errors.InterfaceError as err: self.fail("Can not connect using IPv6: {0}".format(str(err))) else: cnx.close() class BugOra15915243(tests.MySQLConnectorTests): """BUG#15915243: PING COMMAND ALWAYS RECONNECTS TO THE DATABASE """ def test_ping(self): config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) cid = cnx.connection_id cnx.ping() # Do not reconnect self.assertEqual(cid, cnx.connection_id) cnx.close() # Do not reconnect self.assertRaises(errors.InterfaceError, cnx.ping) # Do reconnect cnx.ping(reconnect=True) self.assertNotEqual(cid, cnx.connection_id) cnx.close() class BugOra15916486(tests.MySQLConnectorTests): """BUG#15916486: RESULTS AFTER STORED PROCEDURE WITH ARGUMENTS ARE NOT KEPT """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("DROP PROCEDURE IF EXISTS sp1") self.cur.execute("DROP PROCEDURE IF EXISTS sp2") sp1 = ("CREATE PROCEDURE sp1(IN pIn INT, OUT pOut INT)" " BEGIN SELECT 1; SET pOut := pIn; SELECT 2; END") sp2 = ("CREATE PROCEDURE sp2 ()" " BEGIN SELECT 1; SELECT 2; END") self.cur.execute(sp1) self.cur.execute(sp2) def tearDown(self): try: self.cur.execute("DROP PROCEDURE IF EXISTS sp1") self.cur.execute("DROP PROCEDURE IF EXISTS sp2") except: pass # Clean up fail is acceptable for this test self.cnx.close() def test_callproc_with_args(self): exp = (5, 5) self.assertEqual(exp, self.cur.callproc('sp1', (5, 0))) exp = [[(1,)], [(2,)]] results = [] for result in self.cur.stored_results(): results.append(result.fetchall()) self.assertEqual(exp, results) def test_callproc_without_args(self): exp = () self.assertEqual(exp, self.cur.callproc('sp2')) exp = [[(1,)], [(2,)]] results = [] for result in self.cur.stored_results(): results.append(result.fetchall()) self.assertEqual(exp, results) class BugOra15836979(tests.MySQLConnectorTests): """BUG#15836979: UNCLEAR ERROR MESSAGE CONNECTING USING UNALLOWED IP ADDRESS """ def setUp(self): if os.name == 'nt': return config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) cnx.cmd_query("DROP USER 'root'@'127.0.0.1'") try: cnx.cmd_query("DROP USER 'root'@'::1'") except errors.DatabaseError: # Some MySQL servers have no IPv6 entry pass cnx.close() def tearDown(self): if os.name == 'nt': return config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) cnx.cmd_query( "GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' " "WITH GRANT OPTION") cnx.cmd_query( "GRANT ALL PRIVILEGES ON *.* TO 'root'@'::1' " "WITH GRANT OPTION") cnx.close() def test_handshake(self): if os.name == 'nt': tests.MESSAGES['WARNINGS'].append( "Can't test error handling when doing handshake " "on Windows (lacking named pipe support)") return config = tests.get_mysql_config() config['host'] = '127.0.0.1' config['unix_socket'] = None self.assertRaises(errors.DatabaseError, connection.MySQLConnection, **config) class BugOra16217743(tests.MySQLConnectorTests): """BUG#16217743: CALLPROC FUNCTION WITH STRING PARAMETERS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cnx.cmd_query("DROP TABLE IF EXISTS bug16217743") self.cnx.cmd_query("DROP PROCEDURE IF EXISTS sp_bug16217743") self.cnx.cmd_query("CREATE TABLE bug16217743 (c1 VARCHAR(20), c2 INT)") self.cnx.cmd_query( "CREATE PROCEDURE sp_bug16217743 (p1 VARCHAR(20), p2 INT) " "BEGIN INSERT INTO bug16217743 (c1, c2) " "VALUES (p1, p2); END;") def tearDown(self): self.cnx.cmd_query("DROP TABLE IF EXISTS bug16217743") self.cnx.cmd_query("DROP PROCEDURE IF EXISTS sp_bug16217743") def test_procedure(self): exp = ('ham', 42) cur = self.cnx.cursor() cur.callproc('sp_bug16217743', ('ham', 42)) cur.execute("SELECT c1, c2 FROM bug16217743") self.assertEqual(exp, cur.fetchone()) class BugOra16217667(tests.MySQLConnectorTests): """BUG#16217667: PYTHON CONNECTOR 3.2 SSL CONNECTION FAILS """ def setUp(self): config = tests.get_mysql_config() self.admin_cnx = connection.MySQLConnection(**config) self.admin_cnx.cmd_query( "GRANT ALL ON {db}.* TO 'ssluser'@'{host}' REQUIRE X509".format( db=config['database'], host=tests.get_mysql_config()['host'])) def tearDown(self): self.admin_cnx.cmd_query("DROP USER 'ssluser'@'{0}'".format( tests.get_mysql_config()['host'])) def test_sslauth(self): if not tests.SSL_AVAILABLE: tests.MESSAGES['WARNINGS'].append( "BugOra16217667 test failed. Python lacks SSL support.") return config = tests.get_mysql_config() config['user'] = 'ssluser' config['password'] = '' config['unix_socket'] = None config['ssl_verify_cert'] = True config.update({ 'ssl_ca': os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem')), 'ssl_cert': os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_client_cert.pem')), 'ssl_key': os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_client_key.pem')), }) try: cnx = connection.MySQLConnection(**config) except errors.ProgrammingError: self.fail("Failed authentication with SSL") cnx.cmd_query("SHOW STATUS LIKE 'Ssl_cipher'") self.assertTrue(cnx.get_rows()[0][0] != '') class BugOra16316049(tests.MySQLConnectorTests): """ SSL ERROR: [SSL: TLSV1_ALERT_UNKNOWN_CA] AFTER FIX 6217667""" def setUp(self): config = tests.get_mysql_config() self.admin_cnx = connection.MySQLConnection(**config) self.admin_cnx.cmd_query( "GRANT ALL ON {db}.* TO 'ssluser'@'{host}' REQUIRE SSL".format( db=config['database'], host=tests.get_mysql_config()['host'])) def tearDown(self): self.admin_cnx.cmd_query("DROP USER 'ssluser'@'{host}'".format( host=tests.get_mysql_config()['host'])) def test_ssl(self): if not tests.SSL_AVAILABLE: tests.MESSAGES['WARNINGS'].append( "BugOra16217667 test failed. Python lacks SSL support.") return ssl_ca = os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_CA_cert.pem')) ssl_cert = os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_client_cert.pem')) ssl_key = os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_client_key.pem')) config = tests.get_mysql_config() config['user'] = 'ssluser' config['password'] = '' config['unix_socket'] = None config.update({ 'ssl_ca': None, 'ssl_cert': None, 'ssl_key': None, }) # User requires SSL, but no values for ssl argument given self.assertRaises(errors.ProgrammingError, connection.MySQLConnection, **config) # Use wrong value for ssl_ca config['ssl_ca'] = os.path.abspath( os.path.join(tests.SSL_DIR, 'tests_casdfasdfdsaa_cert.pem')) config['ssl_cert'] = ssl_cert config['ssl_key'] = ssl_key config['ssl_verify_cert'] = True self.assertRaises(errors.InterfaceError, connection.MySQLConnection, **config) # Use correct value config['ssl_ca'] = ssl_ca try: cnx = connection.MySQLConnection(**config) except errors.ProgrammingError: self.fail("Failed authentication with SSL") cnx.cmd_query("SHOW STATUS LIKE 'Ssl_cipher'") self.assertTrue(cnx.get_rows()[0][0] != '') class BugOra16662920(tests.MySQLConnectorTests): """BUG#16662920: FETCHALL() IGNORES NEXT_ROW FOR BUFFERED CURSORS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS t1") cur.execute( "CREATE TABLE t1 (id INT AUTO_INCREMENT, c1 VARCHAR(20), " "PRIMARY KEY (id)) ENGINE=InnoDB" ) data = [('a',), ('c',), ('e',), ('d',), ('g',), ('f',)] cur.executemany("INSERT INTO t1 (c1) VALUES (%s)", data) cur.close() self.cnx.commit() def tearDown(self): try: cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS t1") self.cnx.close() except errors.Error: pass def test_buffered(self): cur = self.cnx.cursor(buffered=True) cur.execute("SELECT * FROM t1 ORDER BY c1") self.assertEqual((1, 'a'), cur.fetchone()) exp = [(2, 'c'), (4, 'd'), (3, 'e')] self.assertEqual(exp, cur.fetchmany(3)) exp = [(6, 'f'), (5, 'g')] self.assertEqual(exp, cur.fetchall()) cur.close() def test_buffered_raw(self): cur = self.cnx.cursor(buffered=True, raw=True) cur.execute("SELECT * FROM t1 ORDER BY c1") if sys.version_info[0] == 2: exp_one = ('1', 'a') exp_many = [('2', 'c'), ('4', 'd'), ('3', 'e')] exp_all = [('6', 'f'), ('5', 'g')] else: exp_one = (b'1', b'a') exp_many = [(b'2', b'c'), (b'4', b'd'), (b'3', b'e')] exp_all = [(b'6', b'f'), (b'5', b'g')] self.assertEqual(exp_one, cur.fetchone()) self.assertEqual(exp_many, cur.fetchmany(3)) self.assertEqual(exp_all, cur.fetchall()) cur.close() class BugOra17041412(tests.MySQLConnectorTests): """BUG#17041412: FETCHALL() DOES NOT RETURN SELF._NEXTROW IF AVAILABLE """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) cur = self.cnx.cursor() self.table_name = 'BugOra17041240' self.data = [(1,), (2,), (3,)] if sys.version_info[0] == 2: self.data_raw = [('1',), ('2',), ('3',)] else: self.data_raw = [(b'1',), (b'2',), (b'3',)] cur.execute("DROP TABLE IF EXISTS %s" % self.table_name) cur.execute("CREATE TABLE %s (c1 INT)" % self.table_name) cur.executemany( "INSERT INTO %s (c1) VALUES (%%s)" % self.table_name, self.data) self.cnx.commit() def tearDown(self): cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS %s" % self.table_name) def test_one_all(self): cur = self.cnx.cursor() cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data[0], cur.fetchone()) self.assertEqual(1, cur.rowcount) self.assertEqual(self.data[1:], cur.fetchall()) self.assertEqual(3, cur.rowcount) def test_many_all(self): cur = self.cnx.cursor() cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data[0:2], cur.fetchmany(2)) self.assertEqual(2, cur.rowcount) self.assertEqual(self.data[2:], cur.fetchall()) self.assertEqual(3, cur.rowcount) def test_many(self): cur = self.cnx.cursor() cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data, cur.fetchall()) self.assertEqual(3, cur.rowcount) cur.execute("SELECT * FROM %s WHERE c1 > %%s" % self.table_name, (self.data[-1][0] + 100,)) self.assertEqual([], cur.fetchall()) def test_raw_one_all(self): cur = self.cnx.cursor(raw=True) cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data_raw[0], cur.fetchone()) self.assertEqual(1, cur.rowcount) self.assertEqual(self.data_raw[1:], cur.fetchall()) self.assertEqual(3, cur.rowcount) def test_raw_many_all(self): cur = self.cnx.cursor(raw=True) cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data_raw[0:2], cur.fetchmany(2)) self.assertEqual(2, cur.rowcount) self.assertEqual(self.data_raw[2:], cur.fetchall()) self.assertEqual(3, cur.rowcount) def test_raw_many(self): cur = self.cnx.cursor(raw=True) cur.execute("SELECT * FROM %s ORDER BY c1" % self.table_name) self.assertEqual(self.data_raw, cur.fetchall()) self.assertEqual(3, cur.rowcount) cur.execute("SELECT * FROM %s WHERE c1 > 1000" % self.table_name) self.assertEqual([], cur.fetchall()) class BugOra16819486(tests.MySQLConnectorTests): """BUG#16819486: ERROR 1210 TO BE HANDLED """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.pcur = self.cnx.cursor(cursor_class=cursor.MySQLCursorPrepared) self.cur.execute("DROP TABLE IF EXISTS BugOra16819486") self.cur.execute("CREATE TABLE BugOra16819486 (c1 INT, c2 INT)") self.cur.executemany("INSERT INTO BugOra16819486 VALUES (%s, %s)", [(1, 10), (2, 20), (3, 30)]) self.cnx.commit() def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS BugOra16819486") self.cur.close() self.pcur.close() def test_error1210(self): prep_stmt = "SELECT * FROM BugOra16819486 WHERE c1 = %s AND c2 = %s" self.assertRaises(mysql.connector.ProgrammingError, self.pcur.execute, prep_stmt, (1,)) prep_stmt = "SELECT * FROM BugOra16819486 WHERE c1 = %s AND c2 = %s" exp = [(1, 10)] self.pcur.execute(prep_stmt, (1, 10)) self.assertEqual(exp, self.pcur.fetchall()) class BugOra16656621(tests.MySQLConnectorTests): """BUG#16656621: IMPOSSIBLE TO ROLLBACK WITH UNREAD RESULTS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("DROP TABLE IF EXISTS BugOra16656621") self.cur.execute( "CREATE TABLE BugOra16656621 " "(id INT AUTO_INCREMENT, c1 VARCHAR(20), " "PRIMARY KEY (id)) ENGINE=InnoDB") def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS BugOra16656621") def test_rollback(self): self.cur.execute( "INSERT INTO BugOra16656621 (c1) VALUES ('a'),('b'),('c')") self.cnx.commit() self.cur.execute("SELECT * FROM BugOra16656621") try: self.cnx.rollback() except mysql.connector.InternalError: self.fail("Rollback not possible with unread results") class BugOra16660356(tests.MySQLConnectorTests): """BUG#16660356: USING EXECUTEMANY WITH EMPTY DATA SHOULD DO NOTHING """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("DROP TABLE IF EXISTS bug16660356") self.cur.execute( "CREATE TABLE bug16660356 (id INT AUTO_INCREMENT, c1 VARCHAR(20), " "PRIMARY KEY (id)) ENGINE=InnoDB" ) def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS bug16660356") def test_executemany(self): try: self.cur.executemany( "INSERT INTO bug16660356 (c1) VALUES (%s)", [] ) except mysql.connector.ProgrammingError: self.fail("executemany raise ProgrammingError with empty data") class BugOra17041240(tests.MySQLConnectorTests): """BUG#17041240: UNCLEAR ERROR CLOSING CURSOR WITH UNREAD RESULTS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) cur = self.cnx.cursor() self.table_name = 'BugOra17041240' self.data = [(1,), (2,), (3,)] cur.execute("DROP TABLE IF EXISTS {table}".format( table=self.table_name)) cur.execute("CREATE TABLE {table} (c1 INT)".format( table=self.table_name)) cur.executemany( "INSERT INTO {table} (c1) VALUES (%s)".format( table=self.table_name), self.data) self.cnx.commit() def tearDown(self): cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS {table}".format( table=self.table_name)) self.cnx.close() def test_cursor_close(self): cur = self.cnx.cursor() cur.execute("SELECT * FROM {table} ORDER BY c1".format( table=self.table_name)) self.assertEqual(self.data[0], cur.fetchone()) self.assertEqual(self.data[1], cur.fetchone()) self.assertRaises(mysql.connector.InternalError, cur.close) self.assertEqual(self.data[2], cur.fetchone()) def test_cursor_new(self): cur = self.cnx.cursor() cur.execute("SELECT * FROM {table} ORDER BY c1".format( table=self.table_name)) self.assertEqual(self.data[0], cur.fetchone()) self.assertEqual(self.data[1], cur.fetchone()) self.assertRaises(mysql.connector.InternalError, self.cnx.cursor) self.assertEqual(self.data[2], cur.fetchone()) class BugOra17065366(tests.MySQLConnectorTests): """BUG#17065366: EXECUTEMANY FAILS USING MYSQL FUNCTION FOR INSERTS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) cur = self.cnx.cursor() self.table_name = 'BugOra17065366' cur.execute( "DROP TABLE IF EXISTS {table}".format(table=self.table_name)) cur.execute( "CREATE TABLE {table} ( " "id INT UNSIGNED NOT NULL AUTO_INCREMENT KEY, " "c1 INT, c2 DATETIME) ENGINE=INNODB".format(table=self.table_name)) def tearDown(self): cur = self.cnx.cursor() cur.execute("DROP TABLE IF EXISTS {table}".format( table=self.table_name)) def test_executemany(self): cur = self.cnx.cursor() adate = datetime(2012, 9, 30) stmt = ( "INSERT INTO {table} (id, c1, c2) " "VALUES (%s, %s, DATE('{date} 13:07:00'))" "/* Using DATE() */ ON DUPLICATE KEY UPDATE c1 = id" ).format(table=self.table_name, date=adate.strftime('%Y-%m-%d')) exp = [ (1, 0, datetime(2012, 9, 30, 0, 0)), (2, 0, datetime(2012, 9, 30, 0, 0)) ] cur.executemany(stmt, [(None, 0), (None, 0)]) self.cnx.commit() cur.execute("SELECT * FROM {table}".format(table=self.table_name)) rows = cur.fetchall() self.assertEqual(exp, rows) exp = [ (1, 1, datetime(2012, 9, 30, 0, 0)), (2, 2, datetime(2012, 9, 30, 0, 0)) ] cur.executemany(stmt, [(1, 1), (2, 2)]) self.cnx.commit() cur.execute("SELECT * FROM {table}".format(table=self.table_name)) rows = cur.fetchall() self.assertEqual(exp, rows) class BugOra16933795(tests.MySQLConnectorTests): """BUG#16933795: ERROR.MSG ATTRIBUTE DOES NOT CONTAIN CORRECT VALUE """ def test_error(self): exp = "Some error message" error = mysql.connector.Error(msg=exp, errno=-1024) self.assertEqual(exp, error.msg) exp = "Unknown MySQL error" error = mysql.connector.Error(errno=2000) self.assertEqual(exp, error.msg) self.assertEqual("2000: " + exp, str(error)) class BugOra17022399(tests.MySQLConnectorTests): """BUG#17022399: EXECUTING AFTER CONNECTION CLOSED GIVES UNCLEAR ERROR """ def setUp(self): self.config = tests.get_mysql_config() def test_execute(self): cnx = connection.MySQLConnection(**self.config) cur = cnx.cursor() cnx.close() try: cur.execute("SELECT 1") except mysql.connector.OperationalError as err: self.assertEqual(2055, err.errno) self.assertTrue('9 ' in str(err)) def test_execute_compressed(self): config = self.config.copy() config['client_flags'] = [constants.ClientFlag.COMPRESS] cnx = connection.MySQLConnection(**config) cur = cnx.cursor() cnx.close() try: cur.execute("SELECT 1") except mysql.connector.OperationalError as err: self.assertEqual(2055, err.errno) self.assertTrue('9 ' in str(err)) class BugOra16369511(tests.MySQLConnectorTests): """BUG#16369511: LOAD DATA LOCAL INFILE IS MISSING """ def setUp(self): config = tests.get_mysql_config() config['client_flags'] = [constants.ClientFlag.LOCAL_FILES] self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.data_file = os.path.join('tests', 'data', 'local_data.csv') self.cur.execute("DROP TABLE IF EXISTS local_data") self.cur.execute( "CREATE TABLE local_data (id int, c1 VARCHAR(6), c2 VARCHAR(6))") def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS local_data") def test_load_csv(self): sql = "LOAD DATA LOCAL INFILE %s INTO TABLE local_data" self.cur.execute(sql, (self.data_file,)) self.cur.execute("SELECT * FROM local_data") exp = [ (1, 'c1_1', 'c2_1'), (2, 'c1_2', 'c2_2'), (3, 'c1_3', 'c2_3'), (4, 'c1_4', 'c2_4'), (5, 'c1_5', 'c2_5'), (6, 'c1_6', 'c2_6')] self.assertEqual(exp, self.cur.fetchall()) def test_filenotfound(self): sql = "LOAD DATA LOCAL INFILE %s INTO TABLE local_data" self.assertRaises(mysql.connector.InterfaceError, self.cur.execute, sql, (self.data_file + '_spam',)) class BugOra17002411(tests.MySQLConnectorTests): """BUG#17002411: LOAD DATA LOCAL INFILE FAILS WITH BIGGER FILES """ def setUp(self): config = tests.get_mysql_config() config['client_flags'] = [constants.ClientFlag.LOCAL_FILES] self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.data_file = os.path.join('tests', 'data', 'local_data_big.csv') self.cur.execute("DROP TABLE IF EXISTS local_data") self.cur.execute( "CREATE TABLE local_data (" "id INT AUTO_INCREMENT KEY, " "c1 VARCHAR(255), c2 VARCHAR(255))" ) self.exp_rows = 33000 fp = open(self.data_file, 'w') i = 0 while i < self.exp_rows: fp.write("{0}\t{1}\n".format('a' * 255, 'b' * 255)) i += 1 fp.close() def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS local_data") os.unlink(self.data_file) def test_load_csv(self): sql = "LOAD DATA LOCAL INFILE %s INTO TABLE local_data (c1, c2)" self.cur.execute(sql, (self.data_file,)) self.cur.execute("SELECT COUNT(*) FROM local_data") self.assertEqual(self.exp_rows, self.cur.fetchone()[0]) class BugOra17422299(tests.MySQLConnectorTests): """BUG#17422299: cmd_shutdown fails with malformed connection packet """ def setUp(self): self.config = tests.get_mysql_config() self.mysql_server = tests.MYSQL_SERVERS[0] def tearDown(self): # Start the MySQL server again if not self.mysql_server.check_running(): self.mysql_server.start() if not self.mysql_server.wait_up(): self.fail("Failed restarting MySQL server after test") def test_shutdown(self): cnx = connection.MySQLConnection(**self.config) try: cnx.cmd_shutdown() except mysql.connector.DatabaseError as err: self.fail("COM_SHUTDOWN failed: {0}".format(err)) if not self.mysql_server.wait_down(): self.fail("MySQL not shut down after COM_SHUTDOWN") def test_shutdown__with_type(self): cnx = connection.MySQLConnection(**self.config) try: cnx.cmd_shutdown(constants.ShutdownType.SHUTDOWN_WAIT_ALL_BUFFERS) except mysql.connector.DatabaseError as err: self.fail("COM_SHUTDOWN failed: {0}".format(err)) if not self.mysql_server.wait_down(): self.fail("MySQL not shut down after COM_SHUTDOWN") class BugOra17215197(tests.MySQLConnectorTests): """BUG#17215197: MYSQLCONNECTION.CURSOR(PREPARED=TRUE) NOT POSSIBLE """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("DROP TABLE IF EXISTS BugOra17215197") self.cur.execute("CREATE TABLE BugOra17215197 (c1 INT, c2 INT)") self.cur.executemany("INSERT INTO BugOra17215197 VALUES (%s, %s)", [(1, 10), (2, 20), (3, 30)]) self.cnx.commit() def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS BugOra17215197") self.cur.close() def test_prepared_argument(self): self.pcur = self.cnx.cursor(prepared=True) prep_stmt = "SELECT * FROM BugOra17215197 WHERE c1 = %s AND c2 = %s" exp = [(1, 10)] self.pcur.execute(prep_stmt, (1, 10)) self.assertEqual(exp, self.pcur.fetchall()) class BugOra17414258(tests.MySQLConnectorTests): """BUG#17414258: IT IS ALLOWED TO CHANGE SIZE OF ACTIVE POOL """ def setUp(self): self.config = tests.get_mysql_config() self.config['pool_name'] = 'test' self.config['pool_size'] = 3 def tearDown(self): # Remove pools created by test del mysql.connector._CONNECTION_POOLS[self.config['pool_name']] def test_poolsize(self): cnx = mysql.connector.connect(**self.config) cnx.close() newconfig = self.config.copy() newconfig['pool_size'] = self.config['pool_size'] + 1 self.assertRaises(mysql.connector.PoolError, mysql.connector.connect, **newconfig) class Bug17578937(tests.MySQLConnectorTests): """CONNECTION POOL DOES NOT HANDLE A NOT AVAILABLE MYSQL SERVER""" def setUp(self): self.mysql_server = tests.MYSQL_SERVERS[0] def tearDown(self): # Start the MySQL server again if not self.mysql_server.check_running(): self.mysql_server.start() if not self.mysql_server.wait_up(): self.fail("Failed restarting MySQL server after test") def test_get_connection(self): """Test reconnect once MySQL server is back To make the test case simpler, we create a pool which only has one connection in the queue. This was we can similuate getting a connection from a pool for which the MySQL server is not running. """ cnxpool = pooling.MySQLConnectionPool( pool_name='test', pool_size=1, **tests.get_mysql_config()) pcnx = cnxpool.get_connection() self.assertTrue(isinstance(pcnx, pooling.PooledMySQLConnection)) pcnx.close() self.mysql_server.stop() if not self.mysql_server.wait_down(): self.fail("MySQL not shut down; can not continue test") self.assertRaises(errors.InterfaceError, cnxpool.get_connection) self.mysql_server.start() if not self.mysql_server.wait_up(): self.fail("MySQL started; can not continue test") pcnx = cnxpool.get_connection() pcnx.close() class BugOra17079344(tests.MySQLConnectorTests): """BUG#17079344: ERROR WITH GBK STRING WITH CHARACTERS ENCODED AS BACKSLASH """ def tearDown(self): cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() for charset in ('gbk', 'sjis', 'big5'): tablename = charset + 'test' cur.execute("DROP TABLE IF EXISTS {0}".format(tablename)) cur.close() cnx.close() def _test_charset(self, charset, data): config = tests.get_mysql_config() config['charset'] = charset config['use_unicode'] = True cnx = connection.MySQLConnection(**config) tablename = charset + 'test' cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS {0}".format(tablename)) table = ( "CREATE TABLE {table} (" "id INT AUTO_INCREMENT KEY, " "c1 VARCHAR(40)" ") CHARACTER SET '{charset}'" ).format(table=tablename, charset=charset) cur.execute(table) insert = "INSERT INTO {0} (c1) VALUES (%s)".format(tablename) for value in data: cur.execute(insert, (value,)) cur.execute("SELECT id, c1 FROM {0} ORDER BY id".format(tablename)) for row in cur: self.assertEqual(data[row[0]-1], row[1]) cur.close() cnx.close() def test_gbk(self): self._test_charset('gbk', BugOra17079344Extra.data_gbk) def test_sjis(self): self._test_charset('sjis', BugOra17079344Extra.data_sjis) def test_big5(self): self._test_charset('big5', BugOra17079344Extra.data_big5) class BugOra17780576(tests.MySQLConnectorTests): """BUG#17780576: CHARACTER SET 'UTF8MB4' UNSUPPORTED """ def tearDown(self): cnx = connection.MySQLConnection(**tests.get_mysql_config()) cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS utf8mb4test") cur.close() cnx.close() def test_utf8mb4(self): if tests.MYSQL_VERSION < (5, 5, 0): # Test only valid for MySQL 5.5.0 and later. return config = tests.get_mysql_config() cnx = connection.MySQLConnection(**config) tablename = 'utf8mb4test' cnx.set_charset_collation('utf8mb4') cur = cnx.cursor() cur.execute("DROP TABLE IF EXISTS {0}".format(tablename)) table = ( "CREATE TABLE {table} (" "id INT AUTO_INCREMENT KEY, " "c1 VARCHAR(40) CHARACTER SET 'utf8mb4'" ") CHARACTER SET 'utf8mb4'" ).format(table=tablename) cur.execute(table) insert = "INSERT INTO {0} (c1) VALUES (%s)".format(tablename) data = BugOra17780576Extra.data_utf8mb4 for value in data: cur.execute(insert, (value,)) cur.execute("SELECT id, c1 FROM {0} ORDER BY id".format(tablename)) for row in cur: self.assertEqual(data[row[0]-1], row[1]) cur.close() cnx.close() class BugOra17573172(tests.MySQLConnectorTests): """BUG#17573172: MISSING SUPPORT FOR READ-ONLY TRANSACTIONS """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cur = self.cnx.cursor() self.cur.execute("DROP TABLE IF EXISTS BugOra17573172") self.cur.execute("CREATE TABLE BugOra17573172 (c1 INT, c2 INT)") self.cur.executemany("INSERT INTO BugOra17573172 VALUES (%s, %s)", [(1, 10), (2, 20), (3, 30)]) self.cnx.commit() def test_read_only(self): if self.cnx.get_server_version() < (5, 6, 5): self.assertRaises(ValueError, self.cnx.start_transaction, readonly=True) else: self.cnx.start_transaction(readonly=True) self.assertTrue(self.cnx.in_transaction) self.assertRaises(errors.ProgrammingError, self.cnx.start_transaction) query = "INSERT INTO BugOra17573172 VALUES(4, 40)" self.assertRaises(errors.ProgrammingError, self.cur.execute, query) self.cnx.rollback() def tearDown(self): self.cur.execute("DROP TABLE IF EXISTS BugOra17573172") self.cur.close() class BugOra17826833(tests.MySQLConnectorTests): """BUG#17826833: EXECUTEMANY() FOR INSERTS W/O VALUES """ def setUp(self): config = tests.get_mysql_config() self.cnx = connection.MySQLConnection(**config) self.cursor = self.cnx.cursor() self.emp_tbl = 'Bug17826833_emp' self.cursor.execute("DROP TABLE IF EXISTS %s" % (self.emp_tbl)) self.city_tbl = 'Bug17826833_city' self.cursor.execute("DROP TABLE IF EXISTS %s" % (self.city_tbl)) create = ("CREATE TABLE %s ( " "`id` int(11) NOT NULL, " "`name` varchar(20) NOT NULL , " "`phone` varchar(20), " "PRIMARY KEY (`id`))" % (self.emp_tbl)) self.cursor.execute(create) create = ("CREATE TABLE %s ( " "`id` int(11) NOT NULL, " "`name` varchar(20) NOT NULL, " "PRIMARY KEY (`id`))" % (self.city_tbl)) self.cursor.execute(create) def test_executemany(self): stmt = "INSERT INTO {0} (id,name) VALUES (%s,%s)".format( self.city_tbl) self.cursor.executemany(stmt, [(1, 'ABC'), (2, 'CDE'), (3, 'XYZ')]) query = ("INSERT INTO %s (id, name, phone)" "SELECT id,name,%%s FROM %s WHERE name=%%s") % (self.emp_tbl, self.city_tbl) try: self.cursor.executemany(query, [('4567', 'CDE'), ('1234', 'XYZ')]) stmt = "SELECT * FROM {0}".format(self.emp_tbl) self.cursor.execute(stmt) self.assertEqual([(2, 'CDE', '4567'), (3, 'XYZ', '1234')], self.cursor.fetchall(), "INSERT ... SELECT failed") except errors.ProgrammingError as err: self.fail("Regular expression fails with executemany(): %s" % err) class BugOra18040042(tests.MySQLConnectorTests): """BUG#18040042: Reset session closing pooled Connection""" def test_clear_session(self): cnxpool = pooling.MySQLConnectionPool( pool_name='test', pool_size=1, **tests.get_mysql_config()) pcnx = cnxpool.get_connection() exp_session_id = pcnx.connection_id pcnx.cmd_query("SET @ham = 2") pcnx.close() pcnx = cnxpool.get_connection() pcnx.cmd_query("SELECT @ham") self.assertEqual(exp_session_id, pcnx.connection_id) self.assertNotEqual(('2',), pcnx.get_rows()[0][0]) def test_do_not_clear_session(self): cnxpool = pooling.MySQLConnectionPool( pool_name='test', pool_size=1, pool_reset_session=False, **tests.get_mysql_config()) pcnx = cnxpool.get_connection() exp_session_id = pcnx.connection_id pcnx.cmd_query("SET @ham = 2") pcnx.close() pcnx = cnxpool.get_connection() pcnx.cmd_query("SELECT @ham") self.assertEqual(exp_session_id, pcnx.connection_id) if sys.version_info[0] == 2: self.assertEqual(('2',), pcnx.get_rows()[0][0]) else: self.assertEqual((b'2',), pcnx.get_rows()[0][0]) mysql-connector-python-1.1.6/tests/test_locales.py0000644001577100000120000001140612276514013021641 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests for mysql.connector.locales """ import sys from datetime import datetime import tests from mysql.connector import errorcode, locales def _get_client_errors(): errors = {} for name in dir(errorcode): if name.startswith('CR_'): errors[name] = getattr(errorcode, name) return errors class LocalesModulesTests(tests.MySQLConnectorTests): def test_defaults(self): # There should always be 'eng' try: from mysql.connector.locales import eng # pylint: disable=W0612 except ImportError: self.fail("locales.eng could not be imported") # There should always be 'eng.client_error' some_error = None try: from mysql.connector.locales.eng import client_error some_error = client_error.CR_UNKNOWN_ERROR except ImportError: self.fail("locales.eng.client_error could not be imported") some_error = some_error + '' # fool pylint def test_get_client_error(self): try: locales.get_client_error(2000, language='spam') except ImportError as err: self.assertEqual("No localization support for language 'spam'", str(err)) else: self.fail("ImportError not raised") exp = "Unknown MySQL error" self.assertEqual(exp, locales.get_client_error(2000)) self.assertEqual(exp, locales.get_client_error('CR_UNKNOWN_ERROR')) try: locales.get_client_error(tuple()) except ValueError as err: self.assertEqual( "error argument needs to be either an integer or string", str(err)) else: self.fail("ValueError not raised") class LocalesEngClientErrorTests(tests.MySQLConnectorTests): """Testing locales.eng.client_error""" def test__GENERATED_ON(self): try: from mysql.connector.locales.eng import client_error except ImportError: self.fail("locales.eng.client_error could not be imported") self.assertTrue(isinstance(client_error._GENERATED_ON, str)) try: generatedon = datetime.strptime(client_error._GENERATED_ON, '%Y-%m-%d').date() except ValueError as err: self.fail(err) delta = datetime.now().date() - generatedon self.assertTrue( delta.days < 120, # pylint disable=E1103 "eng/client_error.py is more than 120 days old ({0})".format( delta.days)) # pylint disable=E1103 def test__MYSQL_VERSION(self): try: from mysql.connector.locales.eng import client_error except ImportError: self.fail("locales.eng.client_error could not be imported") minimum = (5, 6, 6) self.assertTrue(isinstance(client_error._MYSQL_VERSION, tuple)) self.assertTrue(len(client_error._MYSQL_VERSION) == 3) self.assertTrue(client_error._MYSQL_VERSION >= minimum) def test_messages(self): try: from mysql.connector.locales.eng import client_error except ImportError: self.fail("locales.eng.client_error could not be imported") errors = _get_client_errors() count = 0 for name in dir(client_error): if name.startswith('CR_'): count += 1 self.assertEqual(len(errors), count) if sys.version_info[0] == 2: strtype = unicode # pylint: disable=E0602 else: strtype = str for name in errors.keys(): self.assertTrue(isinstance(getattr(client_error, name), strtype)) mysql-connector-python-1.1.6/tests/mysqld.py0000644001577100000120000004317212276514013020476 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Module for managing and running a MySQL server""" import sys import os import signal import re from shutil import rmtree import subprocess import logging import time import ctypes try: from ctypes import wintypes except (ImportError, ValueError): # We are not on Windows pass import tests LOGGER = logging.getLogger(tests.LOGGER_NAME) DEVNULL = open(os.devnull, 'w') # MySQL executables used if os.name == 'nt': EXEC_MYSQLD = 'mysqld.exe' EXEC_MYSQL = 'mysql.exe' else: EXEC_MYSQLD = 'mysqld' EXEC_MYSQL = 'mysql' def _convert_forward_slash(path): """Convert forward slashes with backslashes This function replaces forward slashes with backslashes. This is necessary using Microsoft Windows for location of files in the option files. Returns a string """ if os.name == 'nt': nmpath = os.path.normpath(path) return nmpath.replace('\\', '\\\\') return path def process_running(pid): """Check whether a process is running This function takes the process ID or pid and checks whether it is running. It works for Windows and UNIX-like systems. Return True or False """ if os.name == 'nt': # We are on Windows output = subprocess.check_output("tasklist") lines = [line.split(None, 2) for line in output.splitlines() if line] for name, apid, _ in lines: if name == EXEC_MYSQLD and pid == int(apid): return True return False # We are on a UNIX-like system try: os.kill(pid, 0) except OSError: return False return True def process_terminate(pid): """Terminates a process This function terminates a running process, sending a SIGKILL on Posix systems and using ctypes.windll on Windows. """ if os.name == 'nt': winkernel = ctypes.windll.kernel32 process = winkernel.OpenProcess(1, 0, pid) winkernel.TerminateProcess(process, -1) winkernel.WaitForSingleObject(process) winkernel.CloseHandle(process) else: os.kill(pid, signal.SIGTERM) def get_pid(pid_file): """Returns the PID read from the PID file Returns None or int. """ try: return int(open(pid_file, 'r').readline().strip()) except IOError as err: LOGGER.debug("Failed reading pid file: {0}".format(str(err))) return None class MySQLServerError(Exception): """Exception for raising errors when managing a MySQL server""" pass class MySQLBootstrapError(MySQLServerError): """Exception for raising errors around bootstrapping a MySQL server""" pass class MySQLServerBase(object): """Base for classes managing a MySQL server""" def __init__(self, basedir, option_file=None): self._basedir = basedir self._bindir = None self._sbindir = None self._sharedir = None self._scriptdir = None self._process = None self._lc_messages_dir = None self._init_mysql_install() self._version = self._get_version() if option_file and os.access(option_file, 0): MySQLBootstrapError("Option file not accessible: {name}".format( name=option_file)) self._option_file = option_file def _init_mysql_install(self): """Checking MySQL installation Check the MySQL installation and set the directories where to find binaries and SQL bootstrap scripts. Raises MySQLBootstrapError when something fails. """ # Locate mysqld, mysql and english/errmsg.sys for root, dirs, files in os.walk(self._basedir): for afile in files: if (afile == EXEC_MYSQLD and os.access(os.path.join(root, afile), 0)): self._sbindir = root elif (afile == EXEC_MYSQL and os.access(os.path.join(root, afile), 0)): self._bindir = root elif (afile == 'errmsg.sys' and 'english' in root): self._lc_messages_dir = root elif (afile == 'mysql_system_tables.sql'): self._scriptdir = root if not self._bindir or not self._sbindir: raise MySQLBootstrapError( "MySQL binaries not found under {0}".format(self._basedir)) LOGGER.debug("Location of {bin}: {loc}".format(bin=EXEC_MYSQL, loc=self._bindir)) LOGGER.debug("Location of {bin}: {loc}".format(bin=EXEC_MYSQLD, loc=self._sbindir)) LOGGER.debug("Error messages: {loc}".format(loc=self._lc_messages_dir)) LOGGER.debug("SQL Script folder: {loc}".format(loc=self._scriptdir)) def _get_cmd(self): """Returns command to start MySQL server Returns list. """ cmd = [ os.path.join(self._sbindir, EXEC_MYSQLD), "--defaults-file={0}".format(self._option_file), ] if os.name == 'nt': cmd.append('--standalone') return cmd def _get_version(self): """Get the MySQL server version This method executes mysqld with the --version argument. It parses the output looking for the version number and returns it as a tuple with integer values: (major,minor,patch) Returns a tuple. """ cmd = [ os.path.join(self._sbindir, EXEC_MYSQLD), '--version' ] prc = subprocess.Popen(cmd, stdout=subprocess.PIPE) verstr = str(prc.communicate()[0]) matches = re.match(r'.*Ver (\d)\.(\d).(\d{1,2}).*', verstr) if matches: return tuple([int(v) for v in matches.groups()]) else: raise MySQLServerError( 'Failed reading version from mysqld --version') @property def version(self): """Returns the MySQL server version Returns a tuple. """ return self._version def _start_server(self): """Start the MySQL server""" try: cmd = self._get_cmd() self._process = subprocess.Popen(cmd, stdout=DEVNULL, stderr=DEVNULL) except (OSError, ValueError) as err: raise MySQLServerError(err) def _stop_server(self): """Stop the MySQL server""" if not self._process: return False try: process_terminate(self._process.pid) except (OSError, ValueError) as err: raise MySQLServerError(err) return True class MySQLServer(MySQLServerBase): """Class for managing a MySQL server""" def __init__(self, basedir, topdir, cnf, bind_address, port, name, datadir=None, tmpdir=None, unix_socket_folder=None, ssl_folder=None): self._cnf = cnf self._option_file = os.path.join(topdir, 'my.cnf') self._bind_address = bind_address self._port = port self._topdir = topdir self._basedir = basedir self._ssldir = ssl_folder or topdir self._datadir = datadir or os.path.join(topdir, 'data') self._tmpdir = tmpdir or os.path.join(topdir, 'tmp') self._name = name self._unix_socket = os.path.join(unix_socket_folder or self._topdir, 'mysql_cpy_' + name + '.sock') self._pid_file = os.path.join(topdir, 'mysql_cpy_' + name + '.pid') self._serverid = port + 100000 self._install = None self._server = None self._debug = False self.client_config = {} super(MySQLServer, self).__init__(self._basedir, self._option_file) def _create_directories(self): """Create directory structure for bootstrapping Create the directories needed for bootstrapping a MySQL installation, i.e. 'mysql' directory. The 'test' database is deliberately not created. Raises MySQLBootstrapError when something fails. """ LOGGER.debug("Creating {dir} {dir}/mysql and {dir}/test".format( dir=self._datadir)) os.mkdir(self._topdir) os.mkdir(os.path.join(self._topdir, 'tmp')) os.mkdir(self._datadir) os.mkdir(os.path.join(self._datadir, 'mysql')) def _get_bootstrap_cmd(self): """Get the command for bootstrapping. Get the command which will be used for bootstrapping. This is the full path to the mysqld executable and its arguments. Returns a list (used with subprocess.Popen) """ cmd = [ os.path.join(self._sbindir, EXEC_MYSQLD), '--no-defaults', '--bootstrap', '--basedir=%s' % self._basedir, '--datadir=%s' % self._datadir, '--log-warnings=0', #'--loose-skip-innodb', '--loose-skip-ndbcluster', '--max_allowed_packet=8M', '--default-storage-engine=myisam', '--net_buffer_length=16K', '--tmpdir=%s' % self._tmpdir, ] if self._version[0:2] < (5, 5): cmd.append('--language={0}'.format(self._lc_messages_dir)) else: cmd.extend([ '--lc-messages-dir={0}'.format(self._lc_messages_dir), '--lc-messages=en_US' ]) return cmd def bootstrap(self): """Bootstrap a MySQL installation Bootstrap a MySQL installation using the mysqld executable and the --bootstrap option. Arguments are defined by reading the defaults file and options set in the _get_bootstrap_cmd() method. Raises MySQLBootstrapError when something fails. """ if os.access(self._datadir, 0): raise MySQLBootstrapError("Datadir exists, can't bootstrap MySQL") # Order is important script_files = ( 'mysql_system_tables.sql', 'mysql_system_tables_data.sql', 'fill_help_tables.sql', ) # Extra SQL statements to execute after SQL scripts extra_sql = [ "CREATE DATABASE myconnpy;" ] try: self._create_directories() cmd = self._get_bootstrap_cmd() sql = [] sql.append("USE mysql;") for filename in script_files: full_path = os.path.join(self._scriptdir, filename) LOGGER.debug( "Reading SQL from '{path}'".format(path=full_path)) with open(full_path, 'r') as fp: sql += [line.strip() for line in fp.readlines()] sql += extra_sql logfile = open(os.path.join(self._topdir, 'bootstrap.log'), 'w') prc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=logfile) if sys.version_info[0] == 2: prc.communicate('\n'.join(sql)) else: prc.communicate(bytearray('\n'.join(sql), 'utf8')) logfile.close() except OSError as err: raise MySQLBootstrapError( "Error bootstrapping MySQL '{name}': {error}".format( name=self._name, error=str(err))) @property def name(self): """Returns the name of this MySQL server""" return self._name @property def port(self): """Return TCP/IP port of the server""" return self._port @property def bind_address(self): """Return IP address the server is listening on""" return self._bind_address @property def unix_socket(self): """Return the unix socket of the server""" return self._unix_socket def start(self): """Start a MySQL server""" if self.check_running(): LOGGER.error("MySQL server '{name}' already running".format( name=self.name)) return options = { 'name': self._name, 'basedir': _convert_forward_slash(self._basedir), 'datadir': _convert_forward_slash(self._datadir), 'tmpdir': _convert_forward_slash(self._tmpdir), 'bind_address': self._bind_address, 'port': self._port, 'unix_socket': _convert_forward_slash(self._unix_socket), 'ssl_dir': _convert_forward_slash(self._ssldir), 'pid_file': _convert_forward_slash(self._pid_file), 'serverid': self._serverid, 'lc_messages_dir': _convert_forward_slash( self._lc_messages_dir), } try: fp = open(self._option_file, 'w') fp.write(self._cnf.format(**options)) fp.close() self._start_server() time.sleep(3) except MySQLServerError as err: if self._debug is True: raise LOGGER.error("Failed starting MySQL server " "'{name}': {error}".format(name=self.name, error=str(err))) sys.exit(1) else: pid = get_pid(self._pid_file) if not pid: LOGGER.error("Failed getting PID of MySQL server " "'{name}'".format(name=self._name)) sys.exit(1) LOGGER.info("MySQL server started '{name}' " "(pid={pid})".format(pid=pid, name=self._name)) def stop(self): """Stop the MySQL server Stop the MySQL server and returns whether it was successful or not. This method stops the process and exits when it failed to stop the server due to an error. When the process was killed, but it the process is still found to be running, False is returned. When the server was stopped successfully, True is returned. Raises MySQLServerError or OSError when debug is enabled. Returns True or False. """ pid = get_pid(self._pid_file) if not pid: return try: if not self._stop_server(): process_terminate(pid) except (MySQLServerError, OSError) as err: if self._debug is True: raise LOGGER.error("Failed stopping MySQL server '{name}': " "{error}".format(error=str(err), name=self._name)) sys.exit(1) else: time.sleep(3) if self.check_running(pid): LOGGER.info("MySQL server stopped '{name}' " "(pid={pid})".format(pid=pid, name=self._name)) return True return False def remove(self): """Remove the topdir of the MySQL server""" if not os.path.exists(self._topdir) or self.check_running(): return try: rmtree(self._topdir) except OSError as err: LOGGER.debug("Failed removing {folder}: {error}".format( folder=self._topdir, error=err)) if self._debug is True: raise else: LOGGER.info("Removed {folder}".format(folder=self._topdir)) def check_running(self, pid=None): """Check if MySQL server is running Check if the MySQL server is running using the given pid, or when not specified, using the PID found in the PID file. Returns True or False. """ pid = pid or get_pid(self._pid_file) if pid: LOGGER.debug("Got PID " + str(pid)) return process_running(pid) return False def wait_up(self, tries=10, delay=1): """Wait until the MySQL server is up This method can be used to wait until the MySQL server is started. True is returned when the MySQL server is up, False otherwise. Return True or False. """ running = self.check_running() while not running: if tries == 0: break time.sleep(delay) running = self.check_running() tries -= 1 return running def wait_down(self, tries=10, delay=1): """Wait until the MySQL server is down This method can be used to wait until the MySQL server has stopped. True is returned when the MySQL server is down, False otherwise. Return True or False. """ running = self.check_running() while running: if tries == 0: break time.sleep(delay) running = self.check_running() tries -= 1 return not running mysql-connector-python-1.1.6/tests/__init__.py0000644001577100000120000003116312276514013020721 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unittests """ import os import sys import re import socket import datetime import inspect import platform import unittest import glob import logging LOGGER_NAME = "myconnpy_tests" LOGGER = logging.getLogger(LOGGER_NAME) try: from unittest.util import strclass except ImportError: # Python v2 from unittest import _strclass as strclass # pylint: disable=E0611 try: from unittest.case import SkipTest except ImportError: if sys.version_info[0:2] == (3, 1): from unittest import SkipTest elif sys.version_info[0:2] == (2, 6): # Support skipping tests for Python v2.6 from tests.py2 import test_skip, test_skip_if, SkipTest unittest.skip = test_skip unittest.skipIf = test_skip_if else: LOGGER.error("Could not initilize Python's unittest module") sys.exit(1) if sys.version_info[0] == 2: from tests.py2 import DummySocket else: from tests.py3 import DummySocket SSL_AVAILABLE = True try: import ssl except ImportError: SSL_AVAILABLE = False # Note that IPv6 support for Python is checked here, but it can be disabled # when the bind_address of MySQL was not set to '::1'. IPV6_AVAILABLE = socket.has_ipv6 OLD_UNITTEST = sys.version_info[0:2] in [(2, 6)] if os.name == 'nt': WINDOWS_VERSION = platform.win32_ver()[1] WINDOWS_VERSION_INFO = [0] * 2 for i, value in enumerate(WINDOWS_VERSION.split('.')[0:2]): WINDOWS_VERSION_INFO[i] = int(value) WINDOWS_VERSION_INFO = tuple(WINDOWS_VERSION_INFO) else: WINDOWS_VERSION = None WINDOWS_VERSION_INFO = () # Following dictionary holds messages which were added by test cases # but only logged at the end. MESSAGES = { 'WARNINGS': [], 'INFO': [], 'SKIPPED': [], } MYSQL_SERVERS_NEEDED = 1 MYSQL_SERVERS = [] MYSQL_VERSION = None SSL_DIR = os.path.join('tests', 'data', 'ssl') __all__ = [ 'MySQLConnectorTests', 'get_test_names', 'printmsg', 'LOGGER_NAME', 'DummySocket', 'SSL_DIR', 'get_test_modules', 'MESSAGES', ] # Get all modules which contain tests (prefix is 'test_') def get_test_modules(): """Get list of Python modules containing tests This function scans the tests/ folder for Python modules which name start with 'test_'. Returns a list of strings. """ major = sys.version_info[0] testcases = [] # For all python version for file_ in glob.glob(os.path.join('tests', 'test_*.py')): module = os.path.splitext(os.path.basename(file_))[0] testcases.append( 'tests.{module}'.format(module=module)) LOGGER.debug('Added tests.{module}'.format(module=module)) # Version specific tests ver_specific = os.path.join('tests'.format(major), 'py{0}'.format(major), 'test_*.py') for file_ in glob.glob(ver_specific): module = os.path.splitext(os.path.basename(file_))[0] testcases.append( 'tests.py{major}.{module}'.format(major=major, module=module)) LOGGER.debug('Added tests.py{major}.{module}'.format( major=major, module=module)) return testcases def get_test_names(): """Get test names This functions gets the names of Python modules containing tests. The name is parsed from files prefixed with 'test_'. For example, 'test_cursor.py' has name 'cursor'. Returns a list of strings. """ pattern = re.compile('.*test_') return [pattern.sub('', s) for s in get_test_modules()] def set_nr_mysql_servers(number): """Set the number of MySQL servers needed The functions sets how much MySQL servers are needed for running the unit tests. The number argument should be a integer between 1 and 16 (16 being the hard limit). The set_nr_mysql_servers function is used in test modules, usually at the very top (after imports). Raises AttributeError on errors. """ global MYSQL_SERVERS_NEEDED # pylint: disable=W0603 if not isinstance(number, int) or (number < 1 or number > 16): raise AttributeError( "number of MySQL servers should be a value between 1 and 16") if number > MYSQL_SERVERS_NEEDED: MYSQL_SERVERS_NEEDED = number def fake_hostname(): """Return a fake hostname This function returns a string which can be used in the creation of fake hostname. Note that we do not add a domain name. Returns a string. """ if sys.version_info[0] == 2: return ''.join(["%02x" % ord(c) for c in os.urandom(4)]) else: return ''.join(["%02x" % c for c in os.urandom(4)]) def get_mysql_config(name=None): """Get MySQL server configuration for running MySQL server If no name is given, then we will return the configuration of the first added. """ if not name: return MYSQL_SERVERS[0].client_config.copy() for server in MYSQL_SERVERS: if server.name == name: return server.client_config.copy() return None def have_engine(cnx, engine): """Check support for given storage engine This function checks if the MySQL server accessed through cnx has support for the storage engine. Returns True or False. """ have = False engine = engine.lower() cur = cnx.cursor() # Should use INFORMATION_SCHEMA, but play nice with v4.1 cur.execute("SHOW ENGINES") rows = cur.fetchall() for row in rows: if row[0].lower() == engine: if row[1].lower() == 'yes': have = True break cur.close() return have def cmp_result(result1, result2): """Compare results (list of tuples) coming from MySQL For certain results, like SHOW VARIABLES or SHOW WARNINGS, the order is unpredictable. To check if what is expected in the tests, we need to compare each row. Returns True or False. """ try: if len(result1) != len(result2): return False for row in result1: if row not in result2: return False except: return False return True class UTCTimeZone(datetime.tzinfo): """UTC""" def __init__(self): pass def utcoffset(self, dt): return datetime.timedelta(0) def dst(self, dt): return datetime.timedelta(0) def tzname(self, dt): return 'UTC' class TestTimeZone(datetime.tzinfo): """Test time zone""" def __init__(self, hours=0): self._offset = datetime.timedelta(hours=hours) def utcoffset(self, dt): return self._offset def dst(self, dt): return datetime.timedelta(0) def tzname(self, dt): return 'TestZone' class MySQLConnectorTests(unittest.TestCase): def __str__(self): classname = strclass(self.__class__) return "{classname}.{method}".format( method=self._testMethodName, classname=re.sub(r"tests\d*.test_", "", classname) ) def check_attr(self, obj, attrname, default): cls_name = obj.__class__.__name__ self.assertTrue( hasattr(obj, attrname), "{name} object has no '{attr}' attribute".format( name=cls_name, attr=attrname)) self.assertEqual( default, getattr(obj, attrname), "{name} object's '{attr}' should " "default to {type_} '{default}'".format( name=cls_name, attr=attrname, type_=type(default).__name__, default=default)) def check_method(self, obj, method): cls_name = obj.__class__.__name__ self.assertTrue( hasattr(obj, method), "{0} object has no '{1}' method".format(cls_name, method)) self.assertTrue( inspect.ismethod(getattr(obj, method)), "{0} object defines {1}, but is not a method".format( cls_name, method)) def check_args(self, function, supported_arguments): argspec = inspect.getargspec(function) function_arguments = dict(zip(argspec[0][1:], argspec[3])) for argument, default in function_arguments.items(): try: self.assertEqual( supported_arguments[argument], default, msg="Argument '{0}' has wrong default".format(argument)) except KeyError: self.fail("Found unsupported or new argument '%s'" % argument) for argument, default in supported_arguments.items(): if not argument in function_arguments: self.fail("Supported argument '{0}' fails".format(argument)) def _addSkip(self, result, reason): add_skip = getattr(result, 'addSkip', None) if add_skip: add_skip(self, self._testMethodName + ': ' + reason) def run(self, result=None): if sys.version_info[0:2] == (2, 6): test_method = getattr(self, self._testMethodName) if (getattr(self.__class__, "__unittest_skip__", False) or getattr(test_method, "__unittest_skip__", False)): # We skipped a class try: why = ( getattr(self.__class__, '__unittest_skip_why__', '') or getattr(test_method, '__unittest_skip_why__', '') ) self._addSkip(result, why) finally: result.stopTest(self) return if sys.version_info[0] == 2: return super(MySQLConnectorTests, self).run(result) else: return super().run(result) class TestsCursor(MySQLConnectorTests): def _test_execute_setup(self, cnx, tbl="myconnpy_cursor", engine="MyISAM"): self._test_execute_cleanup(cnx, tbl) stmt_create = ( "CREATE TABLE {table} " "(col1 INT, col2 VARCHAR(30), PRIMARY KEY (col1))" "ENGINE={engine}").format( table=tbl, engine=engine) try: cur = cnx.cursor() cur.execute(stmt_create) except Exception as err: # pylint: disable=W0703 self.fail("Failed setting up test table; {0}".format(err)) cur.close() def _test_execute_cleanup(self, cnx, tbl="myconnpy_cursor"): stmt_drop = "DROP TABLE IF EXISTS {table}".format(table=tbl) try: cur = cnx.cursor() cur.execute(stmt_drop) except Exception as err: # pylint: disable=W0703 self.fail("Failed cleaning up test table; {0}".format(err)) cur.close() def printmsg(msg=None): if msg is not None: print(msg) class SkipTest(Exception): """Exception compatible with SkipTest of Python v2.7 and later""" def _id(obj): """Function defined in unittest.case which is needed for decorators""" return obj def test_skip(reason): """Skip test This decorator is used by Python v2.6 code to keep compatible with Python v2.7 (and later) unittest.skip. """ def decorator(test): if not isinstance(test, (type, types.ClassType)): @wraps(test) def wrapper(*args, **kwargs): raise SkipTest(reason) test = wrapper test.__unittest_skip__ = True test.__unittest_skip_why__ = reason return test return decorator def test_skip_if(condition, reason): """Skip test if condition is true This decorator is used by Python v2.6 code to keep compatible with Python v2.7 (and later) unittest.skipIf. """ if condition: return test_skip(reason) return _id mysql-connector-python-1.1.6/tests/test_setup.py0000644001577100000120000001211512276514013021355 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Unit tests for the setup script of Connector/Python """ import sys import os import tests import imp import version class VersionTests(tests.MySQLConnectorTests): """Testing the version of Connector/Python""" def test_version(self): """Test validity of version""" vs = version.VERSION self.assertTrue(all( [isinstance(vs[0], int), isinstance(vs[1], int), isinstance(vs[2], int), isinstance(vs[3], str), isinstance(vs[4], int)])) def test___version__(self): """Test module __version__ and __version_info__""" import mysql.connector self.assertTrue(hasattr(mysql.connector, '__version__')) self.assertTrue(hasattr(mysql.connector, '__version_info__')) self.assertTrue(isinstance(mysql.connector.__version__, str)) self.assertTrue(isinstance(mysql.connector.__version_info__, tuple)) self.assertEqual(version.VERSION_TEXT, mysql.connector.__version__) self.assertEqual(version.VERSION, mysql.connector.__version_info__) class MetaSetupInfoTests(tests.MySQLConnectorTests): """Testing meta setup information We are importing the metasetupinfo module insite the unit tests to be able to actually do tests. """ def test_name(self): """Test the name of Connector/Python""" import metasetupinfo self.assertEqual('mysql-connector-python', metasetupinfo.name) def test_dev_statuses(self): """Test the development statuses""" import metasetupinfo exp = { 'a': '3 - Alpha', 'b': '4 - Beta', '': '5 - Production/Stable' } self.assertEqual(exp, metasetupinfo.DEVELOPMENT_STATUSES) def test_sys_path(self): """Test if sys.path has been updated""" # Following import is not used, but it does set the sys.path import metasetupinfo exp = 'python' + str(sys.version_info[0]) + '/' self.assertEqual(exp, sys.path[0]) def test_package_dir(self): """Test the package directory""" import metasetupinfo exp = { '': 'python' + str(sys.version_info[0]), 'mysql.connector.django': os.path.join('python23', 'django'), } self.assertEqual(exp, metasetupinfo.package_dir) def test_unsupported_python(self): """Test if old Python version are unsupported""" import metasetupinfo tmp = sys.version_info sys.version_info = (3, 0, 0, 'final', 0) try: imp.reload(metasetupinfo) except RuntimeError: pass else: self.fail("RuntimeError not raised with unsupported Python") sys.version_info = tmp def test_version(self): """Test the imported version information""" import metasetupinfo ver = metasetupinfo.VERSION exp = '{0}.{1}.{2}'.format(*ver[0:3]) self.assertEqual(exp, metasetupinfo.version) def test_misc_meta(self): """Test miscellaneous data such as URLs""" import metasetupinfo self.assertEqual( 'http://dev.mysql.com/doc/connector-python/en/index.html', metasetupinfo.url) self.assertEqual( 'http://dev.mysql.com/downloads/connector/python/', metasetupinfo.download_url) def test_classifiers(self): """Test Trove classifiers""" import metasetupinfo for clsfr in metasetupinfo.classifiers: if 'Programming Language :: Python' in clsfr: ver = clsfr.replace('Programming Language :: Python :: ', '') if ver not in ('2.6', '2.7', '3', '3.1', '3.2', '3.3'): self.fail('Unsupported version in classifiers') if 'Development Status ::' in clsfr: status = clsfr.replace('Development Status :: ', '') self.assertEqual( metasetupinfo.DEVELOPMENT_STATUSES[version.VERSION[3]], status) mysql-connector-python-1.1.6/setup.py0000644001577100000120000000413612276514013017160 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ To install MySQL Connector/Python: shell> python ./setup.py install """ import sys from distutils.core import setup from distutils.command.install import INSTALL_SCHEMES # Make sure that data files are actually installed in the package directory for install_scheme in INSTALL_SCHEMES.values(): install_scheme['data'] = install_scheme['purelib'] import metasetupinfo setup( name = metasetupinfo.name, version = metasetupinfo.version, description = metasetupinfo.description, long_description = metasetupinfo.long_description, author = metasetupinfo.author, author_email = metasetupinfo.author_email, license = metasetupinfo.license, keywords = metasetupinfo.keywords, url = metasetupinfo.url, download_url = metasetupinfo.download_url, package_dir = metasetupinfo.package_dir, packages = metasetupinfo.packages, classifiers = metasetupinfo.classifiers, cmdclass = metasetupinfo.cmdclasses ) mysql-connector-python-1.1.6/PKG-INFO0000644001577100000120000000272212276514327016552 0ustar pb2userwheelMetadata-Version: 1.0 Name: mysql-connector-python Version: 1.1.6 Summary: MySQL driver written in Python Home-page: http://dev.mysql.com/doc/connector-python/en/index.html Author: Oracle and/or its affiliates Author-email: UNKNOWN License: GNU GPLv2 (with FOSS License Exception) Download-URL: http://dev.mysql.com/downloads/connector/python/ Description: MySQL driver written in Python which does not depend on MySQL C client libraries and implements the DB API v2.0 specification (PEP-249). Keywords: mysql db Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Other Environment Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Education Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.1 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Topic :: Database Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Libraries :: Application Frameworks Classifier: Topic :: Software Development :: Libraries :: Python Modules mysql-connector-python-1.1.6/version.py0000644001577100000120000000303012276514013017475 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """MySQL Connector/Python version information The file version.py gets installed and is available after installation as mysql.connector.version. """ VERSION = (1, 1, 6, '', 0) if VERSION[3] and VERSION[4]: VERSION_TEXT = '{0}.{1}.{2}{3}{4}'.format(*VERSION) else: VERSION_TEXT = '{0}.{1}.{2}'.format(*VERSION[0:3]) LICENSE = 'GPLv2 with FOSS License Exception' EDITION = '' # Added in package names, after the version mysql-connector-python-1.1.6/COPYING0000644001577100000120000004354512276514013016510 0ustar pb2userwheelThere are special exceptions to the terms and conditions of the GNU General Public License as it is applied to this software. View the full text of the exception in file EXCEPTIONS-CLIENT in the directory of this software distribution or see the FOSS License Exception at www.mysql.com. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. mysql-connector-python-1.1.6/docs/0000755001577100000120000000000012276514327016402 5ustar pb2userwheelmysql-connector-python-1.1.6/docs/README_DOCS.txt0000644001577100000120000000035012276514013020676 0ustar pb2userwheelThe manual of MySQL Connector/Python is available online here: http://dev.mysql.com/doc/connector-python/en/index.html It is also available for download in various formats here: http://dev.mysql.com/doc/index-connectors.html mysql-connector-python-1.1.6/python2/0000755001577100000120000000000012276514327017055 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/examples/0000755001577100000120000000000012276514327020673 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/examples/client.py0000644001577100000120000001017412276514013022516 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ Simple CLI using the Connector/Python. It does not take arguments so you'll need to set the proper login information manually. Example output: $ ./client.py Welcome to MySQL Python CLI. Your MySQL connection ID is 21. Server version: 5.0.62-enterprise-gpl Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. (MySQLConsole) >>> show tables; 1046 (3D000): No database selected >>> use test; >>> show tables; >>> create table t1 (id int); >>> show tables; (u't1') """ from __future__ import print_function import sys import os import readline import code import atexit import re # We're actually just a demo and supposed to run in the source directory. sys.path.append('.') import mysql.connector class MySQLConsole(code.InteractiveConsole): mysql = None regexp = {} def __init__(self, mysql, locals=None, filename="", histfile=os.path.expanduser("~/.mysql_history")): code.InteractiveConsole.__init__(self) self.init_history(histfile) self.mysql = mysql self.regexp['USE'] = re.compile('USE (\w*)', re.IGNORECASE) def init_history(self, histfile): readline.parse_and_bind("tab: complete") if hasattr(readline, "read_history_file"): try: readline.read_history_file(histfile) except IOError: pass atexit.register(self.save_history, histfile) def save_history(self, histfile): readline.write_history_file(histfile) def send_query(self, line): rows = () try: cursor = self.mysql.cursor() cursor.execute(line) except mysql.connector.errors.Error as e: print(e.errmsglong) return try: rows = cursor.fetchall() for row in rows: print(row) except: pass def _do_use(db): try: my.cmd_init_db(db) except mysql.connector.errors.InterfaceError as e: print(e) def push(self, line): try: res = self.regexp['USE'].findall(line) db = res[0] self._do_use(db) except: pass self.send_query(line) code.InteractiveConsole(self, line) if __name__ == '__main__': print("Welcome to MySQL Python CLI.") try: db = mysql.connector.Connect(unix_socket='/tmp/mysql.sock', user='root', password='') except mysql.connector.errors.InterfaceError as e: print(e) sys.exit(1) console = MySQLConsole(db) myconnpy_version = "%s-%s" % ( '.'.join(map(str,mysql.connector.__version__[0:3])), mysql.connector.__version__[3]) print("Your MySQL connection ID is %d." % (db.get_server_threadid())) print("Server version: %s" % (db.get_server_info())) print("MySQL Connector/Python v%s" % (myconnpy_version)) print() console.interact() mysql-connector-python-1.1.6/python2/examples/multi_resultsets.py0000644001577100000120000000573612276514013024677 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * sending multiple statements and iterating over the results """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, info TEXT DEFAULT '', age TINYINT UNSIGNED DEFAULT '30', PRIMARY KEY (id) )""" cursor.execute(stmt_create) info = "abc"*10000 stmts = [ "INSERT INTO names (name) VALUES ('Geert')", "SELECT COUNT(*) AS cnt FROM names", "INSERT INTO names (name) VALUES ('Jan'),('Michel')", "SELECT name FROM names", ] # Note 'multi=True' when calling cursor.execute() for result in cursor.execute(' ; '.join(stmts), multi=True): if result.with_rows: if result.statement == stmts[3]: output.append("Names in table: " + ' '.join([ name[0] for name in result])) else: output.append("Number of rows: %d" % result.fetchone()[0]) else: if result.rowcount > 1: tmp = 's' else: tmp = '' output.append("Inserted %d row%s" % (result.rowcount, tmp)) cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/unicode.py0000755001577100000120000000562312276514013022674 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * the usefulness of unicode, if it works correctly.. * dropping and creating a table * inserting and selecting a row """ info = """ For this to work you need to make sure your terminal can output unicode character correctly. Check if the encoding of your terminal is set to UTF-8. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Show the unicode string we're going to use unistr = u"\u00bfHabla espa\u00f1ol?" output.append("Unicode string: %s" % unistr.encode('utf8')) # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS unicode" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE unicode ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, str VARCHAR(50) DEFAULT '' NOT NULL, PRIMARY KEY (id) ) CHARACTER SET 'utf8'""" cursor.execute(stmt_create) # Insert a row stmt_insert = "INSERT INTO unicode (str) VALUES (%s)" cursor.execute(stmt_insert, (unistr,)) # Select it again and show it stmt_select = "SELECT str FROM unicode WHERE id = %s" cursor.execute(stmt_select, (1,)) row = cursor.fetchone() output.append("Unicode string coming from db: %s" % row[0].encode('utf8')) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() print(info) out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/warnings.py0000755001577100000120000000403212276514013023067 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * using warnings """ STMT = "SELECT 'abc'+1" def main(config): output = [] config['get_warnings'] = True db = mysql.connector.Connect(**config) cursor = db.cursor() db.sql_mode = '' output.append("Executing '%s'" % STMT) cursor.execute(STMT) cursor.fetchall() warnings = cursor.fetchwarnings() if warnings: for w in warnings: output.append("%d: %s" % (w[1],w[2])) else: raise StandardError("Got no warnings") cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/inserts.py0000755001577100000120000000537112276514013022735 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * dropping and creating a table * inserting 3 rows using executemany() * selecting data and showing it """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, info TEXT DEFAULT '', age TINYINT UNSIGNED DEFAULT '30', PRIMARY KEY (id) )""" cursor.execute(stmt_create) info = "abc"*10000 # Insert 3 records names = ( ('Geert',info), ('Jan',info), ('Michel',info) ) stmt_insert = "INSERT INTO names (name,info) VALUES (%s,%s)" cursor.executemany(stmt_insert, names) db.commit() # Read the names again and print them stmt_select = "SELECT id, name, info, age FROM names ORDER BY id" cursor.execute(stmt_select) for row in cursor.fetchall(): output.append("%d | %s | %d\nInfo: %s..\n" % (row[0], row[1], row[3], row[2][20])) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/microseconds.py0000644001577100000120000000644512276514013023736 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function from datetime import time import mysql.connector """ Example using MySQL Connector/Python showing: * How to save timestamps including microseconds * Check the MySQL server version NOTE: This only works with MySQL 5.6.4 or greater. This example will work with earlier versions, but the microseconds information will be lost. Story: We keep track of swimmers in a freestyle 4x 100m relay swimming event with millisecond precision. """ CREATE_TABLE = """ CREATE TABLE relay_laps ( teamid TINYINT UNSIGNED NOT NULL, swimmer TINYINT UNSIGNED NOT NULL, lap TIME(3), PRIMARY KEY (teamid, swimmer) ) ENGINE=InnoDB """ def main(config): output = [] cnx = mysql.connector.Connect(**config) if cnx.get_server_version() < (5,6,4): output.append( "MySQL %s does not support fractional precision"\ " for timestamps." % cnx.get_server_info()) return output cursor = cnx.cursor() try: cursor.execute("DROP TABLE IF EXISTS relay_laps") except: # Ignoring the fact that it was not there pass cursor.execute(CREATE_TABLE) teams = {} teams[1] = [ (1, time(second=47, microsecond=510000)), (2, time(second=47, microsecond=20000)), (3, time(second=47, microsecond=650000)), (4, time(second=46, microsecond=60000)), ] insert = "INSERT INTO relay_laps (teamid,swimmer,lap) VALUES (%s,%s,%s)" for team, swimmers in teams.items(): for swimmer in swimmers: cursor.execute(insert, (team, swimmer[0], swimmer[1])) cnx.commit() cursor.execute("SELECT * FROM relay_laps") fmt = "%2s | %2s | %s" for row in cursor: output.append(fmt % row) try: cursor.execute("DROP TABLE IF EXISTS relay_laps") except: # Ignoring the fact that it was not there pass cursor.close() cnx.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/dates.py0000644001577100000120000000675112276514013022346 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os from datetime import datetime, tzinfo, timedelta import mysql.connector """ Example using MySQL Connector/Python showing: * How to get datetime, date and time types * Shows also invalid dates returned and handled * Force sql_mode to be not set for the active session """ # Note that by default MySQL takes invalid timestamps. This is for # backward compatibility. As of 5.0, use sql modes NO_ZERO_IN_DATE,NO_ZERO_DATE # to prevent this. _adate = datetime(1977,6,14,21,10,00) DATA = [ (_adate.date(), _adate, _adate.time()), ('0000-00-00', '0000-00-00 00:00:00', '00:00:00'), ('1000-00-00', '9999-00-00 00:00:00', '00:00:00'), ] def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() tbl = 'myconnpy_dates' cursor.execute('SET sql_mode = ""') # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS %s" % (tbl) cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE %s ( `id` tinyint(4) NOT NULL AUTO_INCREMENT, `c1` date DEFAULT NULL, `c2` datetime NOT NULL, `c3` time DEFAULT NULL, `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) )""" % (tbl) cursor.execute(stmt_create) # not using executemany to handle errors better stmt_insert = ("INSERT INTO %s (c1,c2,c3) VALUES " "(%%s,%%s,%%s)" % (tbl)) for d in DATA: try: cursor.execute(stmt_insert, d) except (mysql.connector.errors.Error, TypeError) as e: output.append("Failed inserting %s\nError: %s\n" % (d,e)) raise # Read the names again and print them stmt_select = "SELECT * FROM %s ORDER BY id" % (tbl) cursor.execute(stmt_select) for row in cursor.fetchall(): output.append("%3s | %10s | %19s | %8s |" % ( row[0], row[1], row[2], row[3], )) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/prepared_statements.py0000644001577100000120000000555712276514013025322 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Example using MySQL Prepared Statements Example using MySQL Connector/Python showing: * usage of Prepared Statements """ from __future__ import print_function import mysql.connector from mysql.connector.cursor import MySQLCursorPrepared def main(config): output = [] cnx = mysql.connector.Connect(**config) curprep = cnx.cursor(cursor_class=MySQLCursorPrepared) cur = cnx.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cur.execute(stmt_drop) stmt_create = ( "CREATE TABLE names (" "id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, " "name VARCHAR(30) DEFAULT '' NOT NULL, " "cnt TINYINT UNSIGNED DEFAULT 0, " "PRIMARY KEY (id))" ) cur.execute(stmt_create) # Connector/Python also allows ? as placeholders for MySQL Prepared # statements. prepstmt = "INSERT INTO names (name) VALUES (%s)" # Preparing the statement is done only once. It can be done before # without data, or later with data. curprep.execute(prepstmt) # Insert 3 records names = ('Geert', 'Jan', 'Michel') for name in names: curprep.execute(prepstmt, (name,)) cnx.commit() # We use a normal cursor issue a SELECT output.append("Inserted data") cur.execute("SELECT id, name FROM names") for row in cur: output.append("%d | %s" % (row[0], row[1])) # Cleaning up, dropping the table again cur.execute(stmt_drop) cnx.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/transaction.py0000755001577100000120000000752612276514013023577 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * dropping and creating a table * using warnings * doing a transaction, rolling it back and committing one. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, cnt TINYINT UNSIGNED DEFAULT 0, PRIMARY KEY (id) ) ENGINE=InnoDB""" cursor.execute(stmt_create) warnings = cursor.fetchwarnings() if warnings: ids = [ i for l,i,m in warnings] output.append("Oh oh.. we got warnings..") if 1266L in ids: output.append(""" Table was created as MYISAM, no transaction support. Bailing out, no use to continue. Make sure InnoDB is available! """) db.close() return # Insert 3 records output.append("Inserting data") names = ( ('Geert',), ('Jan',), ('Michel',) ) stmt_insert = "INSERT INTO names (name) VALUES (%s)" cursor.executemany(stmt_insert, names) # Roll back!!!! output.append("Rolling back transaction") db.rollback() # There should be no data! stmt_select = "SELECT id, name FROM names ORDER BY id" cursor.execute(stmt_select) rows = None try: rows = cursor.fetchall() except (mysql.connector.errors.InterfaceError) as e: raise if rows == []: output.append("No data, all is fine.") else: output.append("Something is wrong, we have data although we rolled back!") output.append([repr(r) for r in rows]) raise # Do the insert again. cursor.executemany(stmt_insert, names) # Data should be already there cursor.execute(stmt_select) output.append("Data before commit:") for row in cursor.fetchall(): output.append("%d | %s" % (row[0], row[1])) # Do a commit db.commit() cursor.execute(stmt_select) output.append("Data after commit:") for row in cursor.fetchall(): output.append("%d | %s" % (row[0], row[1])) # Cleaning up, dropping the table again cursor.execute(stmt_drop) db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/examples/__init__.py0000644001577100000120000000000012276514013022762 0ustar pb2userwheelmysql-connector-python-1.1.6/python2/examples/config.py0000644001577100000120000000344612276514013022511 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class Config(object): """Configure me so examples work Use me like this: mysql.connector.Connect(**Config.dbinfo()) """ HOST = 'localhost' DATABASE = 'test' USER = '' PASSWORD = '' PORT = 3306 CHARSET = 'utf8' UNICODE = True WARNINGS = True @classmethod def dbinfo(cls): return { 'host': cls.HOST, 'port': cls.PORT, 'database': cls.DATABASE, 'user': cls.USER, 'password': cls.PASSWORD, 'charset': cls.CHARSET, 'use_unicode': cls.UNICODE, 'get_warnings': cls.WARNINGS, } mysql-connector-python-1.1.6/python2/examples/engines.py0000755001577100000120000000353112276514013022672 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * that show engines works.. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Select it again and show it stmt_select = "SHOW ENGINES" cursor.execute(stmt_select) rows = cursor.fetchall() for row in rows: output.append(repr(row)) db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python2/__init__.py0000644001577100000120000000000012276514013021144 0ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/0000755001577100000120000000000012276514327020222 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/__init__.py0000644001577100000120000000000012276514013022311 0ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/connector/0000755001577100000120000000000012276514327022214 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/connector/connection.py0000644001577100000120000015111312276514013024717 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implementing communication with MySQL servers. """ import os import time import re import StringIO import cStringIO from mysql.connector.network import (MySQLUnixSocket, MySQLTCPSocket) from mysql.connector.constants import ( ClientFlag, ServerCmd, CharacterSet, ServerFlag, flag_is_set, ShutdownType, NET_BUFFER_LENGTH ) from mysql.connector.conversion import (MySQLConverterBase, MySQLConverter) from mysql.connector.protocol import MySQLProtocol from mysql.connector import errors from mysql.connector.utils import int4store from mysql.connector.cursor import (CursorBase, MySQLCursor, MySQLCursorRaw, MySQLCursorBuffered, MySQLCursorBufferedRaw, MySQLCursorPrepared) DEFAULT_CONFIGURATION = { 'database': None, 'user': '', 'password': '', 'host': '127.0.0.1', 'port': 3306, 'unix_socket': None, 'use_unicode': True, 'charset': 'utf8', 'collation': None, 'converter_class': MySQLConverter, 'autocommit': False, 'time_zone': None, 'sql_mode': None, 'get_warnings': False, 'raise_on_warnings': False, 'connection_timeout': None, 'client_flags': 0, 'compress': False, 'buffered': False, 'raw': False, 'ssl_ca': None, 'ssl_cert': None, 'ssl_key': None, 'ssl_verify_cert': False, 'passwd': None, 'db': None, 'connect_timeout': None, 'dsn': None, 'force_ipv6': False, } class MySQLConnection(object): """Connection to a MySQL Server""" def __init__(self, **kwargs): self._protocol = None self._socket = None self._handshake = None self._server_version = None self.converter = None self._converter_class = MySQLConverter self._client_flags = ClientFlag.get_default() self._charset_id = 33 self._sql_mode = None self._time_zone = None self._autocommit = False self._user = '' self._password = '' self._database = '' self._host = '127.0.0.1' self._port = 3306 self._unix_socket = None self._client_host = '' self._client_port = 0 self._ssl = {} self._force_ipv6 = False self._use_unicode = True self._get_warnings = False self._raise_on_warnings = False self._connection_timeout = None self._buffered = False self._unread_result = False self._have_next_result = False self._raw = False self._in_transaction = False self._prepared_statements = None if len(kwargs) > 0: self.connect(**kwargs) def _get_self(self): """Return self for weakref.proxy This method is used when the original object is needed when using weakref.proxy. """ return self def _do_handshake(self): """Get the handshake from the MySQL server""" packet = self._socket.recv() if packet[4] == '\xff': raise errors.get_exception(packet) try: handshake = self._protocol.parse_handshake(packet) except Exception as err: raise errors.InterfaceError('Failed parsing handshake; %s' % err) regex_ver = re.compile(r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)") match = regex_ver.match(handshake['server_version_original']) if not match: raise errors.InterfaceError("Failed parsing MySQL version") version = tuple([int(v) for v in match.groups()[0:3]]) if version < (4, 1): raise errors.InterfaceError( "MySQL Version '%s' is not supported." % \ handshake['server_version_original']) self._handshake = handshake self._server_version = version def _do_auth(self, username=None, password=None, database=None, client_flags=0, charset=33, ssl_options=None): """Authenticate with the MySQL server """ if client_flags & ClientFlag.SSL and ssl_options: packet = self._protocol.make_auth_ssl(charset=charset, client_flags=client_flags) self._socket.send(packet) self._socket.switch_to_ssl(**ssl_options) packet = self._protocol.make_auth( seed=self._handshake['scramble'], username=username, password=password, database=database, charset=charset, client_flags=client_flags) self._socket.send(packet) packet = self._socket.recv() if packet[4] == '\xfe': raise errors.NotSupportedError( "Authentication with old (insecure) passwords " "is not supported. For more information, lookup " "Password Hashing in the latest MySQL manual") elif packet[4] == '\xff': raise errors.get_exception(packet) try: if (not (client_flags & ClientFlag.CONNECT_WITH_DB) and database): self.cmd_init_db(database) except: raise return True def config(self, **kwargs): """Configure the MySQL Connection This method allows you to configure the MySQLConnection instance. Raises AttributeError when a configuration parameter is invalid, missing or unsupported. """ config = kwargs.copy() if 'dsn' in config: raise errors.NotSupportedError("Data source name is not supported") # Configure how we handle MySQL warnings try: self.get_warnings = config['get_warnings'] del config['get_warnings'] except KeyError: pass # Leave what was set or default try: self.raise_on_warnings = config['raise_on_warnings'] del config['raise_on_warnings'] except KeyError: pass # Leave what was set or default # Configure client flags try: default = ClientFlag.get_default() self.set_client_flags(config['client_flags'] or default) del config['client_flags'] except KeyError: pass # Missing client_flags-argument is OK try: if config['compress']: self.set_client_flags([ClientFlag.COMPRESS]) except KeyError: pass # Missing compress argument is OK # Configure character set and collation if ('charset' in config or 'collation' in config): try: charset = config['charset'] del config['charset'] except KeyError: charset = None try: collation = config['collation'] del config['collation'] except KeyError: collation = None self._charset_id = CharacterSet.get_charset_info(charset, collation)[0] # Set converter class try: self.set_converter_class(config['converter_class']) except KeyError: pass # Using default converter class except TypeError: raise AttributeError("Converter class should be a subclass " "of conversion.MySQLConverterBase.") # Compatible configuration with other drivers compat_map = [ # (,) ('db', 'database'), ('passwd', 'password'), ('connect_timeout', 'connection_timeout'), ] for compat, translate in compat_map: try: if translate not in config: config[translate] = config[compat] del config[compat] except KeyError: pass # Missing compat argument is OK # Configure login information if ('user' in config or 'password' in config): try: user = config['user'] del config['user'] except KeyError: user = self._user try: password = config['password'] del config['password'] except KeyError: password = self._password self.set_login(user, password) # Check network locations try: self._port = int(config['port']) del config['port'] except KeyError: pass # Missing port argument is OK except ValueError: raise errors.InterfaceError( "TCP/IP port number should be an integer") # Other configuration set_ssl_flag = False for key, value in config.items(): try: DEFAULT_CONFIGURATION[key] except KeyError: raise AttributeError("Unsupported argument '{0}'".format(key)) # SSL Configuration if key == 'ssl_verify_cert': set_ssl_flag = True self._ssl.update({'verify_cert': value}) elif key.startswith('ssl_') and value: set_ssl_flag = True self._ssl.update({key.replace('ssl_', ''): value}) else: attribute = '_' + key try: setattr(self, attribute, value.strip()) except AttributeError: setattr(self, attribute, value) if set_ssl_flag: if 'verify_cert' not in self._ssl: self._ssl['verify_cert'] = \ DEFAULT_CONFIGURATION['ssl_verify_cert'] required_keys = set(['ca', 'cert', 'key']) diff = list(required_keys - set(self._ssl.keys())) if diff: missing_attrs = ["ssl_" + val for val in diff] raise AttributeError("Missing SSL argument(s): {0}".format( ', '.join(missing_attrs))) self.set_client_flags([ClientFlag.SSL]) def _get_connection(self): """Get connection based on configuration This method will return the appropriated connection object using the connection parameters. Returns subclass of MySQLBaseSocket. """ conn = None if self.unix_socket and os.name != 'nt': conn = MySQLUnixSocket(unix_socket=self.unix_socket) else: conn = MySQLTCPSocket(host=self.server_host, port=self.server_port, force_ipv6=self._force_ipv6) conn.set_connection_timeout(self._connection_timeout) return conn def _open_connection(self): """Open the connection to the MySQL server This method sets up and opens the connection to the MySQL server. """ self._socket = self._get_connection() self._socket.open_connection() self._do_handshake() self._do_auth(self._user, self._password, self._database, self._client_flags, self._charset_id, self._ssl) self.set_converter_class(self._converter_class) if self._client_flags & ClientFlag.COMPRESS: self._socket.recv = self._socket.recv_compressed self._socket.send = self._socket.send_compressed def _post_connection(self): """Executes commands after connection has been established This method executes commands after the connection has been established. Some setting like autocommit, character set, and SQL mode are set using this method. """ self.set_charset_collation(charset=self._charset_id) self.autocommit = self._autocommit if self._time_zone: self.time_zone = self._time_zone if self._sql_mode: self.sql_mode = self._sql_mode def connect(self, **kwargs): """Connect to the MySQL server This method sets up the connection to the MySQL server. If no arguments are given, it will use the already configured or default values. """ if len(kwargs) > 0: self.config(**kwargs) self._protocol = MySQLProtocol() self.disconnect() self._open_connection() self._post_connection() def disconnect(self): """Disconnect from the MySQL server """ if not self._socket: return try: self.cmd_quit() self._socket.close_connection() except (AttributeError, errors.Error): pass # Getting an exception would mean we are disconnected. close = disconnect def _send_cmd(self, command, argument=None, packet_number=0, packet=None, expect_response=True): """Send a command to the MySQL server This method sends a command with an optional argument. If packet is not None, it will be sent and the argument will be ignored. The packet_number is optional and should usually not be used. Some commands might not result in the MySQL server returning a response. If a command does not return anything, you should set expect_response to False. The _send_cmd method will then return None instead of a MySQL packet. Returns a MySQL packet or None. """ if self.unread_result: raise errors.InternalError("Unread result found.") try: self._socket.send( self._protocol.make_command(command, packet or argument), packet_number) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") if not expect_response: return None return self._socket.recv() def _send_data(self, data_file, send_empty_packet=False): """Send data to the MySQL server This method accepts a file-like object and sends its data as is to the MySQL server. If the send_empty_packet is True, it will send an extra empty package (for example when using LOAD LOCAL DATA INFILE). Returns a MySQL packet. """ if self.unread_result: raise errors.InternalError("Unread result found.") if not hasattr(data_file, 'read'): raise ValueError("expecting a file-like object") try: buf = data_file.read(NET_BUFFER_LENGTH - 16) while buf: self._socket.send(buf) buf = data_file.read(NET_BUFFER_LENGTH - 16) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") if send_empty_packet: try: self._socket.send('') except AttributeError: raise errors.OperationalError( "MySQL Connection not available.") return self._socket.recv() def _handle_server_status(self, flags): """Handle the server flags found in MySQL packets This method handles the server flags send by MySQL OK and EOF packets. It, for example, checks whether there exists more result sets or whether there is an ongoing transaction. """ self._have_next_result = flag_is_set(ServerFlag.MORE_RESULTS_EXISTS, flags) self._in_transaction = flag_is_set(ServerFlag.STATUS_IN_TRANS, flags) @property def in_transaction(self): """MySQL session has started a transaction """ return self._in_transaction def _handle_ok(self, packet): """Handle a MySQL OK packet This method handles a MySQL OK packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither an OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == '\x00': ok_packet = self._protocol.parse_ok(packet) self._handle_server_status(ok_packet['server_status']) return ok_packet elif packet[4] == '\xff': raise errors.get_exception(packet) raise errors.InterfaceError('Expected OK packet') def _handle_eof(self, packet): """Handle a MySQL EOF packet This method handles a MySQL EOF packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither and OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == '\xfe': eof = self._protocol.parse_eof(packet) self._handle_server_status(eof['status_flag']) return eof elif packet[4] == '\xff': raise errors.get_exception(packet) raise errors.InterfaceError('Expected EOF packet') def _handle_load_data_infile(self, filename): """Handle a LOAD DATA INFILE LOCAL request""" try: data_file = open(filename, 'rb') except IOError: # Send a empty packet to cancel the operation try: self._socket.send('') except AttributeError: raise errors.OperationalError( "MySQL Connection not available.") raise errors.InterfaceError("File '{0}' could not be read".format( filename)) return self._handle_ok(self._send_data(data_file, send_empty_packet=True)) def _handle_result(self, packet): """Handle a MySQL Result This method handles a MySQL result, for example, after sending the query command. OK and EOF packets will be handled and returned. If the packet is an Error packet, an errors.Error-exception will be raised. The dictionary returned of: - columns: column information - eof: the EOF-packet information Returns a dict() """ if not packet or len(packet) < 4: raise errors.InterfaceError('Empty response') elif packet[4] == '\x00': return self._handle_ok(packet) elif packet[4] == '\xfb': return self._handle_load_data_infile(packet[5:]) elif packet[4] == '\xfe': return self._handle_eof(packet) elif packet[4] == '\xff': raise errors.get_exception(packet) # We have a text result set column_count = self._protocol.parse_column_count(packet) if not column_count or not isinstance(column_count, int): raise errors.InterfaceError('Illegal result set.') columns = [None,] * column_count for i in xrange(0, column_count): columns[i] = self._protocol.parse_column(self._socket.recv()) eof = self._handle_eof(self._socket.recv()) self.unread_result = True return {'columns': columns, 'eof': eof} def get_rows(self, count=None, binary=False, columns=None): """Get all rows returned by the MySQL server This method gets all rows returned by the MySQL server after sending, for example, the query command. The result is a tuple consisting of a list of rows and the EOF packet. Returns a tuple() """ if not self.unread_result: raise errors.InternalError("No result set available.") if binary: rows = self._protocol.read_binary_result( self._socket, columns, count) else: rows = self._protocol.read_text_result(self._socket, count) if rows[-1] is not None: self._handle_server_status(rows[-1]['status_flag']) self.unread_result = False return rows def get_row(self, binary=False, columns=None): """Get the next rows returned by the MySQL server This method gets one row from the result set after sending, for example, the query command. The result is a tuple consisting of the row and the EOF packet. If no row was available in the result set, the row data will be None. Returns a tuple. """ (rows, eof) = self.get_rows(count=1, binary=binary, columns=columns) if len(rows): return (rows[0], eof) return (None, eof) def cmd_init_db(self, database): """Change the current database This method changes the current (default) database by sending the INIT_DB command. The result is a dictionary containing the OK packet information. Returns a dict() """ return self._handle_ok(self._send_cmd(ServerCmd.INIT_DB, database)) def cmd_query(self, statement): """Send a statement to the MySQL server This method sends the given statement to the MySQL server and returns a result. If you need to send multiple statements, you have to use the cmd_query_iter() method. The returned dictionary contains information depending on what kind of query was executed. If the query is a SELECT statement, the result will contain information about columns. Other statements will return a dictionary containing an OK or EOF packet. Errors received from the MySQL server will be raised as exceptions. An InterfaceError is raised when multiple results were found. Returns a dictionary. """ result = self._handle_result(self._send_cmd(ServerCmd.QUERY, statement)) if self._have_next_result: raise errors.InterfaceError( 'Use cmd_query_iter for statements with multiple queries.') return result def cmd_query_iter(self, statements): """Send one or more statements to the MySQL server Similar to the cmd_query method, but instead returns a generator object to iterate through results. It sends the statements to the MySQL server and through the iterator you can get the results. statement = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2' for result in cnx.cmd_query(statement, iterate=True): if 'columns' in result: columns = result['columns'] rows = cnx.get_rows() else: # do something useful with INSERT result Returns a generator. """ # Handle the first query result yield self._handle_result(self._send_cmd(ServerCmd.QUERY, statements)) # Handle next results, if any while self._have_next_result: if self.unread_result: raise errors.InternalError("Unread result found.") else: result = self._handle_result(self._socket.recv()) yield result def cmd_refresh(self, options): """Send the Refresh command to the MySQL server This method sends the Refresh command to the MySQL server. The options argument should be a bitwise value using constants.RefreshOption. Usage example: RefreshOption = mysql.connector.RefreshOption refresh = RefreshOption.LOG | RefreshOption.THREADS cnx.cmd_refresh(refresh) The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok( self._send_cmd(ServerCmd.REFRESH, int4store(options))) def cmd_quit(self): """Close the current connection with the server This method sends the QUIT command to the MySQL server, closing the current connection. Since the no response can be returned to the client, cmd_quit() will return the packet it send. Returns a str() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_command(ServerCmd.QUIT) self._socket.send(packet, 0) return packet def cmd_shutdown(self, shutdown_type=None): """Shut down the MySQL Server This method sends the SHUTDOWN command to the MySQL server and is only possible if the current user has SUPER privileges. The result is a dictionary containing the OK packet information. Note: Most applications and scripts do not the SUPER privilege. Returns a dict() """ if shutdown_type: if not ShutdownType.get_info(shutdown_type): raise errors.InterfaceError("Invalid shutdown type") atype = shutdown_type else: atype = ShutdownType.SHUTDOWN_DEFAULT return self._handle_eof(self._send_cmd(ServerCmd.SHUTDOWN, atype)) def cmd_statistics(self): """Send the statistics command to the MySQL Server This method sends the STATISTICS command to the MySQL server. The result is a dictionary with various statistical information. Returns a dict() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_command(ServerCmd.STATISTICS) self._socket.send(packet, 0) return self._protocol.parse_statistics(self._socket.recv()) def cmd_process_info(self): """Get the process list of the MySQL Server This method is a placeholder to notify that the PROCESS_INFO command is not supported by raising the NotSupportedError. The command "SHOW PROCESSLIST" should be send using the cmd_query()-method or using the INFORMATION_SCHEMA database. Raises NotSupportedError exception """ raise errors.NotSupportedError( "Not implemented. Use SHOW PROCESSLIST or INFORMATION_SCHEMA") def cmd_process_kill(self, mysql_pid): """Kill a MySQL process This method send the PROCESS_KILL command to the server along with the process ID. The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok( self._send_cmd(ServerCmd.PROCESS_KILL, int4store(mysql_pid))) def cmd_debug(self): """Send the DEBUG command This method sends the DEBUG command to the MySQL server, which requires the MySQL user to have SUPER privilege. The output will go to the MySQL server error log and the result of this method is a dictionary with EOF packet information. Returns a dict() """ return self._handle_eof(self._send_cmd(ServerCmd.DEBUG)) def cmd_ping(self): """Send the PING command This method sends the PING command to the MySQL server. It is used to check if the the connection is still valid. The result of this method is dictionary with OK packet information. Returns a dict() """ return self._handle_ok(self._send_cmd(ServerCmd.PING)) def cmd_change_user(self, username='', password='', database='', charset=33): """Change the current logged in user This method allows to change the current logged in user information. The result is a dictionary with OK packet information. Returns a dict() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_change_user( seed=self._handshake['scramble'], username=username, password=password, database=database, charset=charset, client_flags=self._client_flags) self._socket.send(packet, 0) return self._handle_ok(self._socket.recv()) def is_connected(self): """Reports whether the connection to MySQL Server is available This method checks whether the connection to MySQL is available. It is similar to ping(), but unlike the ping()-method, either True or False is returned and no exception is raised. Returns True or False. """ try: self.cmd_ping() except errors.Error: return False # This method does not raise return True def reconnect(self, attempts=1, delay=0): """Attempt to reconnect to the MySQL server The argument attempts should be the number of times a reconnect is tried. The delay argument is the number of seconds to wait between each retry. You may want to set the number of attempts higher and use delay when you expect the MySQL server to be down for maintenance or when you expect the network to be temporary unavailable. Raises InterfaceError on errors. """ counter = 0 while counter != attempts: counter = counter + 1 try: self.disconnect() self.connect() if self.is_connected(): break except StandardError as err: if counter == attempts: raise errors.InterfaceError("Can not reconnect to MySQL " "after %d attempt(s): %s" % ( attempts, str(err))) if delay > 0: time.sleep(delay) def ping(self, reconnect=False, attempts=1, delay=0): """Check availability to the MySQL server When reconnect is set to True, one or more attempts are made to try to reconnect to the MySQL server using the reconnect()-method. delay is the number of seconds to wait between each retry. When the connection is not available, an InterfaceError is raised. Use the is_connected()-method if you just want to check the connection without raising an error. Raises InterfaceError on errors. """ try: self.cmd_ping() except errors.Error: if reconnect: self.reconnect(attempts=attempts, delay=delay) else: raise errors.InterfaceError("Connection to MySQL is" " not available.") def set_converter_class(self, convclass): """ Set the converter class to be used. This should be a class overloading methods and members of conversion.MySQLConverter. """ if issubclass(convclass, MySQLConverterBase): charset_name = CharacterSet.get_info(self._charset_id)[0] self._converter_class = convclass self.converter = convclass(charset_name, self._use_unicode) else: raise TypeError("Converter class should be a subclass " "of conversion.MySQLConverterBase.") def get_server_version(self): """Get the MySQL version This method returns the MySQL server version as a tuple. If not previously connected, it will return None. Returns a tuple or None. """ return self._server_version def get_server_info(self): """Get the original MySQL version information This method returns the original MySQL server as text. If not previously connected, it will return None. Returns a string or None. """ try: return self._handshake['server_version_original'] except (TypeError, KeyError): return None @property def connection_id(self): """MySQL connection ID""" try: return self._handshake['server_threadid'] except KeyError: return None def set_login(self, username=None, password=None): """Set login information for MySQL Set the username and/or password for the user connecting to the MySQL Server. """ if username is not None: self._user = username.strip() else: self._user = '' if password is not None: self._password = password.strip() else: self._password = '' def set_unicode(self, value=True): """Toggle unicode mode Set whether we return string fields as unicode or not. Default is True. """ self._use_unicode = value if self.converter: self.converter.set_unicode(value) def set_charset_collation(self, charset=None, collation=None): """Sets the character set and collation for the current connection This method sets the character set and collation to be used for the current connection. The charset argument can be either the name of a character set as a string, or the numerical equivalent as defined in constants.CharacterSet. When the collation is not given, the default will be looked up and used. For example, the following will set the collation for the latin1 character set to latin1_general_ci: set_charset('latin1','latin1_general_ci') """ if charset: if isinstance(charset, int): self._charset_id = charset (charset_name, collation_name) = CharacterSet.get_info( self._charset_id) elif isinstance(charset, str): (self._charset_id, charset_name, collation_name) = \ CharacterSet.get_charset_info(charset, collation) else: raise ValueError( "charset should be either integer, string or None") elif collation: (self._charset_id, charset_name, collation_name) = \ CharacterSet.get_charset_info(collation=collation) self._execute_query("SET NAMES '%s' COLLATE '%s'" % ( charset_name, collation_name)) self.converter.set_charset(charset_name) @property def charset(self): """Returns the character set for current connection This property returns the character set name of the current connection. Note that the value returned is based on what is previously set by the set_charset_collation(). Returns a string. """ return CharacterSet.get_info(self._charset_id)[0] @property def python_charset(self): """Returns the Python character set for current connection This property returns the character set name of the current connection. Note that, unlike property charset, this checks if the previously set character set is supported by Python and if not, it returns the equivalent character set that Python supports. Returns a string. """ encoding = CharacterSet.get_info(self._charset_id)[0] if encoding == 'utf8mb4': return 'utf8' else: return encoding @property def collation(self): """Returns the collation for current connection This property returns the collation name of the current connection. Note that the value returned is based on what is previously set by the set_charset_collation(). Returns a string. """ return CharacterSet.get_charset_info(self._charset_id)[2] def set_client_flags(self, flags): """Set the client flags The flags-argument can be either an int or a list (or tuple) of ClientFlag-values. If it is an integer, it will set client_flags to flags as is. If flags is a list (or tuple), each flag will be set or unset when it's negative. set_client_flags([ClientFlag.FOUND_ROWS,-ClientFlag.LONG_FLAG]) Raises ProgrammingError when the flags argument is not a set or an integer bigger than 0. Returns self._client_flags """ if isinstance(flags, int) and flags > 0: self._client_flags = flags elif isinstance(flags, (tuple, list)): for flag in flags: if flag < 0: self._client_flags &= ~abs(flag) else: self._client_flags |= flag else: raise errors.ProgrammingError( "set_client_flags expect int (>0) or set") return self._client_flags def isset_client_flag(self, flag): """Check if a client flag is set""" if (self._client_flags & flag) > 0: return True return False @property def user(self): """User used while connecting to MySQL""" return self._user @property def server_host(self): """MySQL server IP address or name""" return self._host @property def server_port(self): "MySQL server TCP/IP port" return self._port @property def unix_socket(self): "MySQL Unix socket file location" return self._unix_socket def _set_unread_result(self, toggle): """Set whether there is an unread result This method is used by cursors to let other cursors know there is still a result set that needs to be retrieved. Raises ValueError on errors. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._unread_result = toggle def _get_unread_result(self): """Get whether there is an unread result This method is used by cursors to check whether another cursor still needs to retrieve its result set. Returns True, or False when there is no unread result. """ return self._unread_result unread_result = property(_get_unread_result, _set_unread_result, doc="Unread result for this MySQL connection") def set_database(self, value): """Set the current database""" self.cmd_query("USE %s" % value) def get_database(self): """Get the current database""" return self._info_query("SELECT DATABASE()")[0] database = property(get_database, set_database, doc="Current database") def set_time_zone(self, value): """Set the time zone""" self.cmd_query("SET @@session.time_zone = '%s'" % value) self._time_zone = value def get_time_zone(self): """Get the current time zone""" return self._info_query("SELECT @@session.time_zone")[0] time_zone = property(get_time_zone, set_time_zone, doc="time_zone value for current MySQL session") def set_sql_mode(self, value): """Set the SQL mode This method sets the SQL Mode for the current connection. The value argument can be either a string with comma separate mode names, or a sequence of mode names. It is good practice to use the constants class SQLMode: from mysql.connector.constants import SQLMode cnx.sql_mode = [SQLMode.NO_ZERO_DATE, SQLMode.REAL_AS_FLOAT] """ if isinstance(value, (list, tuple)): value = ','.join(value) self.cmd_query("SET @@session.sql_mode = '%s'" % value) self._sql_mode = value def get_sql_mode(self): """Get the SQL mode""" return self._info_query("SELECT @@session.sql_mode")[0] sql_mode = property(get_sql_mode, set_sql_mode, doc="sql_mode value for current MySQL session") def set_autocommit(self, value): """Toggle autocommit""" if value: switch = 'ON' else: switch = 'OFF' self._execute_query("SET @@session.autocommit = %s" % switch) def get_autocommit(self): """Get whether autocommit is on or off""" value = self._info_query("SELECT @@session.autocommit")[0] if value == 1: return True return False autocommit = property(get_autocommit, set_autocommit, doc="autocommit value for current MySQL session") def _set_getwarnings(self, toggle): """Set whether warnings should be automatically retrieved The toggle-argument must be a boolean. When True, cursors for this connection will retrieve information about warnings (if any). Raises ValueError on error. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._get_warnings = toggle def _get_getwarnings(self): """Get whether this connection retrieves warnings automatically This method returns whether this connection retrieves warnings automatically. Returns True, or False when warnings are not retrieved. """ return self._get_warnings get_warnings = property(_get_getwarnings, _set_getwarnings, doc="Toggle and check whether to retrieve " "warnings automatically") def _set_raise_on_warnings(self, toggle): """Set whether warnings raise an error The toggle-argument must be a boolean. When True, cursors for this connection will raise an error when MySQL reports warnings. Raising on warnings implies retrieving warnings automatically. In other words: warnings will be set to True. If set to False, warnings will be also set to False. Raises ValueError on error. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._raise_on_warnings = toggle self._get_warnings = toggle def _get_raise_on_warnings(self): """Get whether this connection raises an error on warnings This method returns whether this connection will raise errors when MySQL reports warnings. Returns True or False. """ return self._raise_on_warnings raise_on_warnings = property(_get_raise_on_warnings, _set_raise_on_warnings, doc="Toggle whether to raise on warnings " "(implies retrieving warnings).") def cursor(self, buffered=None, raw=None, prepared=None, cursor_class=None): """Instantiates and returns a cursor By default, MySQLCursor is returned. Depending on the options while connecting, a buffered and/or raw cursor instantiated instead. It is possible to also give a custom cursor through the cursor_class parameter, but it needs to be a subclass of mysql.connector.cursor.CursorBase. Returns a cursor-object """ if self._unread_result is True: raise errors.InternalError("Unread result found.") if not self.is_connected(): raise errors.OperationalError("MySQL Connection not available.") if cursor_class is not None: if not issubclass(cursor_class, CursorBase): raise errors.ProgrammingError( "Cursor class needs to be subclass of cursor.CursorBase") return (cursor_class)(self) if prepared is True: return MySQLCursorPrepared(self) buffered = buffered or self._buffered raw = raw or self._raw cursor_type = 0 if buffered is True: cursor_type |= 1 if raw is True: cursor_type |= 2 types = ( MySQLCursor, # 0 MySQLCursorBuffered, MySQLCursorRaw, MySQLCursorBufferedRaw, ) return (types[cursor_type])(self) def start_transaction(self, consistent_snapshot=False, isolation_level=None, readonly=None): """Start a transaction This method explicitly starts a transaction sending the START TRANSACTION statement to the MySQL server. You can optionally set whether there should be a consistent snapshot, which isolation level you need or which access mode i.e. READ ONLY or READ WRITE. For example, to start a transaction with isolation level SERIALIZABLE, you would do the following: >>> cnx = mysql.connector.connect(..) >>> cnx.start_transaction(isolation_level='SERIALIZABLE') Raises ProgrammingError when a transaction is already in progress and when ValueError when isolation_level specifies an Unknown level. """ if self.in_transaction: raise errors.ProgrammingError("Transaction already in progress") if isolation_level: level = isolation_level.strip().replace('-', ' ').upper() levels = ['READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ', 'SERIALIZABLE'] if level not in levels: raise ValueError( 'Unknown isolation level "{0}"'.format(isolation_level)) self._execute_query( "SET TRANSACTION ISOLATION LEVEL {0}".format(level)) if readonly is not None: if self._server_version < (5, 6, 5): raise ValueError( "MySQL server version {0} does not support " "this feature".format(self._server_version)) if readonly: access_mode = 'READ ONLY' else: access_mode = 'READ WRITE' self._execute_query( "SET TRANSACTION {0}".format(access_mode)) query = "START TRANSACTION" if consistent_snapshot: query += " WITH CONSISTENT SNAPSHOT" self._execute_query(query) def commit(self): """Commit current transaction""" self._execute_query("COMMIT") def rollback(self): """Rollback current transaction""" if self._unread_result: self.get_rows() self._execute_query("ROLLBACK") def _execute_query(self, query): """Execute a query This method simply calls cmd_query() after checking for unread result. If there are still unread result, an errors.InterfaceError is raised. Otherwise whatever cmd_query() returns is returned. Returns a dict() """ if self._unread_result is True: raise errors.InternalError("Unread result found.") self.cmd_query(query) def _info_query(self, query): """Send a query which only returns 1 row""" cursor = self.cursor(buffered=True) cursor.execute(query) return cursor.fetchone() def _handle_binary_ok(self, packet): """Handle a MySQL Binary Protocol OK packet This method handles a MySQL Binary Protocol OK packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither an OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == '\x00': return self._protocol.parse_binary_prepare_ok(packet) elif packet[4] == '\xff': raise errors.get_exception(packet) raise errors.InterfaceError('Expected Binary OK packet') def _handle_binary_result(self, packet): """Handle a MySQL Result This method handles a MySQL result, for example, after sending the query command. OK and EOF packets will be handled and returned. If the packet is an Error packet, an errors.Error-exception will be raised. The tuple returned by this method consist of: - the number of columns in the result, - a list of tuples with information about the columns, - the EOF packet information as a dictionary. Returns tuple() or dict() """ if not packet or len(packet) < 4: raise errors.InterfaceError('Empty response') elif packet[4] == '\x00': return self._handle_ok(packet) elif packet[4] == '\xfe': return self._handle_eof(packet) elif packet[4] == '\xff': raise errors.get_exception(packet) # We have a binary result set column_count = self._protocol.parse_column_count(packet) if not column_count or not isinstance(column_count, int): raise errors.InterfaceError('Illegal result set.') columns = [None,] * column_count for i in xrange(0, column_count): columns[i] = self._protocol.parse_column(self._socket.recv()) eof = self._handle_eof(self._socket.recv()) return (column_count, columns, eof) def cmd_stmt_prepare(self, statement): """Prepare a MySQL statement This method will send the PREPARE command to MySQL together with the given statement. Returns a dict() """ packet = self._send_cmd(ServerCmd.STMT_PREPARE, statement) result = self._handle_binary_ok(packet) result['columns'] = [] result['parameters'] = [] if result['num_params'] > 0: for _ in xrange(0, result['num_params']): result['parameters'].append( self._protocol.parse_column(self._socket.recv())) self._handle_eof(self._socket.recv()) if result['num_columns'] > 0: for _ in xrange(0, result['num_columns']): result['columns'].append( self._protocol.parse_column(self._socket.recv())) self._handle_eof(self._socket.recv()) return result def cmd_stmt_execute(self, statement_id, data=(), parameters=(), flags=0): """Execute a prepared MySQL statement""" parameters = list(parameters) long_data_used = {} if data: for param_id, _ in enumerate(parameters): if isinstance(data[param_id], (file, StringIO.StringIO, cStringIO.InputType)): binary = True try: binary = 'b' not in data[param_id].mode except AttributeError: pass self.cmd_stmt_send_long_data(statement_id, param_id, data[param_id]) long_data_used[param_id] = (binary,) execute_packet = self._protocol.make_stmt_execute( statement_id, data, tuple(parameters), flags, long_data_used) packet = self._send_cmd(ServerCmd.STMT_EXECUTE, packet=execute_packet) result = self._handle_binary_result(packet) return result def cmd_stmt_close(self, statement_id): """Deallocate a prepared MySQL statement This method deallocates the prepared statement using the statement_id. Note that the MySQL server does not return anything. """ self._send_cmd(ServerCmd.STMT_CLOSE, int4store(statement_id), expect_response=False) def cmd_stmt_send_long_data(self, statement_id, param_id, data): """Send data for a column This methods send data for a column (for example BLOB) for statement identified by statement_id. The param_id indicate which parameter the data belongs too. The data argument should be a file-like object. Since MySQL does not send anything back, no error is raised. When the MySQL server is not reachable, an OperationalError is raised. cmd_stmt_send_long_data should be called before cmd_stmt_execute. The total bytes send is returned. Returns int. """ chunk_size = 8192 total_sent = 0 # pylint: disable = W0212 prepare_packet = self._protocol._prepare_stmt_send_long_data # pylint: enable = W0212 try: buf = data.read(chunk_size) while buf: packet = prepare_packet(statement_id, param_id, buf) self._send_cmd(ServerCmd.STMT_SEND_LONG_DATA, packet=packet, expect_response=False) total_sent += len(buf) buf = data.read(chunk_size) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") return total_sent def cmd_stmt_reset(self, statement_id): """Reset data for prepared statement sent as long data The result is a dictionary with OK packet information. Returns a dict() """ self._handle_ok(self._send_cmd(ServerCmd.STMT_RESET, int4store(statement_id))) mysql-connector-python-1.1.6/python2/mysql/connector/utils.py0000644001577100000120000001770112276514013023724 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Utilities """ __MYSQL_DEBUG__ = False import struct def intread(buf): """Unpacks the given buffer to an integer""" try: if isinstance(buf, int): return buf length = len(buf) if length == 1: return int(ord(buf)) if length <= 4: tmp = buf + '\x00'*(4-length) return struct.unpack(' 255: raise ValueError('int1store requires 0 <= i <= 255') else: return struct.pack(' 65535: raise ValueError('int2store requires 0 <= i <= 65535') else: return struct.pack(' 16777215: raise ValueError('int3store requires 0 <= i <= 16777215') else: return struct.pack(' 4294967295L: raise ValueError('int4store requires 0 <= i <= 4294967295') else: return struct.pack(' 18446744073709551616L: raise ValueError('int4store requires 0 <= i <= 2^64') else: return struct.pack(' 18446744073709551616: raise ValueError('intstore requires 0 <= i <= 2^64') if i <= 255: formed_string = int1store elif i <= 65535: formed_string = int2store elif i <= 16777215: formed_string = int3store elif i <= 4294967295L: formed_string = int4store else: formed_string = int8store return formed_string(i) def read_bytes(buf, size): """ Reads bytes from a buffer. Returns a tuple with buffer less the read bytes, and the bytes. """ res = buf[0:size] return (buf[size:], res) def read_lc_string(buf): """ Takes a buffer and reads a length coded string from the start. This is how Length coded strings work If the string is 250 bytes long or smaller, then it looks like this: <-- 1b --> +----------+------------------------- | length | a string goes here +----------+------------------------- If the string is bigger than 250, then it looks like this: <- 1b -><- 2/3/8 -> +------+-----------+------------------------- | type | length | a string goes here +------+-----------+------------------------- if type == \xfc: length is code in next 2 bytes elif type == \xfd: length is code in next 3 bytes elif type == \xfe: length is code in next 8 bytes NULL has a special value. If the buffer starts with \xfb then it's a NULL and we return None as value. Returns a tuple (trucated buffer, string). """ if buf[0] == '\xfb': # NULL value return (buf[1:], None) length = lsize = 0 fst = ord(buf[0]) if fst <= 250: length = fst return (buf[1 + length:], buf[1:length + 1]) elif fst == 252: lsize = 2 elif fst == 253: lsize = 3 if fst == 254: lsize = 8 length = intread(buf[1:lsize + 1]) return (buf[lsize + length + 1:], buf[lsize + 1:length + lsize + 1]) def read_lc_string_list(buf): """Reads all length encoded strings from the given buffer Returns a list of strings """ strlst = [] pos = 0 len_buf = len(buf) while pos < len_buf: if buf[pos] == '\xfb': # NULL value strlst.append(None) pos += 1 continue elif buf[pos] == '\xff': # Special case when MySQL error (usually 1317) is returned by MySQL. # We simply return None. return None length = lsize = 0 fst = ord(buf[pos]) if fst <= 250: length = fst strlst.append(buf[pos + 1:pos + length + 1]) pos = pos + length + 1 continue if fst == 252: lsize = 2 fmt = ', like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implementing pooling of connections to MySQL servers. """ import re import threading import Queue from uuid import uuid4 from mysql.connector import errors from mysql.connector.connection import MySQLConnection CONNECTION_POOL_LOCK = threading.RLock() CNX_POOL_ARGS = ('pool_name', 'pool_size', 'pool_cnx') CNX_POOL_MAXSIZE = 32 CNX_POOL_MAXNAMESIZE = 64 CNX_POOL_NAMEREGEX = re.compile(r'[^a-zA-Z0-9._\-*$#]') def generate_pool_name(**kwargs): """Generate a pool name This function takes keyword arguments, usually the connection arguments for MySQLConnection, and tries to generate a name for a pool. Raises PoolError when no name can be generated. Returns a string. """ parts = [] for key in ('host', 'port', 'user', 'database'): try: parts.append(str(kwargs[key])) except KeyError: pass if not parts: raise errors.PoolError( "Failed generating pool name; specify pool_name") return '_'.join(parts) class PooledMySQLConnection(object): """Class holding a MySQL Connection in a pool PooledMySQLConnection is used by MySQLConnectionPool to return an instance holding a MySQL connection. It works like a MySQLConnection except for methods like close() and config(). The close()-method will add the connection back to the pool rather than disconnecting from the MySQL server. Configuring the connection have to be done through the MySQLConnectionPool method set_config(). Using config() on pooled connection will raise a PoolError. """ def __init__(self, pool, cnx): """Initialize The pool argument must be an instance of MySQLConnectionPoll. cnx if an instance of MySQLConnection. """ if not isinstance(pool, MySQLConnectionPool): raise AttributeError( "pool should be a MySQLConnectionPool") if not isinstance(cnx, MySQLConnection): raise AttributeError( "cnx should be a MySQLConnection") self._cnx_pool = pool self._cnx = cnx def __getattr__(self, attr): """Calls attributes of the MySQLConnection instance""" return getattr(self._cnx, attr) def close(self): """Do not close, but add connection back to pool The close() method does not close the connection with the MySQL server. The connection is added back to the pool so it can be reused. """ cnx = self._cnx if self._cnx_pool.reset_session: # pylint: disable=W0212 cnx.cmd_change_user(cnx._user, cnx._password, cnx._database, cnx._charset_id) # pylint: enable=W0212 self._cnx_pool.add_connection(cnx) self._cnx = None def config(self, **kwargs): """Configuration is done through the pool""" raise errors.PoolError( "Configuration for pooled connections should " "be done through the pool itself." ) @property def pool_name(self): """Return the name of the connection pool""" return self._cnx_pool.pool_name class MySQLConnectionPool(object): """Class defining a pool of MySQL connections """ def __init__(self, pool_size=5, pool_name=None, pool_reset_session=True, **kwargs): """Initialize Initialize a MySQL connection pool with a maximum number of connections set to pool_size. The rest of the keywords arguments, kwargs, are configuration arguments for MySQLConnection instances. """ self._pool_size = None self._pool_name = None self._reset_session = pool_reset_session self._set_pool_size(pool_size) self._set_pool_name(pool_name or generate_pool_name(**kwargs)) self._cnx_config = {} self._cnx_queue = Queue.Queue(self._pool_size) self._config_version = uuid4() if kwargs: self.set_config(**kwargs) cnt = 0 while cnt < self._pool_size: self.add_connection() cnt += 1 @property def pool_name(self): """Return the name of the connection pool""" return self._pool_name @property def pool_size(self): """Return number of connections managed by the pool""" return self._pool_size @property def reset_session(self): """Return whether to reset session""" return self._reset_session def _set_pool_size(self, pool_size): """Set the size of the pool This method sets the size of the pool but it will not resize the pool. Raises an AttributeError when the pool_size is not valid. Invalid size is 0, negative or higher than pooling.CNX_POOL_MAXSIZE. """ if pool_size <= 0 or pool_size > CNX_POOL_MAXSIZE: raise AttributeError( "Pool size should be higher than 0 and " "lower or equal to {0}".format(CNX_POOL_MAXSIZE)) self._pool_size = pool_size def _set_pool_name(self, pool_name): r"""Set the name of the pool This method checks the validity and sets the name of the pool. Raises an AttributeError when pool_name contains illegal characters ([^a-zA-Z0-9._\-*$#]) or is longer than pooling.CNX_POOL_MAXNAMESIZE. """ if CNX_POOL_NAMEREGEX.search(pool_name): raise AttributeError( "Pool name '{0}' contains illegal characters".format(pool_name)) if len(pool_name) > CNX_POOL_MAXNAMESIZE: raise AttributeError( "Pool name '{0}' is too long".format(pool_name)) self._pool_name = pool_name def set_config(self, **kwargs): """Set the connection configuration for MySQLConnection instances This method sets the configuration used for creating MySQLConnection instances. See MySQLConnection for valid connection arguments. Raises PoolError when a connection argument is not valid, missing or not supported by MySQLConnection. """ if not kwargs: return with CONNECTION_POOL_LOCK: try: test_cnx = MySQLConnection() test_cnx.config(**kwargs) self._cnx_config = kwargs self._config_version = uuid4() except AttributeError as err: raise errors.PoolError( "Connection configuration not valid: {0}".format(err)) def _queue_connection(self, cnx): """Put connection back in the queue This method is putting a connection back in the queue. It will not acquire a lock as the methods using _queue_connection() will have it set. Raises PoolError on errors. """ if not isinstance(cnx, MySQLConnection): raise errors.PoolError( "Connection instance not subclass of MySQLConnection.") try: self._cnx_queue.put(cnx, block=False) except Queue.Full: errors.PoolError("Failed adding connection; queue is full") def add_connection(self, cnx=None): """Add a connection to the pool This method instantiates a MySQLConnection using the configuration passed when initializing the MySQLConnectionPool instance or using the set_config() method. If cnx is a MySQLConnection instance, it will be added to the queue. Raises PoolError when no configuration is set, when no more connection can be added (maximum reached) or when the connection can not be instantiated. """ with CONNECTION_POOL_LOCK: if not self._cnx_config: raise errors.PoolError( "Connection configuration not available") if self._cnx_queue.full(): raise errors.PoolError( "Failed adding connection; queue is full") if not cnx: cnx = MySQLConnection(**self._cnx_config) # pylint: disable=W0212 cnx._pool_config_version = self._config_version # pylint: enable=W0212 else: if not isinstance(cnx, MySQLConnection): raise errors.PoolError( "Connection instance not subclass of MySQLConnection.") self._queue_connection(cnx) def get_connection(self): """Get a connection from the pool This method returns an PooledMySQLConnection instance which has a reference to the pool that created it, and the next available MySQL connection. When the MySQL connection is not connect, a reconnect is attempted. Raises PoolError on errors. Returns a PooledMySQLConnection instance. """ with CONNECTION_POOL_LOCK: try: cnx = self._cnx_queue.get(block=False) except Queue.Empty: raise errors.PoolError( "Failed getting connection; pool exhausted") # pylint: disable=W0212 if (not cnx.is_connected() or self._config_version != cnx._pool_config_version): cnx.config(**self._cnx_config) try: cnx.reconnect() except errors.InterfaceError: # Failed to reconnect, give connection back to pool self._queue_connection(cnx) raise cnx._pool_config_version = self._config_version # pylint: enable=W0212 return PooledMySQLConnection(self, cnx) def _remove_connections(self): """Close all connections This method closes all connections. It returns the number of connections it closed. Used mostly for tests. Returns int. """ with CONNECTION_POOL_LOCK: cnt = 0 cnxq = self._cnx_queue while cnxq.qsize(): try: cnx = cnxq.get(block=False) cnx.disconnect() cnt += 1 except Queue.Empty: return cnt except errors.PoolError: raise except errors.Error: # Any other error when closing means connection is closed pass return cnt mysql-connector-python-1.1.6/python2/mysql/connector/version.py0000644001577100000120000000303012276514013024237 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """MySQL Connector/Python version information The file version.py gets installed and is available after installation as mysql.connector.version. """ VERSION = (1, 1, 6, '', 0) if VERSION[3] and VERSION[4]: VERSION_TEXT = '{0}.{1}.{2}{3}{4}'.format(*VERSION) else: VERSION_TEXT = '{0}.{1}.{2}'.format(*VERSION[0:3]) LICENSE = 'GPLv2 with FOSS License Exception' EDITION = '' # Added in package names, after the version mysql-connector-python-1.1.6/python2/mysql/connector/protocol.py0000644001577100000120000005515012276514013024425 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implements the MySQL Client/Server protocol """ import struct import datetime from decimal import Decimal try: from hashlib import sha1 except ImportError: from sha import new as sha1 from mysql.connector.constants import (FieldFlag, ServerCmd, FieldType) from mysql.connector import (errors, utils) class MySQLProtocol(object): """ Implemets MySQL client/server protocol. Creates and parse packets based on MySQL client/server protocol. """ def _scramble_password(self, passwd, seed): """Scramble a password ready to send to MySQL""" hash4 = None try: hash1 = sha1(passwd).digest() hash2 = sha1(hash1).digest() # Password as found in mysql.user() hash3 = sha1(seed + hash2).digest() xored = [utils.intread(h1) ^ utils.intread(h3) for (h1, h3) in zip(hash1, hash3)] hash4 = struct.pack('20B', *xored) except Exception as err: raise errors.InterfaceError( 'Failed scrambling password; %s' % err) return hash4 def _prepare_auth(self, usr, pwd, dbname, flags, seed): """Prepare elements of the authentication packet""" if usr is not None and len(usr) > 0: if isinstance(usr, unicode): usr = usr.encode('utf8') _username = usr + '\x00' else: _username = '\x00' if pwd is not None and len(pwd) > 0: if isinstance(pwd, unicode): pwd = pwd.encode('utf8') _password = utils.int1store(20) +\ self._scramble_password(pwd, seed) else: _password = '\x00' if dbname is not None and len(dbname): _database = dbname.encode('utf8') + '\x00' else: _database = '\x00' return (_username, _password, _database) def make_auth(self, seed, username=None, password=None, database=None, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a MySQL Authentication packet""" if not seed: raise errors.ProgrammingError('Seed missing') auth = self._prepare_auth(username, password, database, client_flags, seed) return utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ '\x00' * 23 + auth[0] + auth[1] + auth[2] def make_auth_ssl(self, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a SSL authentication packet""" return utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ '\x00' * 23 def make_command(self, command, argument=None): """Make a MySQL packet containing a command""" data = utils.int1store(command) if argument is not None: data += str(argument) return data def make_change_user(self, seed, username=None, password=None, database=None, charset=33, client_flags=0): """Make a MySQL packet with the Change User command""" if not seed: raise errors.ProgrammingError('Seed missing') auth = self._prepare_auth(username, password, database, client_flags, seed) data = utils.int1store(ServerCmd.CHANGE_USER) +\ auth[0] + auth[1] + auth[2] + utils.int2store(charset) return data def parse_handshake(self, packet): """Parse a MySQL Handshake-packet""" res = {} (packet, res['protocol']) = utils.read_int(packet[4:], 1) (packet, res['server_version_original']) = utils.read_string( packet, end='\x00') (packet, res['server_threadid']) = utils.read_int(packet, 4) (packet, res['scramble']) = utils.read_bytes(packet, 8) packet = packet[1:] # Filler 1 * \x00 (packet, res['capabilities']) = utils.read_int(packet, 2) (packet, res['charset']) = utils.read_int(packet, 1) (packet, res['server_status']) = utils.read_int(packet, 2) packet = packet[13:] # Filler 13 * \x00 (packet, scramble_next) = utils.read_bytes(packet, 12) res['scramble'] += scramble_next return res def parse_ok(self, packet): """Parse a MySQL OK-packet""" if not packet[4] == '\x00': raise errors.InterfaceError("Failed parsing OK packet.") ok_packet = {} try: ok_packet['field_count'] = struct.unpack('= 7: mcs = 0 if length == 11: mcs = struct.unpack('I', packet[8:length + 1])[0] value = datetime.datetime( year=struct.unpack('H', packet[1:3])[0], month=ord(packet[3]), day=ord(packet[4]), hour=ord(packet[5]), minute=ord(packet[6]), second=ord(packet[7]), microsecond=mcs) return (packet[length + 1:], value) def _parse_binary_time(self, packet, field): """Parse a time value from a binary packet""" length = ord(packet[0]) data = packet[1:length + 1] mcs = 0 if length > 8: mcs = struct.unpack('I', data[8:])[0] days = struct.unpack('I', data[1:5])[0] if int(ord(data[0])) == 1: days *= -1 tmp = datetime.timedelta(days=days, seconds=int(ord(data[7])), microseconds=mcs, minutes=int(ord(data[6])), hours=int(ord(data[5]))) return (packet[length + 1:], tmp) def _parse_binary_values(self, fields, packet): """Parse values from a binary result packet""" null_bitmap_length = (len(fields) + 7 + 2) // 8 null_bitmap = utils.intread(packet[0:null_bitmap_length]) packet = packet[null_bitmap_length:] values = [] for pos, field in enumerate(fields): if null_bitmap & 1 << (pos + 2): values.append(None) continue elif field[1] in (FieldType.TINY, FieldType.SHORT, FieldType.INT24, FieldType.LONG, FieldType.LONGLONG): (packet, value) = self._parse_binary_integer(packet, field) values.append(value) elif field[1] in (FieldType.DOUBLE, FieldType.FLOAT): (packet, value) = self._parse_binary_float(packet, field) values.append(value) elif field[1] in (FieldType.DATETIME, FieldType.DATE, FieldType.TIMESTAMP): (packet, value) = self._parse_binary_timestamp(packet, field) values.append(value) elif field[1] == FieldType.TIME: (packet, value) = self._parse_binary_time(packet, field) values.append(value) else: (packet, value) = utils.read_lc_string(packet) values.append(value) return tuple(values) def read_binary_result(self, sock, columns, count=1): """Read MySQL binary protocol result Reads all or given number of binary resultset rows from the socket. """ rows = [] eof = None values = None i = 0 while True: if eof is not None: break if i == count: break packet = sock.recv() if packet[4] == '\xfe': eof = self.parse_eof(packet) values = None elif packet[4] == '\x00': eof = None values = self._parse_binary_values(columns, packet[5:]) if eof is None and values is not None: rows.append(values) i += 1 return (rows, eof) def parse_binary_prepare_ok(self, packet): """Parse a MySQL Binary Protocol OK packet""" if not packet[4] == '\x00': raise errors.InterfaceError("Failed parsing Binary OK packet") ok_packet = {} try: (packet, ok_packet['statement_id']) = utils.read_int(packet[5:], 4) (packet, ok_packet['num_columns']) = utils.read_int(packet, 2) (packet, ok_packet['num_params']) = utils.read_int(packet, 2) packet = packet[1:] # Filler 1 * \x00 (packet, ok_packet['warning_count']) = utils.read_int(packet, 2) except ValueError: raise errors.InterfaceError("Failed parsing Binary OK packet") return ok_packet def _prepare_binary_integer(self, value): """Prepare an integer for the MySQL binary protocol""" field_type = None flags = 0 if value < 0: if value >= -128: format_ = 'b' field_type = FieldType.TINY elif value >= -32768: format_ = 'h' field_type = FieldType.SHORT elif value >= -2147483648: format_ = 'i' field_type = FieldType.LONG else: format_ = 'q' field_type = FieldType.LONGLONG else: flags = 128 if value <= 255: format_ = 'B' field_type = FieldType.TINY elif value <= 65535: format_ = 'H' field_type = FieldType.SHORT elif value <= 4294967295: format_ = 'I' field_type = FieldType.LONG else: field_type = FieldType.LONGLONG format_ = 'Q' return (struct.pack(format_, value), field_type, flags) def _prepare_binary_timestamp(self, value): """Prepare a timestamp object for the MySQL binary protocol This method prepares a timestamp of type datetime.datetime or datetime.date for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if isinstance(value, datetime.datetime): field_type = FieldType.DATETIME elif isinstance(value, datetime.date): field_type = FieldType.DATE else: raise ValueError( "Argument must a datetime.datetime or datetime.date") packed = (utils.int2store(value.year) + utils.int1store(value.month) + utils.int1store(value.day)) if isinstance(value, datetime.datetime): packed = (packed + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) if value.microsecond > 0: packed += utils.int4store(value.microsecond) packed = utils.int1store(len(packed)) + packed return (packed, field_type) def _prepare_binary_time(self, value): """Prepare a time object for the MySQL binary protocol This method prepares a time object of type datetime.timedelta or datetime.time for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if not isinstance(value, (datetime.timedelta, datetime.time)): raise ValueError( "Argument must a datetime.timedelta or datetime.time") field_type = FieldType.TIME negative = 0 mcs = None packed = '' if isinstance(value, datetime.timedelta): if value.days < 0: negative = 1 (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) packed += (utils.int4store(abs(value.days)) + utils.int1store(hours) + utils.int1store(mins) + utils.int1store(secs)) mcs = value.microseconds else: packed += (utils.int4store(0) + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) mcs = value.microsecond if mcs: packed += utils.int4store(mcs) packed = utils.int1store(negative) + packed packed = utils.int1store(len(packed)) + packed return (packed, field_type) def _prepare_stmt_send_long_data(self, statement, param, data): """Prepare long data for prepared statments Returns a string. """ packet = ( utils.int4store(statement) + utils.int2store(param) + data) return packet def make_stmt_execute(self, statement_id, data=(), parameters=(), flags=0, long_data_used=None): """Make a MySQL packet with the Statement Execute command""" iteration_count = 1 null_bitmap = [0] * ((len(data) + 7) // 8) values = [] types = [] packed = '' if long_data_used is None: long_data_used = {} if parameters and data: if len(data) != len(parameters): raise errors.InterfaceError( "Failed executing prepared statement: data values does not" " match number of parameters") for pos, _ in enumerate(parameters): value = data[pos] flags = 0 if value is None: null_bitmap[(pos // 8)] |= 1 << (pos % 8) continue elif pos in long_data_used: if long_data_used[pos][0]: # We suppose binary data field_type = FieldType.BLOB else: # We suppose text data field_type = FieldType.STRING elif isinstance(value, (int, long)): (packed, field_type, flags) = self._prepare_binary_integer(value) values.append(packed) elif isinstance(value, str): values.append(utils.intstore(len(value)) + value) field_type = FieldType.VARCHAR elif isinstance(value, Decimal): values.append(utils.intstore(len(str(value))) + str(value)) field_type = FieldType.DECIMAL elif isinstance(value, float): values.append(struct.pack('d', value)) field_type = FieldType.DOUBLE elif isinstance(value, (datetime.datetime, datetime.date)): (packed, field_type) = self._prepare_binary_timestamp( value) values.append(packed) elif isinstance(value, (datetime.timedelta, datetime.time)): (packed, field_type) = self._prepare_binary_time(value) values.append(packed) else: raise errors.ProgrammingError( "MySQL binary protocol can not handle " "'{classname}' objects".format( classname=value.__class__.__name__)) types.append(utils.int1store(field_type) + utils.int1store(flags)) packet = ( utils.int4store(statement_id), utils.int1store(flags), utils.int4store(iteration_count), ''.join([struct.pack('B', bit) for bit in null_bitmap]), utils.int1store(1), ''.join(types), ''.join(values) ) return ''.join(packet) mysql-connector-python-1.1.6/python2/mysql/connector/charsets.py0000644001577100000120000002760712276514013024406 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. # GENERATED_ON = '2013-12-18' # MYSQL_VERSION = (5, 7, 2) """This module contains the MySQL Server Character Sets""" MYSQL_CHARACTER_SETS = [ # (character set name, collation, default) None, ("big5", "big5_chinese_ci", True), # 1 ("latin2", "latin2_czech_cs", False), # 2 ("dec8", "dec8_swedish_ci", True), # 3 ("cp850", "cp850_general_ci", True), # 4 ("latin1", "latin1_german1_ci", False), # 5 ("hp8", "hp8_english_ci", True), # 6 ("koi8r", "koi8r_general_ci", True), # 7 ("latin1", "latin1_swedish_ci", True), # 8 ("latin2", "latin2_general_ci", True), # 9 ("swe7", "swe7_swedish_ci", True), # 10 ("ascii", "ascii_general_ci", True), # 11 ("ujis", "ujis_japanese_ci", True), # 12 ("sjis", "sjis_japanese_ci", True), # 13 ("cp1251", "cp1251_bulgarian_ci", False), # 14 ("latin1", "latin1_danish_ci", False), # 15 ("hebrew", "hebrew_general_ci", True), # 16 None, ("tis620", "tis620_thai_ci", True), # 18 ("euckr", "euckr_korean_ci", True), # 19 ("latin7", "latin7_estonian_cs", False), # 20 ("latin2", "latin2_hungarian_ci", False), # 21 ("koi8u", "koi8u_general_ci", True), # 22 ("cp1251", "cp1251_ukrainian_ci", False), # 23 ("gb2312", "gb2312_chinese_ci", True), # 24 ("greek", "greek_general_ci", True), # 25 ("cp1250", "cp1250_general_ci", True), # 26 ("latin2", "latin2_croatian_ci", False), # 27 ("gbk", "gbk_chinese_ci", True), # 28 ("cp1257", "cp1257_lithuanian_ci", False), # 29 ("latin5", "latin5_turkish_ci", True), # 30 ("latin1", "latin1_german2_ci", False), # 31 ("armscii8", "armscii8_general_ci", True), # 32 ("utf8", "utf8_general_ci", True), # 33 ("cp1250", "cp1250_czech_cs", False), # 34 ("ucs2", "ucs2_general_ci", True), # 35 ("cp866", "cp866_general_ci", True), # 36 ("keybcs2", "keybcs2_general_ci", True), # 37 ("macce", "macce_general_ci", True), # 38 ("macroman", "macroman_general_ci", True), # 39 ("cp852", "cp852_general_ci", True), # 40 ("latin7", "latin7_general_ci", True), # 41 ("latin7", "latin7_general_cs", False), # 42 ("macce", "macce_bin", False), # 43 ("cp1250", "cp1250_croatian_ci", False), # 44 ("utf8mb4", "utf8mb4_general_ci", True), # 45 ("utf8mb4", "utf8mb4_bin", False), # 46 ("latin1", "latin1_bin", False), # 47 ("latin1", "latin1_general_ci", False), # 48 ("latin1", "latin1_general_cs", False), # 49 ("cp1251", "cp1251_bin", False), # 50 ("cp1251", "cp1251_general_ci", True), # 51 ("cp1251", "cp1251_general_cs", False), # 52 ("macroman", "macroman_bin", False), # 53 ("utf16", "utf16_general_ci", True), # 54 ("utf16", "utf16_bin", False), # 55 ("utf16le", "utf16le_general_ci", True), # 56 ("cp1256", "cp1256_general_ci", True), # 57 ("cp1257", "cp1257_bin", False), # 58 ("cp1257", "cp1257_general_ci", True), # 59 ("utf32", "utf32_general_ci", True), # 60 ("utf32", "utf32_bin", False), # 61 ("utf16le", "utf16le_bin", False), # 62 ("binary", "binary", True), # 63 ("armscii8", "armscii8_bin", False), # 64 ("ascii", "ascii_bin", False), # 65 ("cp1250", "cp1250_bin", False), # 66 ("cp1256", "cp1256_bin", False), # 67 ("cp866", "cp866_bin", False), # 68 ("dec8", "dec8_bin", False), # 69 ("greek", "greek_bin", False), # 70 ("hebrew", "hebrew_bin", False), # 71 ("hp8", "hp8_bin", False), # 72 ("keybcs2", "keybcs2_bin", False), # 73 ("koi8r", "koi8r_bin", False), # 74 ("koi8u", "koi8u_bin", False), # 75 None, ("latin2", "latin2_bin", False), # 77 ("latin5", "latin5_bin", False), # 78 ("latin7", "latin7_bin", False), # 79 ("cp850", "cp850_bin", False), # 80 ("cp852", "cp852_bin", False), # 81 ("swe7", "swe7_bin", False), # 82 ("utf8", "utf8_bin", False), # 83 ("big5", "big5_bin", False), # 84 ("euckr", "euckr_bin", False), # 85 ("gb2312", "gb2312_bin", False), # 86 ("gbk", "gbk_bin", False), # 87 ("sjis", "sjis_bin", False), # 88 ("tis620", "tis620_bin", False), # 89 ("ucs2", "ucs2_bin", False), # 90 ("ujis", "ujis_bin", False), # 91 ("geostd8", "geostd8_general_ci", True), # 92 ("geostd8", "geostd8_bin", False), # 93 ("latin1", "latin1_spanish_ci", False), # 94 ("cp932", "cp932_japanese_ci", True), # 95 ("cp932", "cp932_bin", False), # 96 ("eucjpms", "eucjpms_japanese_ci", True), # 97 ("eucjpms", "eucjpms_bin", False), # 98 ("cp1250", "cp1250_polish_ci", False), # 99 None, ("utf16", "utf16_unicode_ci", False), # 101 ("utf16", "utf16_icelandic_ci", False), # 102 ("utf16", "utf16_latvian_ci", False), # 103 ("utf16", "utf16_romanian_ci", False), # 104 ("utf16", "utf16_slovenian_ci", False), # 105 ("utf16", "utf16_polish_ci", False), # 106 ("utf16", "utf16_estonian_ci", False), # 107 ("utf16", "utf16_spanish_ci", False), # 108 ("utf16", "utf16_swedish_ci", False), # 109 ("utf16", "utf16_turkish_ci", False), # 110 ("utf16", "utf16_czech_ci", False), # 111 ("utf16", "utf16_danish_ci", False), # 112 ("utf16", "utf16_lithuanian_ci", False), # 113 ("utf16", "utf16_slovak_ci", False), # 114 ("utf16", "utf16_spanish2_ci", False), # 115 ("utf16", "utf16_roman_ci", False), # 116 ("utf16", "utf16_persian_ci", False), # 117 ("utf16", "utf16_esperanto_ci", False), # 118 ("utf16", "utf16_hungarian_ci", False), # 119 ("utf16", "utf16_sinhala_ci", False), # 120 ("utf16", "utf16_german2_ci", False), # 121 ("utf16", "utf16_croatian_ci", False), # 122 ("utf16", "utf16_unicode_520_ci", False), # 123 ("utf16", "utf16_vietnamese_ci", False), # 124 None, None, None, ("ucs2", "ucs2_unicode_ci", False), # 128 ("ucs2", "ucs2_icelandic_ci", False), # 129 ("ucs2", "ucs2_latvian_ci", False), # 130 ("ucs2", "ucs2_romanian_ci", False), # 131 ("ucs2", "ucs2_slovenian_ci", False), # 132 ("ucs2", "ucs2_polish_ci", False), # 133 ("ucs2", "ucs2_estonian_ci", False), # 134 ("ucs2", "ucs2_spanish_ci", False), # 135 ("ucs2", "ucs2_swedish_ci", False), # 136 ("ucs2", "ucs2_turkish_ci", False), # 137 ("ucs2", "ucs2_czech_ci", False), # 138 ("ucs2", "ucs2_danish_ci", False), # 139 ("ucs2", "ucs2_lithuanian_ci", False), # 140 ("ucs2", "ucs2_slovak_ci", False), # 141 ("ucs2", "ucs2_spanish2_ci", False), # 142 ("ucs2", "ucs2_roman_ci", False), # 143 ("ucs2", "ucs2_persian_ci", False), # 144 ("ucs2", "ucs2_esperanto_ci", False), # 145 ("ucs2", "ucs2_hungarian_ci", False), # 146 ("ucs2", "ucs2_sinhala_ci", False), # 147 ("ucs2", "ucs2_german2_ci", False), # 148 ("ucs2", "ucs2_croatian_ci", False), # 149 ("ucs2", "ucs2_unicode_520_ci", False), # 150 ("ucs2", "ucs2_vietnamese_ci", False), # 151 None, None, None, None, None, None, None, ("ucs2", "ucs2_general_mysql500_ci", False), # 159 ("utf32", "utf32_unicode_ci", False), # 160 ("utf32", "utf32_icelandic_ci", False), # 161 ("utf32", "utf32_latvian_ci", False), # 162 ("utf32", "utf32_romanian_ci", False), # 163 ("utf32", "utf32_slovenian_ci", False), # 164 ("utf32", "utf32_polish_ci", False), # 165 ("utf32", "utf32_estonian_ci", False), # 166 ("utf32", "utf32_spanish_ci", False), # 167 ("utf32", "utf32_swedish_ci", False), # 168 ("utf32", "utf32_turkish_ci", False), # 169 ("utf32", "utf32_czech_ci", False), # 170 ("utf32", "utf32_danish_ci", False), # 171 ("utf32", "utf32_lithuanian_ci", False), # 172 ("utf32", "utf32_slovak_ci", False), # 173 ("utf32", "utf32_spanish2_ci", False), # 174 ("utf32", "utf32_roman_ci", False), # 175 ("utf32", "utf32_persian_ci", False), # 176 ("utf32", "utf32_esperanto_ci", False), # 177 ("utf32", "utf32_hungarian_ci", False), # 178 ("utf32", "utf32_sinhala_ci", False), # 179 ("utf32", "utf32_german2_ci", False), # 180 ("utf32", "utf32_croatian_ci", False), # 181 ("utf32", "utf32_unicode_520_ci", False), # 182 ("utf32", "utf32_vietnamese_ci", False), # 183 None, None, None, None, None, None, None, None, ("utf8", "utf8_unicode_ci", False), # 192 ("utf8", "utf8_icelandic_ci", False), # 193 ("utf8", "utf8_latvian_ci", False), # 194 ("utf8", "utf8_romanian_ci", False), # 195 ("utf8", "utf8_slovenian_ci", False), # 196 ("utf8", "utf8_polish_ci", False), # 197 ("utf8", "utf8_estonian_ci", False), # 198 ("utf8", "utf8_spanish_ci", False), # 199 ("utf8", "utf8_swedish_ci", False), # 200 ("utf8", "utf8_turkish_ci", False), # 201 ("utf8", "utf8_czech_ci", False), # 202 ("utf8", "utf8_danish_ci", False), # 203 ("utf8", "utf8_lithuanian_ci", False), # 204 ("utf8", "utf8_slovak_ci", False), # 205 ("utf8", "utf8_spanish2_ci", False), # 206 ("utf8", "utf8_roman_ci", False), # 207 ("utf8", "utf8_persian_ci", False), # 208 ("utf8", "utf8_esperanto_ci", False), # 209 ("utf8", "utf8_hungarian_ci", False), # 210 ("utf8", "utf8_sinhala_ci", False), # 211 ("utf8", "utf8_german2_ci", False), # 212 ("utf8", "utf8_croatian_ci", False), # 213 ("utf8", "utf8_unicode_520_ci", False), # 214 ("utf8", "utf8_vietnamese_ci", False), # 215 None, None, None, None, None, None, None, ("utf8", "utf8_general_mysql500_ci", False), # 223 ("utf8mb4", "utf8mb4_unicode_ci", False), # 224 ("utf8mb4", "utf8mb4_icelandic_ci", False), # 225 ("utf8mb4", "utf8mb4_latvian_ci", False), # 226 ("utf8mb4", "utf8mb4_romanian_ci", False), # 227 ("utf8mb4", "utf8mb4_slovenian_ci", False), # 228 ("utf8mb4", "utf8mb4_polish_ci", False), # 229 ("utf8mb4", "utf8mb4_estonian_ci", False), # 230 ("utf8mb4", "utf8mb4_spanish_ci", False), # 231 ("utf8mb4", "utf8mb4_swedish_ci", False), # 232 ("utf8mb4", "utf8mb4_turkish_ci", False), # 233 ("utf8mb4", "utf8mb4_czech_ci", False), # 234 ("utf8mb4", "utf8mb4_danish_ci", False), # 235 ("utf8mb4", "utf8mb4_lithuanian_ci", False), # 236 ("utf8mb4", "utf8mb4_slovak_ci", False), # 237 ("utf8mb4", "utf8mb4_spanish2_ci", False), # 238 ("utf8mb4", "utf8mb4_roman_ci", False), # 239 ("utf8mb4", "utf8mb4_persian_ci", False), # 240 ("utf8mb4", "utf8mb4_esperanto_ci", False), # 241 ("utf8mb4", "utf8mb4_hungarian_ci", False), # 242 ("utf8mb4", "utf8mb4_sinhala_ci", False), # 243 ("utf8mb4", "utf8mb4_german2_ci", False), # 244 ("utf8mb4", "utf8mb4_croatian_ci", False), # 245 ("utf8mb4", "utf8mb4_unicode_520_ci", False), # 246 ("utf8mb4", "utf8mb4_vietnamese_ci", False), # 247 ] mysql-connector-python-1.1.6/python2/mysql/connector/constants.py0000644001577100000120000005463512276514013024607 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Various MySQL constants and character sets """ from mysql.connector.errors import ProgrammingError from mysql.connector.charsets import MYSQL_CHARACTER_SETS MAX_PACKET_LENGTH = 16777215 NET_BUFFER_LENGTH = 8192 RESULT_WITHOUT_ROWS = 0 RESULT_WITH_ROWS = 1 def flag_is_set(flag, flags): """Checks if the flag is set Returns boolean""" if (flags & flag) > 0: return True return False class _Constants(object): """Base class for constants """ prefix = '' desc = {} def __new__(cls): raise TypeError("Can not instanciate from %s" % cls.__name__) @classmethod def get_desc(cls, name): """Get description of given constant""" try: return cls.desc[name][1] except: return None @classmethod def get_info(cls, num): """Get information about given constant""" for name, info in cls.desc.items(): if info[0] == num: return name return None @classmethod def get_full_info(cls): """Get full information about given constant""" res = () try: res = ["%s : %s" % (k, v[1]) for k, v in cls.desc.items()] except StandardError as err: res = ('No information found in constant class.%s' % err) return res class _Flags(_Constants): """Base class for classes describing flags """ @classmethod def get_bit_info(cls, value): """Get the name of all bits set Returns a list of strings.""" res = [] for name, info in cls.desc.items(): if value & info[0]: res.append(name) return res class FieldType(_Constants): """MySQL Field Types """ prefix = 'FIELD_TYPE_' DECIMAL = 0x00 TINY = 0x01 SHORT = 0x02 LONG = 0x03 FLOAT = 0x04 DOUBLE = 0x05 NULL = 0x06 TIMESTAMP = 0x07 LONGLONG = 0x08 INT24 = 0x09 DATE = 0x0a TIME = 0x0b DATETIME = 0x0c YEAR = 0x0d NEWDATE = 0x0e VARCHAR = 0x0f BIT = 0x10 NEWDECIMAL = 0xf6 ENUM = 0xf7 SET = 0xf8 TINY_BLOB = 0xf9 MEDIUM_BLOB = 0xfa LONG_BLOB = 0xfb BLOB = 0xfc VAR_STRING = 0xfd STRING = 0xfe GEOMETRY = 0xff desc = { 'DECIMAL': (0x00, 'DECIMAL'), 'TINY': (0x01, 'TINY'), 'SHORT': (0x02, 'SHORT'), 'LONG': (0x03, 'LONG'), 'FLOAT': (0x04, 'FLOAT'), 'DOUBLE': (0x05, 'DOUBLE'), 'NULL': (0x06, 'NULL'), 'TIMESTAMP': (0x07, 'TIMESTAMP'), 'LONGLONG': (0x08, 'LONGLONG'), 'INT24': (0x09, 'INT24'), 'DATE': (0x0a, 'DATE'), 'TIME': (0x0b, 'TIME'), 'DATETIME': (0x0c, 'DATETIME'), 'YEAR': (0x0d, 'YEAR'), 'NEWDATE': (0x0e, 'NEWDATE'), 'VARCHAR': (0x0f, 'VARCHAR'), 'BIT': (0x10, 'BIT'), 'NEWDECIMAL': (0xf6, 'NEWDECIMAL'), 'ENUM': (0xf7, 'ENUM'), 'SET': (0xf8, 'SET'), 'TINY_BLOB': (0xf9, 'TINY_BLOB'), 'MEDIUM_BLOB': (0xfa, 'MEDIUM_BLOB'), 'LONG_BLOB': (0xfb, 'LONG_BLOB'), 'BLOB': (0xfc, 'BLOB'), 'VAR_STRING': (0xfd, 'VAR_STRING'), 'STRING': (0xfe, 'STRING'), 'GEOMETRY': (0xff, 'GEOMETRY'), } @classmethod def get_string_types(cls): """Get the list of all string types""" return [ cls.VARCHAR, cls.ENUM, cls.VAR_STRING, cls.STRING, ] @classmethod def get_binary_types(cls): """Get the list of all binary types""" return [ cls.TINY_BLOB, cls.MEDIUM_BLOB, cls.LONG_BLOB, cls.BLOB, ] @classmethod def get_number_types(cls): """Get the list of all number types""" return [ cls.DECIMAL, cls.NEWDECIMAL, cls.TINY, cls.SHORT, cls.LONG, cls.FLOAT, cls.DOUBLE, cls.LONGLONG, cls.INT24, cls.BIT, cls.YEAR, ] @classmethod def get_timestamp_types(cls): """Get the list of all timestamp types""" return [ cls.DATETIME, cls.TIMESTAMP, ] class FieldFlag(_Flags): """MySQL Field Flags Field flags as found in MySQL sources mysql-src/include/mysql_com.h """ _prefix = '' NOT_NULL = 1 << 0 PRI_KEY = 1 << 1 UNIQUE_KEY = 1 << 2 MULTIPLE_KEY = 1 << 3 BLOB = 1 << 4 UNSIGNED = 1 << 5 ZEROFILL = 1 << 6 BINARY = 1 << 7 ENUM = 1 << 8 AUTO_INCREMENT = 1 << 9 TIMESTAMP = 1 << 10 SET = 1 << 11 NO_DEFAULT_VALUE = 1 << 12 ON_UPDATE_NOW = 1 << 13 NUM = 1 << 14 PART_KEY = 1 << 15 GROUP = 1 << 14 # SAME AS NUM !!!!!!!???? UNIQUE = 1 << 16 BINCMP = 1 << 17 GET_FIXED_FIELDS = 1 << 18 FIELD_IN_PART_FUNC = 1 << 19 FIELD_IN_ADD_INDEX = 1 << 20 FIELD_IS_RENAMED = 1 << 21 desc = { 'NOT_NULL': (1 << 0, "Field can't be NULL"), 'PRI_KEY': (1 << 1, "Field is part of a primary key"), 'UNIQUE_KEY': (1 << 2, "Field is part of a unique key"), 'MULTIPLE_KEY': (1 << 3, "Field is part of a key"), 'BLOB': (1 << 4, "Field is a blob"), 'UNSIGNED': (1 << 5, "Field is unsigned"), 'ZEROFILL': (1 << 6, "Field is zerofill"), 'BINARY': (1 << 7, "Field is binary "), 'ENUM': (1 << 8, "field is an enum"), 'AUTO_INCREMENT': (1 << 9, "field is a autoincrement field"), 'TIMESTAMP': (1 << 10, "Field is a timestamp"), 'SET': (1 << 11, "field is a set"), 'NO_DEFAULT_VALUE': (1 << 12, "Field doesn't have default value"), 'ON_UPDATE_NOW': (1 << 13, "Field is set to NOW on UPDATE"), 'NUM': (1 << 14, "Field is num (for clients)"), 'PART_KEY': (1 << 15, "Intern; Part of some key"), 'GROUP': (1 << 14, "Intern: Group field"), # Same as NUM 'UNIQUE': (1 << 16, "Intern: Used by sql_yacc"), 'BINCMP': (1 << 17, "Intern: Used by sql_yacc"), 'GET_FIXED_FIELDS': (1 << 18, "Used to get fields in item tree"), 'FIELD_IN_PART_FUNC': (1 << 19, "Field part of partition func"), 'FIELD_IN_ADD_INDEX': (1 << 20, "Intern: Field used in ADD INDEX"), 'FIELD_IS_RENAMED': (1 << 21, "Intern: Field is being renamed"), } class ServerCmd(_Constants): """MySQL Server Commands """ _prefix = 'COM_' SLEEP = 0 QUIT = 1 INIT_DB = 2 QUERY = 3 FIELD_LIST = 4 CREATE_DB = 5 DROP_DB = 6 REFRESH = 7 SHUTDOWN = 8 STATISTICS = 9 PROCESS_INFO = 10 CONNECT = 11 PROCESS_KILL = 12 DEBUG = 13 PING = 14 TIME = 15 DELAYED_INSERT = 16 CHANGE_USER = 17 BINLOG_DUMP = 18 TABLE_DUMP = 19 CONNECT_OUT = 20 REGISTER_SLAVE = 21 STMT_PREPARE = 22 STMT_EXECUTE = 23 STMT_SEND_LONG_DATA = 24 STMT_CLOSE = 25 STMT_RESET = 26 SET_OPTION = 27 STMT_FETCH = 28 DAEMON = 29 desc = { 'SLEEP': (0, 'SLEEP'), 'QUIT': (1, 'QUIT'), 'INIT_DB': (2, 'INIT_DB'), 'QUERY': (3, 'QUERY'), 'FIELD_LIST': (4, 'FIELD_LIST'), 'CREATE_DB': (5, 'CREATE_DB'), 'DROP_DB': (6, 'DROP_DB'), 'REFRESH': (7, 'REFRESH'), 'SHUTDOWN': (8, 'SHUTDOWN'), 'STATISTICS': (9, 'STATISTICS'), 'PROCESS_INFO': (10, 'PROCESS_INFO'), 'CONNECT': (11, 'CONNECT'), 'PROCESS_KILL': (12, 'PROCESS_KILL'), 'DEBUG': (13, 'DEBUG'), 'PING': (14, 'PING'), 'TIME': (15, 'TIME'), 'DELAYED_INSERT': (16, 'DELAYED_INSERT'), 'CHANGE_USER': (17, 'CHANGE_USER'), 'BINLOG_DUMP': (18, 'BINLOG_DUMP'), 'TABLE_DUMP': (19, 'TABLE_DUMP'), 'CONNECT_OUT': (20, 'CONNECT_OUT'), 'REGISTER_SLAVE': (21, 'REGISTER_SLAVE'), 'STMT_PREPARE': (22, 'STMT_PREPARE'), 'STMT_EXECUTE': (23, 'STMT_EXECUTE'), 'STMT_SEND_LONG_DATA': (24, 'STMT_SEND_LONG_DATA'), 'STMT_CLOSE': (25, 'STMT_CLOSE'), 'STMT_RESET': (26, 'STMT_RESET'), 'SET_OPTION': (27, 'SET_OPTION'), 'STMT_FETCH': (28, 'STMT_FETCH'), 'DAEMON': (29, 'DAEMON'), } class ClientFlag(_Flags): """MySQL Client Flags Client options as found in the MySQL sources mysql-src/include/mysql_com.h """ LONG_PASSWD = 1 << 0 FOUND_ROWS = 1 << 1 LONG_FLAG = 1 << 2 CONNECT_WITH_DB = 1 << 3 NO_SCHEMA = 1 << 4 COMPRESS = 1 << 5 ODBC = 1 << 6 LOCAL_FILES = 1 << 7 IGNORE_SPACE = 1 << 8 PROTOCOL_41 = 1 << 9 INTERACTIVE = 1 << 10 SSL = 1 << 11 IGNORE_SIGPIPE = 1 << 12 TRANSACTIONS = 1 << 13 RESERVED = 1 << 14 SECURE_CONNECTION = 1 << 15 MULTI_STATEMENTS = 1 << 16 MULTI_RESULTS = 1 << 17 SSL_VERIFY_SERVER_CERT = 1 << 30 REMEMBER_OPTIONS = 1 << 31 desc = { 'LONG_PASSWD': (1 << 0, 'New more secure passwords'), 'FOUND_ROWS': (1 << 1, 'Found instead of affected rows'), 'LONG_FLAG': (1 << 2, 'Get all column flags'), 'CONNECT_WITH_DB': (1 << 3, 'One can specify db on connect'), 'NO_SCHEMA': (1 << 4, "Don't allow database.table.column"), 'COMPRESS': (1 << 5, 'Can use compression protocol'), 'ODBC': (1 << 6, 'ODBC client'), 'LOCAL_FILES': (1 << 7, 'Can use LOAD DATA LOCAL'), 'IGNORE_SPACE': (1 << 8, "Ignore spaces before ''"), 'PROTOCOL_41': (1 << 9, 'New 4.1 protocol'), 'INTERACTIVE': (1 << 10, 'This is an interactive client'), 'SSL': (1 << 11, 'Switch to SSL after handshake'), 'IGNORE_SIGPIPE': (1 << 12, 'IGNORE sigpipes'), 'TRANSACTIONS': (1 << 13, 'Client knows about transactions'), 'RESERVED': (1 << 14, 'Old flag for 4.1 protocol'), 'SECURE_CONNECTION': (1 << 15, 'New 4.1 authentication'), 'MULTI_STATEMENTS': (1 << 16, 'Enable/disable multi-stmt support'), 'MULTI_RESULTS': (1 << 17, 'Enable/disable multi-results'), 'SSL_VERIFY_SERVER_CERT': (1 << 30, ''), 'REMEMBER_OPTIONS': (1 << 31, ''), } default = [ LONG_PASSWD, LONG_FLAG, CONNECT_WITH_DB, PROTOCOL_41, TRANSACTIONS, SECURE_CONNECTION, MULTI_STATEMENTS, MULTI_RESULTS, ] @classmethod def get_default(cls): """Get the default client options set Returns a flag with all the default client options set""" flags = 0 for option in cls.default: flags |= option return flags class ServerFlag(_Flags): """MySQL Server Flags Server flags as found in the MySQL sources mysql-src/include/mysql_com.h """ _prefix = 'SERVER_' STATUS_IN_TRANS = 1 << 0 STATUS_AUTOCOMMIT = 1 << 1 MORE_RESULTS_EXISTS = 1 << 3 QUERY_NO_GOOD_INDEX_USED = 1 << 4 QUERY_NO_INDEX_USED = 1 << 5 STATUS_CURSOR_EXISTS = 1 << 6 STATUS_LAST_ROW_SENT = 1 << 7 STATUS_DB_DROPPED = 1 << 8 STATUS_NO_BACKSLASH_ESCAPES = 1 << 9 desc = { 'SERVER_STATUS_IN_TRANS': (1 << 0, 'Transaction has started'), 'SERVER_STATUS_AUTOCOMMIT': (1 << 1, 'Server in auto_commit mode'), 'SERVER_MORE_RESULTS_EXISTS': (1 << 3, 'Multi query - ' 'next query exists'), 'SERVER_QUERY_NO_GOOD_INDEX_USED': (1 << 4, ''), 'SERVER_QUERY_NO_INDEX_USED': (1 << 5, ''), 'SERVER_STATUS_CURSOR_EXISTS': (1 << 6, ''), 'SERVER_STATUS_LAST_ROW_SENT': (1 << 7, ''), 'SERVER_STATUS_DB_DROPPED': (1 << 8, 'A database was dropped'), 'SERVER_STATUS_NO_BACKSLASH_ESCAPES': (1 << 9, ''), } class RefreshOption(_Constants): """MySQL Refresh command options Options used when sending the COM_REFRESH server command. """ _prefix = 'REFRESH_' GRANT = 1 << 0 LOG = 1 << 1 TABLES = 1 << 2 HOST = 1 << 3 STATUS = 1 << 4 THREADS = 1 << 5 SLAVE = 1 << 6 desc = { 'GRANT': (1 << 0, 'Refresh grant tables'), 'LOG': (1 << 1, 'Start on new log file'), 'TABLES': (1 << 2, 'close all tables'), 'HOSTS': (1 << 3, 'Flush host cache'), 'STATUS': (1 << 4, 'Flush status variables'), 'THREADS': (1 << 5, 'Flush thread cache'), 'SLAVE': (1 << 6, 'Reset master info and restart slave thread'), } class ShutdownType(_Constants): """MySQL Shutdown types Shutdown types used by the COM_SHUTDOWN server command. """ _prefix = '' SHUTDOWN_DEFAULT = '\x00' SHUTDOWN_WAIT_CONNECTIONS = '\x01' SHUTDOWN_WAIT_TRANSACTIONS = '\x02' SHUTDOWN_WAIT_UPDATES = '\x08' SHUTDOWN_WAIT_ALL_BUFFERS = '\x10' SHUTDOWN_WAIT_CRITICAL_BUFFERS = '\x11' KILL_QUERY = '\xfe' KILL_CONNECTION = '\xff' desc = { 'SHUTDOWN_DEFAULT': (SHUTDOWN_DEFAULT, "defaults to SHUTDOWN_WAIT_ALL_BUFFERS"), 'SHUTDOWN_WAIT_CONNECTIONS': (SHUTDOWN_WAIT_CONNECTIONS, "wait for existing connections to finish"), 'SHUTDOWN_WAIT_TRANSACTIONS': (SHUTDOWN_WAIT_TRANSACTIONS, "wait for existing trans to finish"), 'SHUTDOWN_WAIT_UPDATES': (SHUTDOWN_WAIT_UPDATES, "wait for existing updates to finish"), 'SHUTDOWN_WAIT_ALL_BUFFERS': (SHUTDOWN_WAIT_ALL_BUFFERS, "flush InnoDB and other storage engine buffers"), 'SHUTDOWN_WAIT_CRITICAL_BUFFERS': (SHUTDOWN_WAIT_CRITICAL_BUFFERS, "don't flush InnoDB buffers, " "flush other storage engines' buffers"), 'KILL_QUERY': (KILL_QUERY, "(no description)"), 'KILL_CONNECTION': (KILL_CONNECTION, "(no description)"), } class CharacterSet(_Constants): """MySQL supported character sets and collations List of character sets with their collations supported by MySQL. This maps to the character set we get from the server within the handshake packet. The list is hardcode so we avoid a database query when getting the name of the used character set or collation. """ desc = MYSQL_CHARACTER_SETS # Multi-byte character sets which use 5c (backslash) in characters slash_charsets = (1, 13, 28, 84, 87, 88) @classmethod def get_info(cls, setid): """Retrieves character set information as tuple using an ID Retrieves character set and collation information based on the given MySQL ID. Raises ProgrammingError when character set is not supported. Returns a tuple. """ try: return cls.desc[setid][0:2] except IndexError: raise ProgrammingError( "Character set '{0}' unsupported".format(setid)) @classmethod def get_desc(cls, setid): """Retrieves character set information as string using an ID Retrieves character set and collation information based on the given MySQL ID. Returns a tuple. """ try: return "%s/%s" % cls.get_info(setid) except: raise @classmethod def get_default_collation(cls, charset): """Retrieves the default collation for given character set Raises ProgrammingError when character set is not supported. Returns list (collation, charset, index) """ if isinstance(charset, int): try: info = cls.desc[charset] return info[1], info[0], charset except: ProgrammingError("Character set ID '%s' unsupported." % ( charset)) for cid, info in enumerate(cls.desc): if info is None: continue if info[0] == charset and info[2] is True: return info[1], info[0], cid raise ProgrammingError("Character set '%s' unsupported." % (charset)) @classmethod def get_charset_info(cls, charset=None, collation=None): """Get character set information using charset name and/or collation Retrieves character set and collation information given character set name and/or a collation name. If charset is an integer, it will look up the character set based on the MySQL's ID. For example: get_charset_info('utf8',None) get_charset_info(collation='utf8_general_ci') get_charset_info(47) Raises ProgrammingError when character set is not supported. Returns a tuple with (id, characterset name, collation) """ if isinstance(charset, int): try: info = cls.desc[charset] return (charset, info[0], info[1]) except IndexError: ProgrammingError("Character set ID %s unknown." % (charset)) if charset is not None and collation is None: info = cls.get_default_collation(charset) return (info[2], info[1], info[0]) elif charset is None and collation is not None: for cid, info in enumerate(cls.desc): if info is None: continue if collation == info[1]: return (cid, info[0], info[1]) raise ProgrammingError("Collation '%s' unknown." % (collation)) else: for cid, info in enumerate(cls.desc): if info is None: continue if info[0] == charset and info[1] == collation: return (cid, info[0], info[1]) raise ProgrammingError("Character set '%s' unknown." % (charset)) @classmethod def get_supported(cls): """Retrieves a list with names of all supproted character sets Returns a tuple. """ res = [] for info in cls.desc: if info and info[0] not in res: res.append(info[0]) return tuple(res) class SQLMode(_Constants): # pylint: disable=R0921 """MySQL SQL Modes The numeric values of SQL Modes are not interesting, only the names are used when setting the SQL_MODE system variable using the MySQL SET command. See http://dev.mysql.com/doc/refman/5.6/en/server-sql-mode.html """ _prefix = 'MODE_' REAL_AS_FLOAT = 'REAL_AS_FLOAT' PIPES_AS_CONCAT = 'PIPES_AS_CONCAT' ANSI_QUOTES = 'ANSI_QUOTES' IGNORE_SPACE = 'IGNORE_SPACE' NOT_USED = 'NOT_USED' ONLY_FULL_GROUP_BY = 'ONLY_FULL_GROUP_BY' NO_UNSIGNED_SUBTRACTION = 'NO_UNSIGNED_SUBTRACTION' NO_DIR_IN_CREATE = 'NO_DIR_IN_CREATE' POSTGRESQL = 'POSTGRESQL' ORACLE = 'ORACLE' MSSQL = 'MSSQL' DB2 = 'DB2' MAXDB = 'MAXDB' NO_KEY_OPTIONS = 'NO_KEY_OPTIONS' NO_TABLE_OPTIONS = 'NO_TABLE_OPTIONS' NO_FIELD_OPTIONS = 'NO_FIELD_OPTIONS' MYSQL323 = 'MYSQL323' MYSQL40 = 'MYSQL40' ANSI = 'ANSI' NO_AUTO_VALUE_ON_ZERO = 'NO_AUTO_VALUE_ON_ZERO' NO_BACKSLASH_ESCAPES = 'NO_BACKSLASH_ESCAPES' STRICT_TRANS_TABLES = 'STRICT_TRANS_TABLES' STRICT_ALL_TABLES = 'STRICT_ALL_TABLES' NO_ZERO_IN_DATE = 'NO_ZERO_IN_DATE' NO_ZERO_DATE = 'NO_ZERO_DATE' INVALID_DATES = 'INVALID_DATES' ERROR_FOR_DIVISION_BY_ZERO = 'ERROR_FOR_DIVISION_BY_ZERO' TRADITIONAL = 'TRADITIONAL' NO_AUTO_CREATE_USER = 'NO_AUTO_CREATE_USER' HIGH_NOT_PRECEDENCE = 'HIGH_NOT_PRECEDENCE' NO_ENGINE_SUBSTITUTION = 'NO_ENGINE_SUBSTITUTION' PAD_CHAR_TO_FULL_LENGTH = 'PAD_CHAR_TO_FULL_LENGTH' @classmethod def get_desc(cls, name): raise NotImplementedError @classmethod def get_info(cls, number): raise NotImplementedError @classmethod def get_full_info(cls): """Returns a sequence of all availble SQL Modes This class method returns a tuple containing all SQL Mode names. The names will be alphabetically sorted. Returns a tuple. """ res = [] for key in vars(cls).keys(): if (not key.startswith('_') and not hasattr(getattr(cls, key), '__call__')): res.append(key) return tuple(sorted(res)) mysql-connector-python-1.1.6/python2/mysql/connector/__init__.py0000644001577100000120000001123712276514013024321 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ MySQL Connector/Python - MySQL drive written in Python """ from mysql.connector.connection import MySQLConnection from mysql.connector.errors import ( # pylint: disable=W0622 Error, Warning, InterfaceError, DatabaseError, NotSupportedError, DataError, IntegrityError, ProgrammingError, OperationalError, InternalError, custom_error_exception, PoolError) from mysql.connector.constants import ( FieldFlag, FieldType, CharacterSet, RefreshOption, ClientFlag) from mysql.connector.dbapi import ( Date, Time, Timestamp, Binary, DateFromTicks, DateFromTicks, TimestampFromTicks, TimeFromTicks, STRING, BINARY, NUMBER, DATETIME, ROWID, apilevel, threadsafety, paramstyle) from mysql.connector.pooling import ( MySQLConnectionPool, generate_pool_name, CNX_POOL_ARGS, CONNECTION_POOL_LOCK) try: from mysql.connector import version except ImportError: # Development, try import from current directory try: import version except ImportError: raise ImportError("For development, make sure version.py is " "in current directory.") _CONNECTION_POOLS = {} def connect(*args, **kwargs): """Create or get a MySQL connection object In its simpliest form, Connect() will open a connection to a MySQL server and return a MySQLConnection object. When any connection pooling arguments are given, for example pool_name or pool_size, a pool is created or a previously one is used to return a PooledMySQLConnection. Returns MySQLConnection or PooledMySQLConnection. """ # Pooled connections if any([key in kwargs for key in CNX_POOL_ARGS]): # If no pool name specified, generate one try: pool_name = kwargs['pool_name'] except KeyError: pool_name = generate_pool_name(**kwargs) # Setup the pool, ensuring only 1 thread can update at a time with CONNECTION_POOL_LOCK: if pool_name not in _CONNECTION_POOLS: _CONNECTION_POOLS[pool_name] = MySQLConnectionPool( *args, **kwargs) elif isinstance(_CONNECTION_POOLS[pool_name], MySQLConnectionPool): # pool_size must be the same check_size = _CONNECTION_POOLS[pool_name].pool_size if ('pool_size' in kwargs and kwargs['pool_size'] != check_size): raise PoolError("Size can not be changed " "for active pools.") # Return pooled connection try: return _CONNECTION_POOLS[pool_name].get_connection() except AttributeError: raise InterfaceError( "Failed getting connection from pool '{0}'".format(pool_name)) # Regular connection return MySQLConnection(*args, **kwargs) Connect = connect # pylint: disable=C0103 __version_info__ = version.VERSION __version__ = version.VERSION_TEXT __all__ = [ 'MySQLConnection', 'Connect', 'custom_error_exception', # Some useful constants 'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption', # Error handling 'Error', 'Warning', 'InterfaceError', 'DatabaseError', 'NotSupportedError', 'DataError', 'IntegrityError', 'ProgrammingError', 'OperationalError', 'InternalError', # DBAPI PEP 249 required exports 'connect', 'apilevel', 'threadsafety', 'paramstyle', 'Date', 'Time', 'Timestamp', 'Binary', 'DateFromTicks', 'DateFromTicks', 'TimestampFromTicks', 'TimeFromTicks', 'STRING', 'BINARY', 'NUMBER', 'DATETIME', 'ROWID', ] mysql-connector-python-1.1.6/python2/mysql/connector/conversion.py0000644001577100000120000003640212276514013024750 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Converting MySQL and Python types """ import struct import datetime import time from decimal import Decimal from mysql.connector.constants import FieldType, FieldFlag, CharacterSet class HexLiteral(str): """Class holding MySQL hex literals""" def __new__(cls, str_, charset='utf8'): hexed = ["{0:x}".format(ord(i)) for i in str_.encode(charset)] obj = str.__new__(cls, ''.join(hexed)) obj.charset = charset obj.original = str_ return obj def __str__(self): return '0x' + self class MySQLConverterBase(object): """Base class for conversion classes All class dealing with converting to and from MySQL data types must be a subclass of this class. """ def __init__(self, charset='utf8', use_unicode=True): self.python_types = None self.mysql_types = None self.charset = None self.charset_id = 0 self.use_unicode = None self.set_charset(charset) self.set_unicode(use_unicode) def set_charset(self, charset): """Set character set""" if charset == 'utf8mb4': charset = 'utf8' if charset is not None: self.charset = charset else: # default to utf8 self.charset = 'utf8' self.charset_id = CharacterSet.get_charset_info(self.charset)[0] def set_unicode(self, value=True): """Set whether to use Unicode""" self.use_unicode = value def to_mysql(self, value): """Convert Python data type to MySQL""" return value def to_python(self, vtype, value): """Convert MySQL data type to Python""" return value def escape(self, buf): """Escape buffer for sending to MySQL""" return buf def quote(self, buf): """Quote buffer for sending to MySQL""" return str(buf) class MySQLConverter(MySQLConverterBase): """Default conversion class for MySQL Connector/Python. o escape method: for escaping values send to MySQL o quoting method: for quoting values send to MySQL in statements o conversion mapping: maps Python and MySQL data types to function for converting them. Whenever one needs to convert values differently, a converter_class argument can be given while instantiating a new connection like cnx.connect(converter_class=CustomMySQLConverterClass). """ def __init__(self, charset=None, use_unicode=True): MySQLConverterBase.__init__(self, charset, use_unicode) self._cache_field_types = {} def escape(self, value): """ Escapes special characters as they are expected to by when MySQL receives them. As found in MySQL source mysys/charset.c Returns the value if not a string, or the escaped string. """ if value is None: return value elif isinstance(value, (int, float, long, Decimal, HexLiteral)): return value res = value res = res.replace('\\', '\\\\') res = res.replace('\n', '\\n') res = res.replace('\r', '\\r') res = res.replace('\047', '\134\047') # single quotes res = res.replace('\042', '\134\042') # double quotes res = res.replace('\032', '\134\032') # for Win32 return res def quote(self, buf): """ Quote the parameters for commands. General rules: o numbers are returns as str type (because operation expect it) o None is returned as str('NULL') o String are quoted with single quotes '' Returns a string. """ if isinstance(buf, (int, float, long, Decimal, HexLiteral)): return str(buf) elif isinstance(buf, type(None)): return "NULL" else: # Anything else would be a string return "'%s'" % buf def to_mysql(self, value): """Convert Python data type to MySQL""" type_name = value.__class__.__name__.lower() return getattr(self, "_%s_to_mysql" % str(type_name))(value) def _int_to_mysql(self, value): """Convert value to int""" return int(value) def _long_to_mysql(self, value): """Convert value to long""" return long(value) def _float_to_mysql(self, value): """Convert value to float""" return float(value) def _str_to_mysql(self, value): """Convert value to string""" return str(value) def _unicode_to_mysql(self, value): """ Encodes value, a Python unicode string, to whatever the character set for this converter is set too. """ encoded = value.encode(self.charset) if self.charset_id in CharacterSet.slash_charsets: if '\x5c' in encoded: return HexLiteral(value, self.charset) return encoded def _bool_to_mysql(self, value): """Convert value to boolean""" if value: return 1 else: return 0 def _nonetype_to_mysql(self, value): """ This would return what None would be in MySQL, but instead we leave it None and return it right away. The actual conversion from None to NULL happens in the quoting functionality. Return None. """ return None def _datetime_to_mysql(self, value): """ Converts a datetime instance to a string suitable for MySQL. The returned string has format: %Y-%m-%d %H:%M:%S[.%f] If the instance isn't a datetime.datetime type, it return None. Returns a string. """ if value.microsecond: return '%d-%02d-%02d %02d:%02d:%02d.%06d' % ( value.year, value.month, value.day, value.hour, value.minute, value.second, value.microsecond) return '%d-%02d-%02d %02d:%02d:%02d' % ( value.year, value.month, value.day, value.hour, value.minute, value.second) def _date_to_mysql(self, value): """ Converts a date instance to a string suitable for MySQL. The returned string has format: %Y-%m-%d If the instance isn't a datetime.date type, it return None. Returns a string. """ return '%d-%02d-%02d' % (value.year, value.month, value.day) def _time_to_mysql(self, value): """ Converts a time instance to a string suitable for MySQL. The returned string has format: %H:%M:%S[.%f] If the instance isn't a datetime.time type, it return None. Returns a string or None when not valid. """ if value.microsecond: return value.strftime('%H:%M:%S.%%06d') % value.microsecond return value.strftime('%H:%M:%S') def _struct_time_to_mysql(self, value): """ Converts a time.struct_time sequence to a string suitable for MySQL. The returned string has format: %Y-%m-%d %H:%M:%S Returns a string or None when not valid. """ return time.strftime('%Y-%m-%d %H:%M:%S', value) def _timedelta_to_mysql(self, value): """ Converts a timedelta instance to a string suitable for MySQL. The returned string has format: %H:%M:%S Returns a string. """ (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) hours = hours + (value.days * 24) if value.microseconds: return '%02d:%02d:%02d.%06d' % (hours, mins, secs, value.microseconds) return '%02d:%02d:%02d' % (hours, mins, secs) def _decimal_to_mysql(self, value): """ Converts a decimal.Decimal instance to a string suitable for MySQL. Returns a string or None when not valid. """ if isinstance(value, Decimal): return str(value) return None def to_python(self, flddsc, value): """ Converts a given value coming from MySQL to a certain type in Python. The flddsc contains additional information for the field in the table. It's an element from MySQLCursor.description. Returns a mixed value. """ if value == '\x00' and flddsc[1] != FieldType.BIT: # Don't go further when we hit a NULL value return None if value is None: return None if not self._cache_field_types: self._cache_field_types = {} for name, info in FieldType.desc.items(): try: self._cache_field_types[info[0]] = getattr( self, '_{0}_to_python'.format(name)) except AttributeError: # We ignore field types which has no method pass try: return self._cache_field_types[flddsc[1]](value, flddsc) except KeyError: # If one type is not defined, we just return the value as str return str(value) except ValueError as err: raise ValueError("%s (field %s)" % (err, flddsc[0])) except TypeError as err: raise TypeError("%s (field %s)" % (err, flddsc[0])) except: raise def _FLOAT_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as float type. """ return float(value) _DOUBLE_to_python = _FLOAT_to_python def _INT_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as int type. """ return int(value) _TINY_to_python = _INT_to_python _SHORT_to_python = _INT_to_python _INT24_to_python = _INT_to_python def _LONG_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as long type. """ return int(value) _LONGLONG_to_python = _LONG_to_python def _DECIMAL_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as a decimal.Decimal. """ return Decimal(value) _NEWDECIMAL_to_python = _DECIMAL_to_python def _str(self, value, desc=None): """ Returns value as str type. """ return str(value) def _BIT_to_python(self, value, dsc=None): # pylint: disable=C0103 """Returns BIT columntype as integer""" int_val = value if len(int_val) < 8: int_val = '\x00' * (8-len(int_val)) + int_val return struct.unpack('>Q', int_val)[0] def _DATE_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns DATE column type as datetime.date type. """ try: parts = value.split('-') return datetime.date(int(parts[0]), int(parts[1]), int(parts[2])) except ValueError: return None _NEWDATE_to_python = _DATE_to_python def _TIME_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns TIME column type as datetime.time type. """ time_val = None try: (hms, mcs) = value.split('.') mcs = int(mcs.ljust(6, '0')) except ValueError: hms = value mcs = 0 try: (hour, mins, sec) = [int(d) for d in hms.split(':')] time_val = datetime.timedelta(hours=hour, minutes=mins, seconds=sec, microseconds=mcs) except ValueError: raise ValueError( "Could not convert %s to python datetime.timedelta" % value) else: return time_val def _DATETIME_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns DATETIME column type as datetime.datetime type. """ datetime_val = None try: (date_, time_) = value.split(' ') if len(time_) > 8: (hms, mcs) = time_.split('.') mcs = int(mcs.ljust(6, '0')) else: hms = time_ mcs = 0 dtval = [int(value) for value in date_.split('-')] +\ [int(value) for value in hms.split(':')] + [mcs,] datetime_val = datetime.datetime(*dtval) except ValueError: datetime_val = None return datetime_val _TIMESTAMP_to_python = _DATETIME_to_python def _YEAR_to_python(self, value, desc=None): # pylint: disable=C0103 """Returns YEAR column type as integer""" try: year = int(value) except ValueError: raise ValueError("Failed converting YEAR to int (%s)" % value) return year def _SET_to_python(self, value, dsc=None): # pylint: disable=C0103 """Returns SET column typs as set Actually, MySQL protocol sees a SET as a string type field. So this code isn't called directly, but used by STRING_to_python() method. Returns SET column type as a set. """ set_type = None try: set_type = set(value.split(',')) except ValueError: raise ValueError("Could not convert SET %s to a set." % value) return set_type def _STRING_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Note that a SET is a string too, but using the FieldFlag we can see whether we have to split it. Returns string typed columns as string type. """ if dsc is not None: # Check if we deal with a SET if dsc[7] & FieldFlag.SET: return self._SET_to_python(value, dsc) if dsc[7] & FieldFlag.BINARY: return value if self.use_unicode: try: return unicode(value, self.charset) except: raise return str(value) _VAR_STRING_to_python = _STRING_to_python def _BLOB_to_python(self, value, dsc=None): # pylint: disable=C0103 """Convert BLOB data type to Python""" if dsc is not None: if dsc[7] & FieldFlag.BINARY: return value return self._STRING_to_python(value, dsc) _LONG_BLOB_to_python = _BLOB_to_python _MEDIUM_BLOB_to_python = _BLOB_to_python _TINY_BLOB_to_python = _BLOB_to_python mysql-connector-python-1.1.6/python2/mysql/connector/cursor.py0000644001577100000120000010326412276514013024101 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Cursor classes """ import sys import weakref import re import itertools from mysql.connector import errors SQL_COMMENT = r"\/\*.*?\*\/" RE_SQL_COMMENT = re.compile( r'''({0})|(["'`][^"'`]*?({0})[^"'`]*?["'`])'''.format(SQL_COMMENT), re.I | re.M | re.S) RE_SQL_ON_DUPLICATE = re.compile( r'''\s*ON\s+DUPLICATE\s+KEY(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$''', re.I | re.M | re.S) RE_SQL_INSERT_STMT = re.compile( r"({0}|\s)*INSERT({0}|\s)*INTO.+VALUES.*".format(SQL_COMMENT), re.I | re.M | re.S) RE_SQL_INSERT_VALUES = re.compile(r'.*VALUES\s*(\(.*\)).*', re.I | re.M | re.S) RE_SQL_SPLIT_STMTS = re.compile( r''';(?=(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$)''') RE_SQL_FIND_PARAM = re.compile( r'''%s(?=(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$)''') class CursorBase(object): """ Base for defining MySQLCursor. This class is a skeleton and defines methods and members as required for the Python Database API Specification v2.0. It's better to inherite from MySQLCursor. """ def __init__(self): self._description = None self._rowcount = -1 self._last_insert_id = None self.arraysize = 1 def callproc(self, procname, args=()): """Calls a stored procedue with the given arguments The arguments will be set during this session, meaning they will be called like ___arg where is an enumeration (+1) of the arguments. Coding Example: 1) Definining the Stored Routine in MySQL: CREATE PROCEDURE multiply(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) BEGIN SET pProd := pFac1 * pFac2; END 2) Executing in Python: args = (5,5,0) # 0 is to hold pprod cursor.callproc('multiply', args) print(cursor.fetchone()) Does not return a value, but a result set will be available when the CALL-statement execute successfully. Raises exceptions when something is wrong. """ pass def close(self): """Close the cursor.""" pass def execute(self, operation, params=(), multi=False): """Executes the given operation Executes the given operation substituting any markers with the given parameters. For example, getting all rows where id is 5: cursor.execute("SELECT * FROM t1 WHERE id = %s", (5,)) The multi argument should be set to True when executing multiple statements in one operation. If not set and multiple results are found, an InterfaceError will be raised. If warnings where generated, and connection.get_warnings is True, then self._warnings will be a list containing these warnings. Returns an iterator when multi is True, otherwise None. """ pass def executemany(self, operation, seqparams): """Execute the given operation multiple times The executemany() method will execute the operation iterating over the list of parameters in seq_params. Example: Inserting 3 new employees and their phone number data = [ ('Jane','555-001'), ('Joe', '555-001'), ('John', '555-003') ] stmt = "INSERT INTO employees (name, phone) VALUES ('%s','%s')" cursor.executemany(stmt, data) INSERT statements are optimized by batching the data, that is using the MySQL multiple rows syntax. Results are discarded. If they are needed, consider looping over data using the execute() method. """ pass def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ pass def fetchmany(self, size=1): """Returns the next set of rows of a query result, returning a list of tuples. When no more rows are available, it returns an empty list. The number of rows returned can be specified using the size argument, which defaults to one """ pass def fetchall(self): """Returns all rows of a query result set Returns a list of tuples. """ pass def nextset(self): """Not Implemented.""" pass def setinputsizes(self, sizes): """Not Implemeted.""" pass def setoutputsize(self, size, column=None): """Not Implemeted.""" pass def reset(self): """Reset the cursor to default""" pass @property def description(self): """Returns description of columns in a result This property returns a list of tuples describing the columns in in a result set. A tuple is described as follows:: (column_name, type, None, None, None, None, null_ok, column_flags) # Addition to PEP-249 specs Returns a list of tuples. """ return self._description @property def rowcount(self): """Returns the number of rows produced or affected This property returns the number of rows produced by queries such as a SELECT, or affected rows when executing DML statements like INSERT or UPDATE. Note that for non-buffered cursors it is impossible to know the number of rows produced before having fetched them all. For those, the number of rows will be -1 right after execution, and incremented when fetching rows. Returns an integer. """ return self._rowcount @property def lastrowid(self): """Returns the value generated for an AUTO_INCREMENT column Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement or None when there is no such value available. Returns a long value or None. """ return self._last_insert_id class MySQLCursor(CursorBase): """Default cursor for interacting with MySQL This cursor will execute statements and handle the result. It will not automatically fetch all rows. MySQLCursor should be inherited whenever other functionallity is required. An example would to change the fetch* member functions to return dictionaries instead of lists of values. Implements the Python Database API Specification v2.0 (PEP-249) """ def __init__(self, connection=None): CursorBase.__init__(self) self._connection = None self._stored_results = [] self._nextrow = (None, None) self._warnings = None self._warning_count = 0 self._executed = None self._executed_list = [] self._binary = False self._lastrowid = None if connection is not None: self._set_connection(connection) def __iter__(self): """ Iteration over the result set which calls self.fetchone() and returns the next row. """ return iter(self.fetchone, None) def _set_connection(self, connection): """Set the connection""" try: self._connection = weakref.proxy(connection) self._connection._protocol # pylint: disable=W0212,W0104 except (AttributeError, TypeError): raise errors.InterfaceError(errno=2048) def _reset_result(self): """Reset the cursor to default""" self._rowcount = -1 self._lastrowid = None self._nextrow = (None, None) self._stored_results = [] self._warnings = None self._warning_count = 0 self._description = None self._executed = None self._executed_list = [] self.reset() def _have_unread_result(self): """Check whether there is an unread result""" try: return self._connection.unread_result except AttributeError: return False def next(self): """ Used for iterating over the result set. Calles self.fetchone() to get the next row. """ try: row = self.fetchone() except errors.InterfaceError: raise StopIteration if not row: raise StopIteration return row def close(self): """Close the cursor Returns True when successful, otherwise False. """ if self._connection is None: return False if self._have_unread_result(): raise errors.InternalError("Unread result found.") self._reset_result() self._connection = None return True def _process_params_dict(self, params): """Process query parameters given as dictionary""" try: to_mysql = self._connection.converter.to_mysql escape = self._connection.converter.escape quote = self._connection.converter.quote res = {} for key, val in params.items(): conv = val conv = to_mysql(conv) conv = escape(conv) conv = quote(conv) res[key] = conv except StandardError as err: raise errors.ProgrammingError( "Failed processing pyformat-parameters; %s" % err) else: return res return None def _process_params(self, params): """Process query parameters.""" if isinstance(params, dict): return self._process_params_dict(params) try: res = params # pylint: disable=W0141 res = map(self._connection.converter.to_mysql, res) res = map(self._connection.converter.escape, res) res = map(self._connection.converter.quote, res) # pylint: enable=W0141 except StandardError as err: raise errors.ProgrammingError( "Failed processing format-parameters; %s" % err) else: return tuple(res) return None def _row_to_python(self, rowdata, desc=None): """Convert the row from MySQL to Python types""" res = [] to_python = self._connection.converter.to_python try: if not desc: desc = self.description for flddsc, val in zip(desc, rowdata): res.append(to_python(flddsc, val),) except StandardError as err: raise errors.InterfaceError( "Failed converting row to Python types; %s" % err) else: return tuple(res) return None def _handle_noresultset(self, res): """Handles result of execute() when there is no result set """ try: self._rowcount = res['affected_rows'] self._last_insert_id = res['insert_id'] self._warning_count = res['warning_count'] except (KeyError, TypeError) as err: raise errors.ProgrammingError( "Failed handling non-resultset; %s" % err) if self._connection.get_warnings is True and self._warning_count: self._warnings = self._fetch_warnings() def _handle_resultset(self): """Handles result set This method handles the result set and is called after reading and storing column information in _handle_result(). For non-buffering cursors, this method is usually doing nothing. """ pass def _handle_result(self, result): """ Handle the result after a command was send. The result can be either an OK-packet or a dictionary containing column/eof information. Raises InterfaceError when result is not a dict() or result is invalid. """ if not isinstance(result, dict): raise errors.InterfaceError('Result was not a dict()') if 'columns' in result: # Weak test, must be column/eof information self._description = result['columns'] self._connection.unread_result = True self._handle_resultset() elif 'affected_rows' in result: # Weak test, must be an OK-packet self._connection.unread_result = False self._handle_noresultset(result) else: raise errors.InterfaceError('Invalid result') def _execute_iter(self, query_iter): """Generator returns MySQLCursor objects for multiple statements This method is only used when multiple statements are executed by the execute() method. It uses itertools.izip to iterate over the given query_iter (result of MySQLConnection.cmd_query_iter()) and the list of statements that were executed. Yields a MySQLCursor instance. """ if not self._executed_list: self._executed_list = RE_SQL_SPLIT_STMTS.split(self._executed) for result, stmt in itertools.izip(query_iter, iter(self._executed_list)): self._reset_result() self._handle_result(result) self._executed = stmt yield self def execute(self, operation, params=None, multi=False): """Executes the given operation Executes the given operation substituting any markers with the given parameters. For example, getting all rows where id is 5: cursor.execute("SELECT * FROM t1 WHERE id = %s", (5,)) The multi argument should be set to True when executing multiple statements in one operation. If not set and multiple results are found, an InterfaceError will be raised. If warnings where generated, and connection.get_warnings is True, then self._warnings will be a list containing these warnings. Returns an iterator when multi is True, otherwise None. """ if not operation: return if self._have_unread_result(): raise errors.InternalError("Unread result found.") self._reset_result() stmt = '' try: if isinstance(operation, unicode): operation = operation.encode(self._connection.python_charset) except (UnicodeDecodeError, UnicodeEncodeError) as err: raise errors.ProgrammingError(str(err)) if params is not None: try: stmt = operation % self._process_params(params) except TypeError: raise errors.ProgrammingError( "Wrong number of arguments during string formatting") else: stmt = operation if multi: self._executed = stmt self._executed_list = [] return self._execute_iter(self._connection.cmd_query_iter(stmt)) else: self._executed = stmt try: self._handle_result(self._connection.cmd_query(stmt)) except errors.InterfaceError: if self._connection._have_next_result: # pylint: disable=W0212 raise errors.InterfaceError( "Use multi=True when executing multiple statements") raise return None def executemany(self, operation, seq_params): """Execute the given operation multiple times The executemany() method will execute the operation iterating over the list of parameters in seq_params. Example: Inserting 3 new employees and their phone number data = [ ('Jane','555-001'), ('Joe', '555-001'), ('John', '555-003') ] stmt = "INSERT INTO employees (name, phone) VALUES ('%s','%s')" cursor.executemany(stmt, data) INSERT statements are optimized by batching the data, that is using the MySQL multiple rows syntax. Results are discarded. If they are needed, consider looping over data using the execute() method. """ def remove_comments(match): """Remove comments from INSERT statements. This function is used while removing comments from INSERT statements. If the matched string is a comment not enclosed by quotes, it returns an empty string, else the string itself. """ if match.group(1): return "" else: return match.group(2) if not operation: return if self._have_unread_result(): raise errors.InternalError("Unread result found.") elif len(RE_SQL_SPLIT_STMTS.split(operation)) > 1: raise errors.InternalError( "executemany() does not support multiple statements") # Optimize INSERTs by batching them if re.match(RE_SQL_INSERT_STMT, operation): if not seq_params: self._rowcount = 0 return tmp = re.sub(RE_SQL_ON_DUPLICATE, '', re.sub(RE_SQL_COMMENT, remove_comments, operation)) matches = re.search(RE_SQL_INSERT_VALUES, tmp) if not matches: raise errors.InterfaceError( "Failed rewriting statement for multi-row INSERT. " "Check SQL syntax." ) fmt = matches.group(1) values = [] for params in seq_params: values.append(fmt % self._process_params(params)) if matches.group(1) in operation: operation = operation.replace(matches.group(1), ','.join(values), 1) return self.execute(operation) rowcnt = 0 try: for params in seq_params: self.execute(operation, params) if self.with_rows and self._have_unread_result(): self.fetchall() rowcnt += self._rowcount except (ValueError, TypeError) as err: raise errors.InterfaceError( "Failed executing the operation; %s" % err) except: # Raise whatever execute() raises raise self._rowcount = rowcnt def stored_results(self): """Returns an iterator for stored results This method returns an iterator over results which are stored when callproc() is called. The iterator will provide MySQLCursorBuffered instances. Returns a iterator. """ return iter(self._stored_results) def callproc(self, procname, args=()): """Calls a stored procedue with the given arguments The arguments will be set during this session, meaning they will be called like ___arg where is an enumeration (+1) of the arguments. Coding Example: 1) Definining the Stored Routine in MySQL: CREATE PROCEDURE multiply(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) BEGIN SET pProd := pFac1 * pFac2; END 2) Executing in Python: args = (5,5,0) # 0 is to hold pprod cursor.callproc('multiply', args) print(cursor.fetchone()) Does not return a value, but a result set will be available when the CALL-statement execute successfully. Raises exceptions when something is wrong. """ if not procname or not isinstance(procname, str): raise ValueError("procname must be a string") if not isinstance(args, (tuple, list)): raise ValueError("args must be a sequence") argfmt = "@_{name}_arg{index}" self._stored_results = [] results = [] try: argnames = [] if args: for idx, arg in enumerate(args): argname = argfmt.format(name=procname, index=idx + 1) argnames.append(argname) self.execute("SET {0}=%s".format(argname), (arg,)) call = "CALL {0}({1})".format(procname, ','.join(argnames)) for result in self._connection.cmd_query_iter(call): if 'columns' in result: # pylint: disable=W0212 tmp = MySQLCursorBuffered(self._connection._get_self()) tmp._handle_result(result) results.append(tmp) # pylint: enable=W0212 if argnames: select = "SELECT {0}".format(','.join(argnames)) self.execute(select) self._stored_results = results return self.fetchone() else: self._stored_results = results return () except errors.Error: raise except StandardError as err: raise errors.InterfaceError( "Failed calling stored routine; {0}".format(err)) def getlastrowid(self): """Returns the value generated for an AUTO_INCREMENT column This method is kept for backward compatibility. Please use the property lastrowid instead. Returns a long value or None. """ return self.lastrowid def _fetch_warnings(self): """ Fetch warnings doing a SHOW WARNINGS. Can be called after getting the result. Returns a result set or None when there were no warnings. """ res = [] try: cur = self._connection.cursor() cur.execute("SHOW WARNINGS") res = cur.fetchall() cur.close() except StandardError as err: raise errors.InterfaceError, errors.InterfaceError( "Failed getting warnings; %s" % err), sys.exc_info()[2] if self._connection.raise_on_warnings is True: raise errors.get_mysql_exception(res[0][1], res[0][2]) else: if len(res): return res return None def _handle_eof(self, eof): """Handle EOF packet""" self._connection.unread_result = False self._nextrow = (None, None) self._warning_count = eof['warning_count'] if self._connection.get_warnings is True and eof['warning_count']: self._warnings = self._fetch_warnings() def _fetch_row(self): """Returns the next row in the result set Returns a tuple or None. """ if not self._have_unread_result(): return None row = None if self._nextrow == (None, None): (row, eof) = self._connection.get_row( binary=self._binary, columns=self.description) else: (row, eof) = self._nextrow if row: self._nextrow = self._connection.get_row( binary=self._binary, columns=self.description) eof = self._nextrow[1] if eof is not None: self._handle_eof(eof) if self._rowcount == -1: self._rowcount = 1 else: self._rowcount += 1 if eof: self._handle_eof(eof) return row def fetchwarnings(self): """Returns warnings""" return self._warnings def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ row = self._fetch_row() if row: return self._row_to_python(row) return None def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0 and self._have_unread_result(): cnt -= 1 row = self.fetchone() if row: res.append(row) return res def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows() if self._nextrow[0]: rows.insert(0, self._nextrow[0]) res = [self._row_to_python(row) for row in rows] self._handle_eof(eof) rowcount = len(rows) if rowcount >= 0 and self._rowcount == -1: self._rowcount = 0 self._rowcount += rowcount return res @property def column_names(self): """Returns column names This property returns the columns names as a tuple. Returns a tuple. """ if not self.description: return () return tuple([d[0].decode('utf8') for d in self.description]) @property def statement(self): """Returns the executed statement This property returns the executed statement. When multiple statements were executed, the current statement in the iterator will be returned. """ return self._executed.strip() @property def with_rows(self): """Returns whether the cursor could have rows returned This property returns True when column descriptions are available and possibly also rows, which will need to be fetched. Returns True or False. """ if not self.description: return False return True def __unicode__(self): fmt = "MySQLCursor: %s" if self._executed: if len(self._executed) > 30: res = fmt % (self._executed[:30] + '..') else: res = fmt % (self._executed) else: res = fmt % '(Nothing executed yet)' return res def __str__(self): return repr(self.__unicode__()) class MySQLCursorBuffered(MySQLCursor): """Cursor which fetches rows within execute()""" def __init__(self, connection=None): MySQLCursor.__init__(self, connection) self._rows = None self._next_row = 0 def _handle_resultset(self): (self._rows, eof) = self._connection.get_rows() self._rowcount = len(self._rows) self._handle_eof(eof) self._next_row = 0 try: self._connection.unread_result = False except: pass def reset(self): self._rows = None def _fetch_row(self): """Returns the next row in the result set Returns a tuple or None. """ row = None try: row = self._rows[self._next_row] except: return None else: self._next_row += 1 return row return None def fetchall(self): if self._rows is None: raise errors.InterfaceError("No result set to fetch from.") res = [] for row in self._rows[self._next_row:]: res.append(self._row_to_python(row)) self._next_row = len(self._rows) return res def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0: cnt -= 1 row = self.fetchone() if row: res.append(row) return res @property def with_rows(self): return self._rows is not None class MySQLCursorRaw(MySQLCursor): """ Skips conversion from MySQL datatypes to Python types when fetching rows. """ def fetchone(self): row = self._fetch_row() if row: return row return None def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows() if self._nextrow[0]: rows.insert(0, self._nextrow[0]) self._handle_eof(eof) rowcount = len(rows) if rowcount >= 0 and self._rowcount == -1: self._rowcount = 0 self._rowcount += rowcount return rows class MySQLCursorBufferedRaw(MySQLCursorBuffered): """ Cursor which skips conversion from MySQL datatypes to Python types when fetching rows and fetches rows within execute(). """ def fetchone(self): row = self._fetch_row() if row: return row return None def fetchall(self): if self._rows is None: raise errors.InterfaceError("No result set to fetch from.") return self._rows[self._next_row:] class MySQLCursorPrepared(MySQLCursor): """Cursor using MySQL Prepared Statements """ def __init__(self, connection=None): super(MySQLCursorPrepared, self).__init__(connection) self._rows = None self._next_row = 0 self._prepared = None self._binary = True self._have_result = None def callproc(self, *args, **kwargs): """Calls a stored procedure Not supported with MySQLCursorPrepared. """ raise errors.NotSupportedError() def close(self): """Close the cursor This method will try to deallocate the prepared statement and close the cursor. """ if self._prepared: try: self._connection.cmd_stmt_close(self._prepared['statement_id']) except errors.Error: # We tried to deallocate, but it's OK when we fail. pass self._prepared = None super(MySQLCursorPrepared, self).close() def _row_to_python(self, rowdata, desc=None): """Convert row data from MySQL to Python types The conversion is done while reading binary data in the protocol module. """ pass def _handle_result(self, res): """Handle result after execution""" if isinstance(res, dict): self._connection.unread_result = False self._have_result = False self._handle_noresultset(res) else: self._description = res[1] self._connection.unread_result = True self._have_result = True def execute(self, operation, params=(), multi=False): """Prepare and execute a MySQL Prepared Statement This method will prepare the given operation and execute it using the optionally given parameters. If the cursor instance already had a prepared statement, it is first closed. """ if operation is not self._executed: if self._prepared: self._connection.cmd_stmt_close(self._prepared['statement_id']) self._executed = operation # need to convert %s to ? before sending it to MySQL if '%s' in operation: operation = re.sub(RE_SQL_FIND_PARAM, '?', operation) try: self._prepared = self._connection.cmd_stmt_prepare(operation) except errors.Error: self._executed = None raise self._connection.cmd_stmt_reset(self._prepared['statement_id']) if self._prepared['parameters'] and not params: return elif len(self._prepared['parameters']) != len(params): raise errors.ProgrammingError( errno=1210, msg="Incorrect number of arguments " "executing prepared statement") res = self._connection.cmd_stmt_execute( self._prepared['statement_id'], data=params, parameters=self._prepared['parameters']) self._handle_result(res) def executemany(self, operation, seq_params): """Prepare and execute a MySQL Prepared Statement many times This method will prepare the given operation and execute with each tuple found the list seq_params. If the cursor instance already had a prepared statement, it is first closed. executemany() simply calls execute(). """ rowcnt = 0 try: for params in seq_params: self.execute(operation, params) if self.with_rows and self._have_unread_result(): self.fetchall() rowcnt += self._rowcount except (ValueError, TypeError) as err: raise errors.InterfaceError( "Failed executing the operation; {error}".format(error=err)) except: # Raise whatever execute() raises raise self._rowcount = rowcnt def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ return self._fetch_row() or None def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0 and self._have_unread_result(): cnt -= 1 row = self._fetch_row() if row: res.append(row) return res def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows( binary=self._binary, columns=self.description) self._rowcount = len(rows) self._handle_eof(eof) return rows mysql-connector-python-1.1.6/python2/mysql/connector/errors.py0000644001577100000120000002261112276514013024074 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """This module implements Exception classes """ from mysql.connector import utils from mysql.connector.locales import get_client_error # _CUSTOM_ERROR_EXCEPTIONS holds custom exceptions and is used by the # function custom_error_exception. _ERROR_EXCEPTIONS (at bottom of module) # is similar, but hardcoded exceptions. _CUSTOM_ERROR_EXCEPTIONS = {} def custom_error_exception(error=None, exception=None): """Define custom exceptions for MySQL server errors This function defines custom exceptions for MySQL server errors and returns the current set customizations. If error is a MySQL Server error number, then you have to pass also the exception class. The error argument can also be a dictionary in which case the key is the server error number, and value the exception to be raised. If none of the arguments are given, then custom_error_exception() will simply return the current set customizations. To reset the customizations, simply supply an empty dictionary. Examples: import mysql.connector from mysql.connector import errorcode # Server error 1028 should raise a DatabaseError mysql.connector.custom_error_exception( 1028, mysql.connector.DatabaseError) # Or using a dictionary: mysql.connector.custom_error_exception({ 1028: mysql.connector.DatabaseError, 1029: mysql.connector.OperationalError, }) # Reset mysql.connector.custom_error_exception({}) Returns a dictionary. """ global _CUSTOM_ERROR_EXCEPTIONS # pylint: disable=W0603 if isinstance(error, dict) and not len(error): _CUSTOM_ERROR_EXCEPTIONS = {} return _CUSTOM_ERROR_EXCEPTIONS if not error and not exception: return _CUSTOM_ERROR_EXCEPTIONS if not isinstance(error, (int, dict)): raise ValueError( "The error argument should be either an integer or dictionary") if isinstance(error, int): error = {error: exception} for errno, exception in error.items(): if not isinstance(errno, int): raise ValueError("error number should be an integer") try: if not issubclass(exception, Exception): raise TypeError except TypeError: raise ValueError("exception should be subclass of Exception") _CUSTOM_ERROR_EXCEPTIONS[errno] = exception return _CUSTOM_ERROR_EXCEPTIONS def get_mysql_exception(errno, msg, sqlstate=None): """Get the exception matching the MySQL error This function will return an exception based on the SQLState. The given message will be passed on in the returned exception. The exception returned can be customized using the mysql.connector.custom_error_exception() function. Returns an Exception """ try: return _CUSTOM_ERROR_EXCEPTIONS[errno]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Error was not mapped to custom exception pass try: return _ERROR_EXCEPTIONS[errno]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Error was not mapped to particular exception pass if not sqlstate: return DatabaseError(msg=msg, errno=errno) try: return _SQLSTATE_CLASS_EXCEPTION[sqlstate[0:2]]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Return default InterfaceError return DatabaseError(msg=msg, errno=errno, sqlstate=sqlstate) def get_exception(packet): """Returns an exception object based on the MySQL error Returns an exception object based on the MySQL error in the given packet. Returns an Error-Object. """ errno = errmsg = None if packet[4] != '\xff': raise ValueError("Packet is not an error packet") sqlstate = None try: packet = packet[5:] (packet, errno) = utils.read_int(packet, 2) if packet[0] != '\x23': # Error without SQLState errmsg = packet else: (packet, sqlstate) = utils.read_bytes(packet[1:], 5) errmsg = packet except StandardError as err: return InterfaceError("Failed getting Error information (%r)" % err) else: return get_mysql_exception(errno, errmsg, sqlstate) class Error(StandardError): """Exception that is base class for all other error exceptions""" def __init__(self, msg=None, errno=None, values=None, sqlstate=None): super(Error, self).__init__() self.msg = msg self._full_msg = self.msg self.errno = errno or -1 self.sqlstate = sqlstate if not self.msg and (2000 <= self.errno < 3000): self.msg = get_client_error(self.errno) if values is not None: try: self.msg = self.msg % values except TypeError as err: self.msg = "{0} (Warning: {1})".format(self.msg, str(err)) elif not self.msg: self._full_msg = self.msg = 'Unknown error' if self.msg and self.errno != -1: fields = { 'errno': self.errno, 'msg': self.msg } if self.sqlstate: fmt = '{errno} ({state}): {msg}' fields['state'] = self.sqlstate else: fmt = '{errno}: {msg}' self._full_msg = fmt.format(**fields) def __str__(self): return self._full_msg class Warning(StandardError): # pylint: disable=W0622 """Exception for important warnings""" pass class InterfaceError(Error): """Exception for errors related to the interface""" pass class DatabaseError(Error): """Exception for errors related to the database""" pass class InternalError(DatabaseError): """Exception for errors internal database errors""" pass class OperationalError(DatabaseError): """Exception for errors related to the database's operation""" pass class ProgrammingError(DatabaseError): """Exception for errors programming errors""" pass class IntegrityError(DatabaseError): """Exception for errors regarding relational integrity""" pass class DataError(DatabaseError): """Exception for errors reporting problems with processed data""" pass class NotSupportedError(DatabaseError): """Exception for errors when an unsupported database feature was used""" pass class PoolError(Error): """Exception raise for errors relating to connection pooling""" pass _SQLSTATE_CLASS_EXCEPTION = { '02': DataError, # no data '07': DatabaseError, # dynamic SQL error '08': OperationalError, # connection exception '0A': NotSupportedError, # feature not supported '21': DataError, # cardinality violation '22': DataError, # data exception '23': IntegrityError, # integrity constraint violation '24': ProgrammingError, # invalid cursor state '25': ProgrammingError, # invalid transaction state '26': ProgrammingError, # invalid SQL statement name '27': ProgrammingError, # triggered data change violation '28': ProgrammingError, # invalid authorization specification '2A': ProgrammingError, # direct SQL syntax error or access rule violation '2B': DatabaseError, # dependent privilege descriptors still exist '2C': ProgrammingError, # invalid character set name '2D': DatabaseError, # invalid transaction termination '2E': DatabaseError, # invalid connection name '33': DatabaseError, # invalid SQL descriptor name '34': ProgrammingError, # invalid cursor name '35': ProgrammingError, # invalid condition number '37': ProgrammingError, # dynamic SQL syntax error or access rule violation '3C': ProgrammingError, # ambiguous cursor name '3D': ProgrammingError, # invalid catalog name '3F': ProgrammingError, # invalid schema name '40': InternalError, # transaction rollback '42': ProgrammingError, # syntax error or access rule violation '44': InternalError, # with check option violation 'HZ': OperationalError, # remote database access 'XA': IntegrityError, '0K': OperationalError, 'HY': DatabaseError, # default when no SQLState provided by MySQL server } _ERROR_EXCEPTIONS = { 1243: ProgrammingError, 1210: ProgrammingError, } mysql-connector-python-1.1.6/python2/mysql/connector/network.py0000644001577100000120000003403712276514013024256 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Module implementing low-level socket communication with MySQL servers. """ import socket import struct from collections import deque import zlib try: import ssl except ImportError: # If import fails, we don't have SSL support. pass from mysql.connector import constants, errors def _strioerror(err): """Reformat the IOError error message This function reformats the IOError error message. """ if not err.errno: return str(err) return '{errno} {strerr}'.format(errno=err.errno, strerr=err.strerror) def _prepare_packets(buf, pktnr): """Prepare a packet for sending to the MySQL server""" pkts = [] buflen = len(buf) maxpktlen = constants.MAX_PACKET_LENGTH while buflen > maxpktlen: pkts.append('\xff\xff\xff' + struct.pack(' 255: self._packet_number = 0 return self._packet_number def open_connection(self): """Open the socket""" raise NotImplementedError def get_address(self): """Get the location of the socket""" raise NotImplementedError def close_connection(self): """Close the socket""" try: self.sock.close() del self._packet_queue except (socket.error, AttributeError): pass def send_plain(self, buf, packet_number=None): """Send packets to the MySQL server""" if packet_number is None: self.next_packet_number # pylint: disable=W0104 else: self._packet_number = packet_number packets = _prepare_packets(buf, self._packet_number) for packet in packets: try: self.sock.sendall(packet) except IOError as err: raise errors.OperationalError( errno=2055, values=(self.get_address(), _strioerror(err))) except AttributeError: raise errors.OperationalError(errno=2006) send = send_plain def send_compressed(self, buf, packet_number=None): """Send compressed packets to the MySQL server""" if packet_number is None: self.next_packet_number # pylint: disable=W0104 else: self._packet_number = packet_number pktnr = self._packet_number pllen = len(buf) zpkts = [] maxpktlen = constants.MAX_PACKET_LENGTH if pllen > maxpktlen: pkts = _prepare_packets(buf, pktnr) tmpbuf = ''.join(pkts) del pkts seqid = 0 zbuf = zlib.compress(tmpbuf[:16384]) zpkts.append(struct.pack(' maxpktlen: zbuf = zlib.compress(tmpbuf[:maxpktlen]) zpkts.append(struct.pack(' 50: zbuf = zlib.compress(pkt) zpkts.append(struct.pack(' 0: chunk = self.sock.recv(rest) if not chunk: raise errors.InterfaceError(errno=2013) packet += chunk rest = packet_totlen - len(packet) return packet except IOError as err: raise errors.OperationalError( errno=2055, values=(self.get_address(), _strioerror(err))) recv = recv_plain def _split_zipped_payload(self, packet_bunch): """Split compressed payload""" while packet_bunch: payload_length = struct.unpack(", like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. _GENERATED_ON = '2013-10-04' _MYSQL_VERSION = (5, 7, 2) """This module contains the MySQL Server and Client error codes""" # Start MySQL Errors ER_HASHCHK = 1000 ER_NISAMCHK = 1001 ER_NO = 1002 ER_YES = 1003 ER_CANT_CREATE_FILE = 1004 ER_CANT_CREATE_TABLE = 1005 ER_CANT_CREATE_DB = 1006 ER_DB_CREATE_EXISTS = 1007 ER_DB_DROP_EXISTS = 1008 ER_DB_DROP_DELETE = 1009 ER_DB_DROP_RMDIR = 1010 ER_CANT_DELETE_FILE = 1011 ER_CANT_FIND_SYSTEM_REC = 1012 ER_CANT_GET_STAT = 1013 ER_CANT_GET_WD = 1014 ER_CANT_LOCK = 1015 ER_CANT_OPEN_FILE = 1016 ER_FILE_NOT_FOUND = 1017 ER_CANT_READ_DIR = 1018 ER_CANT_SET_WD = 1019 ER_CHECKREAD = 1020 ER_DISK_FULL = 1021 ER_DUP_KEY = 1022 ER_ERROR_ON_CLOSE = 1023 ER_ERROR_ON_READ = 1024 ER_ERROR_ON_RENAME = 1025 ER_ERROR_ON_WRITE = 1026 ER_FILE_USED = 1027 ER_FILSORT_ABORT = 1028 ER_FORM_NOT_FOUND = 1029 ER_GET_ERRNO = 1030 ER_ILLEGAL_HA = 1031 ER_KEY_NOT_FOUND = 1032 ER_NOT_FORM_FILE = 1033 ER_NOT_KEYFILE = 1034 ER_OLD_KEYFILE = 1035 ER_OPEN_AS_READONLY = 1036 ER_OUTOFMEMORY = 1037 ER_OUT_OF_SORTMEMORY = 1038 ER_UNEXPECTED_EOF = 1039 ER_CON_COUNT_ERROR = 1040 ER_OUT_OF_RESOURCES = 1041 ER_BAD_HOST_ERROR = 1042 ER_HANDSHAKE_ERROR = 1043 ER_DBACCESS_DENIED_ERROR = 1044 ER_ACCESS_DENIED_ERROR = 1045 ER_NO_DB_ERROR = 1046 ER_UNKNOWN_COM_ERROR = 1047 ER_BAD_NULL_ERROR = 1048 ER_BAD_DB_ERROR = 1049 ER_TABLE_EXISTS_ERROR = 1050 ER_BAD_TABLE_ERROR = 1051 ER_NON_UNIQ_ERROR = 1052 ER_SERVER_SHUTDOWN = 1053 ER_BAD_FIELD_ERROR = 1054 ER_WRONG_FIELD_WITH_GROUP = 1055 ER_WRONG_GROUP_FIELD = 1056 ER_WRONG_SUM_SELECT = 1057 ER_WRONG_VALUE_COUNT = 1058 ER_TOO_LONG_IDENT = 1059 ER_DUP_FIELDNAME = 1060 ER_DUP_KEYNAME = 1061 ER_DUP_ENTRY = 1062 ER_WRONG_FIELD_SPEC = 1063 ER_PARSE_ERROR = 1064 ER_EMPTY_QUERY = 1065 ER_NONUNIQ_TABLE = 1066 ER_INVALID_DEFAULT = 1067 ER_MULTIPLE_PRI_KEY = 1068 ER_TOO_MANY_KEYS = 1069 ER_TOO_MANY_KEY_PARTS = 1070 ER_TOO_LONG_KEY = 1071 ER_KEY_COLUMN_DOES_NOT_EXITS = 1072 ER_BLOB_USED_AS_KEY = 1073 ER_TOO_BIG_FIELDLENGTH = 1074 ER_WRONG_AUTO_KEY = 1075 ER_READY = 1076 ER_NORMAL_SHUTDOWN = 1077 ER_GOT_SIGNAL = 1078 ER_SHUTDOWN_COMPLETE = 1079 ER_FORCING_CLOSE = 1080 ER_IPSOCK_ERROR = 1081 ER_NO_SUCH_INDEX = 1082 ER_WRONG_FIELD_TERMINATORS = 1083 ER_BLOBS_AND_NO_TERMINATED = 1084 ER_TEXTFILE_NOT_READABLE = 1085 ER_FILE_EXISTS_ERROR = 1086 ER_LOAD_INFO = 1087 ER_ALTER_INFO = 1088 ER_WRONG_SUB_KEY = 1089 ER_CANT_REMOVE_ALL_FIELDS = 1090 ER_CANT_DROP_FIELD_OR_KEY = 1091 ER_INSERT_INFO = 1092 ER_UPDATE_TABLE_USED = 1093 ER_NO_SUCH_THREAD = 1094 ER_KILL_DENIED_ERROR = 1095 ER_NO_TABLES_USED = 1096 ER_TOO_BIG_SET = 1097 ER_NO_UNIQUE_LOGFILE = 1098 ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099 ER_TABLE_NOT_LOCKED = 1100 ER_BLOB_CANT_HAVE_DEFAULT = 1101 ER_WRONG_DB_NAME = 1102 ER_WRONG_TABLE_NAME = 1103 ER_TOO_BIG_SELECT = 1104 ER_UNKNOWN_ERROR = 1105 ER_UNKNOWN_PROCEDURE = 1106 ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108 ER_UNKNOWN_TABLE = 1109 ER_FIELD_SPECIFIED_TWICE = 1110 ER_INVALID_GROUP_FUNC_USE = 1111 ER_UNSUPPORTED_EXTENSION = 1112 ER_TABLE_MUST_HAVE_COLUMNS = 1113 ER_RECORD_FILE_FULL = 1114 ER_UNKNOWN_CHARACTER_SET = 1115 ER_TOO_MANY_TABLES = 1116 ER_TOO_MANY_FIELDS = 1117 ER_TOO_BIG_ROWSIZE = 1118 ER_STACK_OVERRUN = 1119 ER_WRONG_OUTER_JOIN = 1120 ER_NULL_COLUMN_IN_INDEX = 1121 ER_CANT_FIND_UDF = 1122 ER_CANT_INITIALIZE_UDF = 1123 ER_UDF_NO_PATHS = 1124 ER_UDF_EXISTS = 1125 ER_CANT_OPEN_LIBRARY = 1126 ER_CANT_FIND_DL_ENTRY = 1127 ER_FUNCTION_NOT_DEFINED = 1128 ER_HOST_IS_BLOCKED = 1129 ER_HOST_NOT_PRIVILEGED = 1130 ER_PASSWORD_ANONYMOUS_USER = 1131 ER_PASSWORD_NOT_ALLOWED = 1132 ER_PASSWORD_NO_MATCH = 1133 ER_UPDATE_INFO = 1134 ER_CANT_CREATE_THREAD = 1135 ER_WRONG_VALUE_COUNT_ON_ROW = 1136 ER_CANT_REOPEN_TABLE = 1137 ER_INVALID_USE_OF_NULL = 1138 ER_REGEXP_ERROR = 1139 ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 ER_NONEXISTING_GRANT = 1141 ER_TABLEACCESS_DENIED_ERROR = 1142 ER_COLUMNACCESS_DENIED_ERROR = 1143 ER_ILLEGAL_GRANT_FOR_TABLE = 1144 ER_GRANT_WRONG_HOST_OR_USER = 1145 ER_NO_SUCH_TABLE = 1146 ER_NONEXISTING_TABLE_GRANT = 1147 ER_NOT_ALLOWED_COMMAND = 1148 ER_SYNTAX_ERROR = 1149 ER_UNUSED1 = 1150 ER_UNUSED2 = 1151 ER_ABORTING_CONNECTION = 1152 ER_NET_PACKET_TOO_LARGE = 1153 ER_NET_READ_ERROR_FROM_PIPE = 1154 ER_NET_FCNTL_ERROR = 1155 ER_NET_PACKETS_OUT_OF_ORDER = 1156 ER_NET_UNCOMPRESS_ERROR = 1157 ER_NET_READ_ERROR = 1158 ER_NET_READ_INTERRUPTED = 1159 ER_NET_ERROR_ON_WRITE = 1160 ER_NET_WRITE_INTERRUPTED = 1161 ER_TOO_LONG_STRING = 1162 ER_TABLE_CANT_HANDLE_BLOB = 1163 ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 ER_UNUSED3 = 1165 ER_WRONG_COLUMN_NAME = 1166 ER_WRONG_KEY_COLUMN = 1167 ER_WRONG_MRG_TABLE = 1168 ER_DUP_UNIQUE = 1169 ER_BLOB_KEY_WITHOUT_LENGTH = 1170 ER_PRIMARY_CANT_HAVE_NULL = 1171 ER_TOO_MANY_ROWS = 1172 ER_REQUIRES_PRIMARY_KEY = 1173 ER_NO_RAID_COMPILED = 1174 ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 ER_KEY_DOES_NOT_EXITS = 1176 ER_CHECK_NO_SUCH_TABLE = 1177 ER_CHECK_NOT_IMPLEMENTED = 1178 ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 ER_ERROR_DURING_COMMIT = 1180 ER_ERROR_DURING_ROLLBACK = 1181 ER_ERROR_DURING_FLUSH_LOGS = 1182 ER_ERROR_DURING_CHECKPOINT = 1183 ER_NEW_ABORTING_CONNECTION = 1184 ER_DUMP_NOT_IMPLEMENTED = 1185 ER_FLUSH_MASTER_BINLOG_CLOSED = 1186 ER_INDEX_REBUILD = 1187 ER_MASTER = 1188 ER_MASTER_NET_READ = 1189 ER_MASTER_NET_WRITE = 1190 ER_FT_MATCHING_KEY_NOT_FOUND = 1191 ER_LOCK_OR_ACTIVE_TRANSACTION = 1192 ER_UNKNOWN_SYSTEM_VARIABLE = 1193 ER_CRASHED_ON_USAGE = 1194 ER_CRASHED_ON_REPAIR = 1195 ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196 ER_TRANS_CACHE_FULL = 1197 ER_SLAVE_MUST_STOP = 1198 ER_SLAVE_NOT_RUNNING = 1199 ER_BAD_SLAVE = 1200 ER_MASTER_INFO = 1201 ER_SLAVE_THREAD = 1202 ER_TOO_MANY_USER_CONNECTIONS = 1203 ER_SET_CONSTANTS_ONLY = 1204 ER_LOCK_WAIT_TIMEOUT = 1205 ER_LOCK_TABLE_FULL = 1206 ER_READ_ONLY_TRANSACTION = 1207 ER_DROP_DB_WITH_READ_LOCK = 1208 ER_CREATE_DB_WITH_READ_LOCK = 1209 ER_WRONG_ARGUMENTS = 1210 ER_NO_PERMISSION_TO_CREATE_USER = 1211 ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212 ER_LOCK_DEADLOCK = 1213 ER_TABLE_CANT_HANDLE_FT = 1214 ER_CANNOT_ADD_FOREIGN = 1215 ER_NO_REFERENCED_ROW = 1216 ER_ROW_IS_REFERENCED = 1217 ER_CONNECT_TO_MASTER = 1218 ER_QUERY_ON_MASTER = 1219 ER_ERROR_WHEN_EXECUTING_COMMAND = 1220 ER_WRONG_USAGE = 1221 ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 ER_CANT_UPDATE_WITH_READLOCK = 1223 ER_MIXING_NOT_ALLOWED = 1224 ER_DUP_ARGUMENT = 1225 ER_USER_LIMIT_REACHED = 1226 ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227 ER_LOCAL_VARIABLE = 1228 ER_GLOBAL_VARIABLE = 1229 ER_NO_DEFAULT = 1230 ER_WRONG_VALUE_FOR_VAR = 1231 ER_WRONG_TYPE_FOR_VAR = 1232 ER_VAR_CANT_BE_READ = 1233 ER_CANT_USE_OPTION_HERE = 1234 ER_NOT_SUPPORTED_YET = 1235 ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236 ER_SLAVE_IGNORED_TABLE = 1237 ER_INCORRECT_GLOBAL_LOCAL_VAR = 1238 ER_WRONG_FK_DEF = 1239 ER_KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 ER_OPERAND_COLUMNS = 1241 ER_SUBQUERY_NO_1_ROW = 1242 ER_UNKNOWN_STMT_HANDLER = 1243 ER_CORRUPT_HELP_DB = 1244 ER_CYCLIC_REFERENCE = 1245 ER_AUTO_CONVERT = 1246 ER_ILLEGAL_REFERENCE = 1247 ER_DERIVED_MUST_HAVE_ALIAS = 1248 ER_SELECT_REDUCED = 1249 ER_TABLENAME_NOT_ALLOWED_HERE = 1250 ER_NOT_SUPPORTED_AUTH_MODE = 1251 ER_SPATIAL_CANT_HAVE_NULL = 1252 ER_COLLATION_CHARSET_MISMATCH = 1253 ER_SLAVE_WAS_RUNNING = 1254 ER_SLAVE_WAS_NOT_RUNNING = 1255 ER_TOO_BIG_FOR_UNCOMPRESS = 1256 ER_ZLIB_Z_MEM_ERROR = 1257 ER_ZLIB_Z_BUF_ERROR = 1258 ER_ZLIB_Z_DATA_ERROR = 1259 ER_CUT_VALUE_GROUP_CONCAT = 1260 ER_WARN_TOO_FEW_RECORDS = 1261 ER_WARN_TOO_MANY_RECORDS = 1262 ER_WARN_NULL_TO_NOTNULL = 1263 ER_WARN_DATA_OUT_OF_RANGE = 1264 WARN_DATA_TRUNCATED = 1265 ER_WARN_USING_OTHER_HANDLER = 1266 ER_CANT_AGGREGATE_2COLLATIONS = 1267 ER_DROP_USER = 1268 ER_REVOKE_GRANTS = 1269 ER_CANT_AGGREGATE_3COLLATIONS = 1270 ER_CANT_AGGREGATE_NCOLLATIONS = 1271 ER_VARIABLE_IS_NOT_STRUCT = 1272 ER_UNKNOWN_COLLATION = 1273 ER_SLAVE_IGNORED_SSL_PARAMS = 1274 ER_SERVER_IS_IN_SECURE_AUTH_MODE = 1275 ER_WARN_FIELD_RESOLVED = 1276 ER_BAD_SLAVE_UNTIL_COND = 1277 ER_MISSING_SKIP_SLAVE = 1278 ER_UNTIL_COND_IGNORED = 1279 ER_WRONG_NAME_FOR_INDEX = 1280 ER_WRONG_NAME_FOR_CATALOG = 1281 ER_WARN_QC_RESIZE = 1282 ER_BAD_FT_COLUMN = 1283 ER_UNKNOWN_KEY_CACHE = 1284 ER_WARN_HOSTNAME_WONT_WORK = 1285 ER_UNKNOWN_STORAGE_ENGINE = 1286 ER_WARN_DEPRECATED_SYNTAX = 1287 ER_NON_UPDATABLE_TABLE = 1288 ER_FEATURE_DISABLED = 1289 ER_OPTION_PREVENTS_STATEMENT = 1290 ER_DUPLICATED_VALUE_IN_TYPE = 1291 ER_TRUNCATED_WRONG_VALUE = 1292 ER_TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 ER_INVALID_ON_UPDATE = 1294 ER_UNSUPPORTED_PS = 1295 ER_GET_ERRMSG = 1296 ER_GET_TEMPORARY_ERRMSG = 1297 ER_UNKNOWN_TIME_ZONE = 1298 ER_WARN_INVALID_TIMESTAMP = 1299 ER_INVALID_CHARACTER_STRING = 1300 ER_WARN_ALLOWED_PACKET_OVERFLOWED = 1301 ER_CONFLICTING_DECLARATIONS = 1302 ER_SP_NO_RECURSIVE_CREATE = 1303 ER_SP_ALREADY_EXISTS = 1304 ER_SP_DOES_NOT_EXIST = 1305 ER_SP_DROP_FAILED = 1306 ER_SP_STORE_FAILED = 1307 ER_SP_LILABEL_MISMATCH = 1308 ER_SP_LABEL_REDEFINE = 1309 ER_SP_LABEL_MISMATCH = 1310 ER_SP_UNINIT_VAR = 1311 ER_SP_BADSELECT = 1312 ER_SP_BADRETURN = 1313 ER_SP_BADSTATEMENT = 1314 ER_UPDATE_LOG_DEPRECATED_IGNORED = 1315 ER_UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 ER_QUERY_INTERRUPTED = 1317 ER_SP_WRONG_NO_OF_ARGS = 1318 ER_SP_COND_MISMATCH = 1319 ER_SP_NORETURN = 1320 ER_SP_NORETURNEND = 1321 ER_SP_BAD_CURSOR_QUERY = 1322 ER_SP_BAD_CURSOR_SELECT = 1323 ER_SP_CURSOR_MISMATCH = 1324 ER_SP_CURSOR_ALREADY_OPEN = 1325 ER_SP_CURSOR_NOT_OPEN = 1326 ER_SP_UNDECLARED_VAR = 1327 ER_SP_WRONG_NO_OF_FETCH_ARGS = 1328 ER_SP_FETCH_NO_DATA = 1329 ER_SP_DUP_PARAM = 1330 ER_SP_DUP_VAR = 1331 ER_SP_DUP_COND = 1332 ER_SP_DUP_CURS = 1333 ER_SP_CANT_ALTER = 1334 ER_SP_SUBSELECT_NYI = 1335 ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 ER_SP_VARCOND_AFTER_CURSHNDLR = 1337 ER_SP_CURSOR_AFTER_HANDLER = 1338 ER_SP_CASE_NOT_FOUND = 1339 ER_FPARSER_TOO_BIG_FILE = 1340 ER_FPARSER_BAD_HEADER = 1341 ER_FPARSER_EOF_IN_COMMENT = 1342 ER_FPARSER_ERROR_IN_PARAMETER = 1343 ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 ER_VIEW_NO_EXPLAIN = 1345 ER_FRM_UNKNOWN_TYPE = 1346 ER_WRONG_OBJECT = 1347 ER_NONUPDATEABLE_COLUMN = 1348 ER_VIEW_SELECT_DERIVED = 1349 ER_VIEW_SELECT_CLAUSE = 1350 ER_VIEW_SELECT_VARIABLE = 1351 ER_VIEW_SELECT_TMPTABLE = 1352 ER_VIEW_WRONG_LIST = 1353 ER_WARN_VIEW_MERGE = 1354 ER_WARN_VIEW_WITHOUT_KEY = 1355 ER_VIEW_INVALID = 1356 ER_SP_NO_DROP_SP = 1357 ER_SP_GOTO_IN_HNDLR = 1358 ER_TRG_ALREADY_EXISTS = 1359 ER_TRG_DOES_NOT_EXIST = 1360 ER_TRG_ON_VIEW_OR_TEMP_TABLE = 1361 ER_TRG_CANT_CHANGE_ROW = 1362 ER_TRG_NO_SUCH_ROW_IN_TRG = 1363 ER_NO_DEFAULT_FOR_FIELD = 1364 ER_DIVISION_BY_ZERO = 1365 ER_TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 ER_ILLEGAL_VALUE_FOR_TYPE = 1367 ER_VIEW_NONUPD_CHECK = 1368 ER_VIEW_CHECK_FAILED = 1369 ER_PROCACCESS_DENIED_ERROR = 1370 ER_RELAY_LOG_FAIL = 1371 ER_PASSWD_LENGTH = 1372 ER_UNKNOWN_TARGET_BINLOG = 1373 ER_IO_ERR_LOG_INDEX_READ = 1374 ER_BINLOG_PURGE_PROHIBITED = 1375 ER_FSEEK_FAIL = 1376 ER_BINLOG_PURGE_FATAL_ERR = 1377 ER_LOG_IN_USE = 1378 ER_LOG_PURGE_UNKNOWN_ERR = 1379 ER_RELAY_LOG_INIT = 1380 ER_NO_BINARY_LOGGING = 1381 ER_RESERVED_SYNTAX = 1382 ER_WSAS_FAILED = 1383 ER_DIFF_GROUPS_PROC = 1384 ER_NO_GROUP_FOR_PROC = 1385 ER_ORDER_WITH_PROC = 1386 ER_LOGGING_PROHIBIT_CHANGING_OF = 1387 ER_NO_FILE_MAPPING = 1388 ER_WRONG_MAGIC = 1389 ER_PS_MANY_PARAM = 1390 ER_KEY_PART_0 = 1391 ER_VIEW_CHECKSUM = 1392 ER_VIEW_MULTIUPDATE = 1393 ER_VIEW_NO_INSERT_FIELD_LIST = 1394 ER_VIEW_DELETE_MERGE_VIEW = 1395 ER_CANNOT_USER = 1396 ER_XAER_NOTA = 1397 ER_XAER_INVAL = 1398 ER_XAER_RMFAIL = 1399 ER_XAER_OUTSIDE = 1400 ER_XAER_RMERR = 1401 ER_XA_RBROLLBACK = 1402 ER_NONEXISTING_PROC_GRANT = 1403 ER_PROC_AUTO_GRANT_FAIL = 1404 ER_PROC_AUTO_REVOKE_FAIL = 1405 ER_DATA_TOO_LONG = 1406 ER_SP_BAD_SQLSTATE = 1407 ER_STARTUP = 1408 ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 ER_CANT_CREATE_USER_WITH_GRANT = 1410 ER_WRONG_VALUE_FOR_TYPE = 1411 ER_TABLE_DEF_CHANGED = 1412 ER_SP_DUP_HANDLER = 1413 ER_SP_NOT_VAR_ARG = 1414 ER_SP_NO_RETSET = 1415 ER_CANT_CREATE_GEOMETRY_OBJECT = 1416 ER_FAILED_ROUTINE_BREAK_BINLOG = 1417 ER_BINLOG_UNSAFE_ROUTINE = 1418 ER_BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 ER_EXEC_STMT_WITH_OPEN_CURSOR = 1420 ER_STMT_HAS_NO_OPEN_CURSOR = 1421 ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 ER_NO_DEFAULT_FOR_VIEW_FIELD = 1423 ER_SP_NO_RECURSION = 1424 ER_TOO_BIG_SCALE = 1425 ER_TOO_BIG_PRECISION = 1426 ER_M_BIGGER_THAN_D = 1427 ER_WRONG_LOCK_OF_SYSTEM_TABLE = 1428 ER_CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 ER_QUERY_ON_FOREIGN_DATA_SOURCE = 1430 ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 ER_FOREIGN_DATA_STRING_INVALID = 1433 ER_CANT_CREATE_FEDERATED_TABLE = 1434 ER_TRG_IN_WRONG_SCHEMA = 1435 ER_STACK_OVERRUN_NEED_MORE = 1436 ER_TOO_LONG_BODY = 1437 ER_WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 ER_TOO_BIG_DISPLAYWIDTH = 1439 ER_XAER_DUPID = 1440 ER_DATETIME_FUNCTION_OVERFLOW = 1441 ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 ER_VIEW_PREVENT_UPDATE = 1443 ER_PS_NO_RECURSION = 1444 ER_SP_CANT_SET_AUTOCOMMIT = 1445 ER_MALFORMED_DEFINER = 1446 ER_VIEW_FRM_NO_USER = 1447 ER_VIEW_OTHER_USER = 1448 ER_NO_SUCH_USER = 1449 ER_FORBID_SCHEMA_CHANGE = 1450 ER_ROW_IS_REFERENCED_2 = 1451 ER_NO_REFERENCED_ROW_2 = 1452 ER_SP_BAD_VAR_SHADOW = 1453 ER_TRG_NO_DEFINER = 1454 ER_OLD_FILE_FORMAT = 1455 ER_SP_RECURSION_LIMIT = 1456 ER_SP_PROC_TABLE_CORRUPT = 1457 ER_SP_WRONG_NAME = 1458 ER_TABLE_NEEDS_UPGRADE = 1459 ER_SP_NO_AGGREGATE = 1460 ER_MAX_PREPARED_STMT_COUNT_REACHED = 1461 ER_VIEW_RECURSIVE = 1462 ER_NON_GROUPING_FIELD_USED = 1463 ER_TABLE_CANT_HANDLE_SPKEYS = 1464 ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA = 1465 ER_REMOVED_SPACES = 1466 ER_AUTOINC_READ_FAILED = 1467 ER_USERNAME = 1468 ER_HOSTNAME = 1469 ER_WRONG_STRING_LENGTH = 1470 ER_NON_INSERTABLE_TABLE = 1471 ER_ADMIN_WRONG_MRG_TABLE = 1472 ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT = 1473 ER_NAME_BECOMES_EMPTY = 1474 ER_AMBIGUOUS_FIELD_TERM = 1475 ER_FOREIGN_SERVER_EXISTS = 1476 ER_FOREIGN_SERVER_DOESNT_EXIST = 1477 ER_ILLEGAL_HA_CREATE_OPTION = 1478 ER_PARTITION_REQUIRES_VALUES_ERROR = 1479 ER_PARTITION_WRONG_VALUES_ERROR = 1480 ER_PARTITION_MAXVALUE_ERROR = 1481 ER_PARTITION_SUBPARTITION_ERROR = 1482 ER_PARTITION_SUBPART_MIX_ERROR = 1483 ER_PARTITION_WRONG_NO_PART_ERROR = 1484 ER_PARTITION_WRONG_NO_SUBPART_ERROR = 1485 ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR = 1486 ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR = 1487 ER_FIELD_NOT_FOUND_PART_ERROR = 1488 ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR = 1489 ER_INCONSISTENT_PARTITION_INFO_ERROR = 1490 ER_PARTITION_FUNC_NOT_ALLOWED_ERROR = 1491 ER_PARTITIONS_MUST_BE_DEFINED_ERROR = 1492 ER_RANGE_NOT_INCREASING_ERROR = 1493 ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR = 1494 ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR = 1495 ER_PARTITION_ENTRY_ERROR = 1496 ER_MIX_HANDLER_ERROR = 1497 ER_PARTITION_NOT_DEFINED_ERROR = 1498 ER_TOO_MANY_PARTITIONS_ERROR = 1499 ER_SUBPARTITION_ERROR = 1500 ER_CANT_CREATE_HANDLER_FILE = 1501 ER_BLOB_FIELD_IN_PART_FUNC_ERROR = 1502 ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF = 1503 ER_NO_PARTS_ERROR = 1504 ER_PARTITION_MGMT_ON_NONPARTITIONED = 1505 ER_FOREIGN_KEY_ON_PARTITIONED = 1506 ER_DROP_PARTITION_NON_EXISTENT = 1507 ER_DROP_LAST_PARTITION = 1508 ER_COALESCE_ONLY_ON_HASH_PARTITION = 1509 ER_REORG_HASH_ONLY_ON_SAME_NO = 1510 ER_REORG_NO_PARAM_ERROR = 1511 ER_ONLY_ON_RANGE_LIST_PARTITION = 1512 ER_ADD_PARTITION_SUBPART_ERROR = 1513 ER_ADD_PARTITION_NO_NEW_PARTITION = 1514 ER_COALESCE_PARTITION_NO_PARTITION = 1515 ER_REORG_PARTITION_NOT_EXIST = 1516 ER_SAME_NAME_PARTITION = 1517 ER_NO_BINLOG_ERROR = 1518 ER_CONSECUTIVE_REORG_PARTITIONS = 1519 ER_REORG_OUTSIDE_RANGE = 1520 ER_PARTITION_FUNCTION_FAILURE = 1521 ER_PART_STATE_ERROR = 1522 ER_LIMITED_PART_RANGE = 1523 ER_PLUGIN_IS_NOT_LOADED = 1524 ER_WRONG_VALUE = 1525 ER_NO_PARTITION_FOR_GIVEN_VALUE = 1526 ER_FILEGROUP_OPTION_ONLY_ONCE = 1527 ER_CREATE_FILEGROUP_FAILED = 1528 ER_DROP_FILEGROUP_FAILED = 1529 ER_TABLESPACE_AUTO_EXTEND_ERROR = 1530 ER_WRONG_SIZE_NUMBER = 1531 ER_SIZE_OVERFLOW_ERROR = 1532 ER_ALTER_FILEGROUP_FAILED = 1533 ER_BINLOG_ROW_LOGGING_FAILED = 1534 ER_BINLOG_ROW_WRONG_TABLE_DEF = 1535 ER_BINLOG_ROW_RBR_TO_SBR = 1536 ER_EVENT_ALREADY_EXISTS = 1537 ER_EVENT_STORE_FAILED = 1538 ER_EVENT_DOES_NOT_EXIST = 1539 ER_EVENT_CANT_ALTER = 1540 ER_EVENT_DROP_FAILED = 1541 ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG = 1542 ER_EVENT_ENDS_BEFORE_STARTS = 1543 ER_EVENT_EXEC_TIME_IN_THE_PAST = 1544 ER_EVENT_OPEN_TABLE_FAILED = 1545 ER_EVENT_NEITHER_M_EXPR_NOR_M_AT = 1546 ER_OBSOLETE_COL_COUNT_DOESNT_MATCH_CORRUPTED = 1547 ER_OBSOLETE_CANNOT_LOAD_FROM_TABLE = 1548 ER_EVENT_CANNOT_DELETE = 1549 ER_EVENT_COMPILE_ERROR = 1550 ER_EVENT_SAME_NAME = 1551 ER_EVENT_DATA_TOO_LONG = 1552 ER_DROP_INDEX_FK = 1553 ER_WARN_DEPRECATED_SYNTAX_WITH_VER = 1554 ER_CANT_WRITE_LOCK_LOG_TABLE = 1555 ER_CANT_LOCK_LOG_TABLE = 1556 ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED = 1557 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE = 1558 ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR = 1559 ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1560 ER_NDB_CANT_SWITCH_BINLOG_FORMAT = 1561 ER_PARTITION_NO_TEMPORARY = 1562 ER_PARTITION_CONST_DOMAIN_ERROR = 1563 ER_PARTITION_FUNCTION_IS_NOT_ALLOWED = 1564 ER_DDL_LOG_ERROR = 1565 ER_NULL_IN_VALUES_LESS_THAN = 1566 ER_WRONG_PARTITION_NAME = 1567 ER_CANT_CHANGE_TX_CHARACTERISTICS = 1568 ER_DUP_ENTRY_AUTOINCREMENT_CASE = 1569 ER_EVENT_MODIFY_QUEUE_ERROR = 1570 ER_EVENT_SET_VAR_ERROR = 1571 ER_PARTITION_MERGE_ERROR = 1572 ER_CANT_ACTIVATE_LOG = 1573 ER_RBR_NOT_AVAILABLE = 1574 ER_BASE64_DECODE_ERROR = 1575 ER_EVENT_RECURSION_FORBIDDEN = 1576 ER_EVENTS_DB_ERROR = 1577 ER_ONLY_INTEGERS_ALLOWED = 1578 ER_UNSUPORTED_LOG_ENGINE = 1579 ER_BAD_LOG_STATEMENT = 1580 ER_CANT_RENAME_LOG_TABLE = 1581 ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT = 1582 ER_WRONG_PARAMETERS_TO_NATIVE_FCT = 1583 ER_WRONG_PARAMETERS_TO_STORED_FCT = 1584 ER_NATIVE_FCT_NAME_COLLISION = 1585 ER_DUP_ENTRY_WITH_KEY_NAME = 1586 ER_BINLOG_PURGE_EMFILE = 1587 ER_EVENT_CANNOT_CREATE_IN_THE_PAST = 1588 ER_EVENT_CANNOT_ALTER_IN_THE_PAST = 1589 ER_SLAVE_INCIDENT = 1590 ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT = 1591 ER_BINLOG_UNSAFE_STATEMENT = 1592 ER_SLAVE_FATAL_ERROR = 1593 ER_SLAVE_RELAY_LOG_READ_FAILURE = 1594 ER_SLAVE_RELAY_LOG_WRITE_FAILURE = 1595 ER_SLAVE_CREATE_EVENT_FAILURE = 1596 ER_SLAVE_MASTER_COM_FAILURE = 1597 ER_BINLOG_LOGGING_IMPOSSIBLE = 1598 ER_VIEW_NO_CREATION_CTX = 1599 ER_VIEW_INVALID_CREATION_CTX = 1600 ER_SR_INVALID_CREATION_CTX = 1601 ER_TRG_CORRUPTED_FILE = 1602 ER_TRG_NO_CREATION_CTX = 1603 ER_TRG_INVALID_CREATION_CTX = 1604 ER_EVENT_INVALID_CREATION_CTX = 1605 ER_TRG_CANT_OPEN_TABLE = 1606 ER_CANT_CREATE_SROUTINE = 1607 ER_NEVER_USED = 1608 ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT = 1609 ER_SLAVE_CORRUPT_EVENT = 1610 ER_LOAD_DATA_INVALID_COLUMN = 1611 ER_LOG_PURGE_NO_FILE = 1612 ER_XA_RBTIMEOUT = 1613 ER_XA_RBDEADLOCK = 1614 ER_NEED_REPREPARE = 1615 ER_DELAYED_NOT_SUPPORTED = 1616 WARN_NO_MASTER_INFO = 1617 WARN_OPTION_IGNORED = 1618 WARN_PLUGIN_DELETE_BUILTIN = 1619 WARN_PLUGIN_BUSY = 1620 ER_VARIABLE_IS_READONLY = 1621 ER_WARN_ENGINE_TRANSACTION_ROLLBACK = 1622 ER_SLAVE_HEARTBEAT_FAILURE = 1623 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE = 1624 ER_NDB_REPLICATION_SCHEMA_ERROR = 1625 ER_CONFLICT_FN_PARSE_ERROR = 1626 ER_EXCEPTIONS_WRITE_ERROR = 1627 ER_TOO_LONG_TABLE_COMMENT = 1628 ER_TOO_LONG_FIELD_COMMENT = 1629 ER_FUNC_INEXISTENT_NAME_COLLISION = 1630 ER_DATABASE_NAME = 1631 ER_TABLE_NAME = 1632 ER_PARTITION_NAME = 1633 ER_SUBPARTITION_NAME = 1634 ER_TEMPORARY_NAME = 1635 ER_RENAMED_NAME = 1636 ER_TOO_MANY_CONCURRENT_TRXS = 1637 WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED = 1638 ER_DEBUG_SYNC_TIMEOUT = 1639 ER_DEBUG_SYNC_HIT_LIMIT = 1640 ER_DUP_SIGNAL_SET = 1641 ER_SIGNAL_WARN = 1642 ER_SIGNAL_NOT_FOUND = 1643 ER_SIGNAL_EXCEPTION = 1644 ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER = 1645 ER_SIGNAL_BAD_CONDITION_TYPE = 1646 WARN_COND_ITEM_TRUNCATED = 1647 ER_COND_ITEM_TOO_LONG = 1648 ER_UNKNOWN_LOCALE = 1649 ER_SLAVE_IGNORE_SERVER_IDS = 1650 ER_QUERY_CACHE_DISABLED = 1651 ER_SAME_NAME_PARTITION_FIELD = 1652 ER_PARTITION_COLUMN_LIST_ERROR = 1653 ER_WRONG_TYPE_COLUMN_VALUE_ERROR = 1654 ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR = 1655 ER_MAXVALUE_IN_VALUES_IN = 1656 ER_TOO_MANY_VALUES_ERROR = 1657 ER_ROW_SINGLE_PARTITION_FIELD_ERROR = 1658 ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD = 1659 ER_PARTITION_FIELDS_TOO_LONG = 1660 ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE = 1661 ER_BINLOG_ROW_MODE_AND_STMT_ENGINE = 1662 ER_BINLOG_UNSAFE_AND_STMT_ENGINE = 1663 ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE = 1664 ER_BINLOG_STMT_MODE_AND_ROW_ENGINE = 1665 ER_BINLOG_ROW_INJECTION_AND_STMT_MODE = 1666 ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1667 ER_BINLOG_UNSAFE_LIMIT = 1668 ER_UNUSED4 = 1669 ER_BINLOG_UNSAFE_SYSTEM_TABLE = 1670 ER_BINLOG_UNSAFE_AUTOINC_COLUMNS = 1671 ER_BINLOG_UNSAFE_UDF = 1672 ER_BINLOG_UNSAFE_SYSTEM_VARIABLE = 1673 ER_BINLOG_UNSAFE_SYSTEM_FUNCTION = 1674 ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS = 1675 ER_MESSAGE_AND_STATEMENT = 1676 ER_SLAVE_CONVERSION_FAILED = 1677 ER_SLAVE_CANT_CREATE_CONVERSION = 1678 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1679 ER_PATH_LENGTH = 1680 ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT = 1681 ER_WRONG_NATIVE_TABLE_STRUCTURE = 1682 ER_WRONG_PERFSCHEMA_USAGE = 1683 ER_WARN_I_S_SKIPPED_TABLE = 1684 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1685 ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1686 ER_SPATIAL_MUST_HAVE_GEOM_COL = 1687 ER_TOO_LONG_INDEX_COMMENT = 1688 ER_LOCK_ABORTED = 1689 ER_DATA_OUT_OF_RANGE = 1690 ER_WRONG_SPVAR_TYPE_IN_LIMIT = 1691 ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1692 ER_BINLOG_UNSAFE_MIXED_STATEMENT = 1693 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1694 ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1695 ER_FAILED_READ_FROM_PAR_FILE = 1696 ER_VALUES_IS_NOT_INT_TYPE_ERROR = 1697 ER_ACCESS_DENIED_NO_PASSWORD_ERROR = 1698 ER_SET_PASSWORD_AUTH_PLUGIN = 1699 ER_GRANT_PLUGIN_USER_EXISTS = 1700 ER_TRUNCATE_ILLEGAL_FK = 1701 ER_PLUGIN_IS_PERMANENT = 1702 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN = 1703 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX = 1704 ER_STMT_CACHE_FULL = 1705 ER_MULTI_UPDATE_KEY_CONFLICT = 1706 ER_TABLE_NEEDS_REBUILD = 1707 WARN_OPTION_BELOW_LIMIT = 1708 ER_INDEX_COLUMN_TOO_LONG = 1709 ER_ERROR_IN_TRIGGER_BODY = 1710 ER_ERROR_IN_UNKNOWN_TRIGGER_BODY = 1711 ER_INDEX_CORRUPT = 1712 ER_UNDO_RECORD_TOO_BIG = 1713 ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT = 1714 ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE = 1715 ER_BINLOG_UNSAFE_REPLACE_SELECT = 1716 ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT = 1717 ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT = 1718 ER_BINLOG_UNSAFE_UPDATE_IGNORE = 1719 ER_PLUGIN_NO_UNINSTALL = 1720 ER_PLUGIN_NO_INSTALL = 1721 ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT = 1722 ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC = 1723 ER_BINLOG_UNSAFE_INSERT_TWO_KEYS = 1724 ER_TABLE_IN_FK_CHECK = 1725 ER_UNSUPPORTED_ENGINE = 1726 ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST = 1727 ER_CANNOT_LOAD_FROM_TABLE_V2 = 1728 ER_MASTER_DELAY_VALUE_OUT_OF_RANGE = 1729 ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT = 1730 ER_PARTITION_EXCHANGE_DIFFERENT_OPTION = 1731 ER_PARTITION_EXCHANGE_PART_TABLE = 1732 ER_PARTITION_EXCHANGE_TEMP_TABLE = 1733 ER_PARTITION_INSTEAD_OF_SUBPARTITION = 1734 ER_UNKNOWN_PARTITION = 1735 ER_TABLES_DIFFERENT_METADATA = 1736 ER_ROW_DOES_NOT_MATCH_PARTITION = 1737 ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX = 1738 ER_WARN_INDEX_NOT_APPLICABLE = 1739 ER_PARTITION_EXCHANGE_FOREIGN_KEY = 1740 ER_NO_SUCH_KEY_VALUE = 1741 ER_RPL_INFO_DATA_TOO_LONG = 1742 ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE = 1743 ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE = 1744 ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX = 1745 ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT = 1746 ER_PARTITION_CLAUSE_ON_NONPARTITIONED = 1747 ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET = 1748 ER_NO_SUCH_PARTITION__UNUSED = 1749 ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE = 1750 ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE = 1751 ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE = 1752 ER_MTS_FEATURE_IS_NOT_SUPPORTED = 1753 ER_MTS_UPDATED_DBS_GREATER_MAX = 1754 ER_MTS_CANT_PARALLEL = 1755 ER_MTS_INCONSISTENT_DATA = 1756 ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING = 1757 ER_DA_INVALID_CONDITION_NUMBER = 1758 ER_INSECURE_PLAIN_TEXT = 1759 ER_INSECURE_CHANGE_MASTER = 1760 ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO = 1761 ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO = 1762 ER_SQLTHREAD_WITH_SECURE_SLAVE = 1763 ER_TABLE_HAS_NO_FT = 1764 ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER = 1765 ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION = 1766 ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST = 1767 ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL = 1768 ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION = 1769 ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL = 1770 ER_SKIPPING_LOGGED_TRANSACTION = 1771 ER_MALFORMED_GTID_SET_SPECIFICATION = 1772 ER_MALFORMED_GTID_SET_ENCODING = 1773 ER_MALFORMED_GTID_SPECIFICATION = 1774 ER_GNO_EXHAUSTED = 1775 ER_BAD_SLAVE_AUTO_POSITION = 1776 ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON = 1777 ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET = 1778 ER_GTID_MODE_2_OR_3_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON = 1779 ER_GTID_MODE_REQUIRES_BINLOG = 1780 ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF = 1781 ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON = 1782 ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF = 1783 ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF = 1784 ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE = 1785 ER_GTID_UNSAFE_CREATE_SELECT = 1786 ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION = 1787 ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME = 1788 ER_MASTER_HAS_PURGED_REQUIRED_GTIDS = 1789 ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID = 1790 ER_UNKNOWN_EXPLAIN_FORMAT = 1791 ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION = 1792 ER_TOO_LONG_TABLE_PARTITION_COMMENT = 1793 ER_SLAVE_CONFIGURATION = 1794 ER_INNODB_FT_LIMIT = 1795 ER_INNODB_NO_FT_TEMP_TABLE = 1796 ER_INNODB_FT_WRONG_DOCID_COLUMN = 1797 ER_INNODB_FT_WRONG_DOCID_INDEX = 1798 ER_INNODB_ONLINE_LOG_TOO_BIG = 1799 ER_UNKNOWN_ALTER_ALGORITHM = 1800 ER_UNKNOWN_ALTER_LOCK = 1801 ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS = 1802 ER_MTS_RECOVERY_FAILURE = 1803 ER_MTS_RESET_WORKERS = 1804 ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 = 1805 ER_SLAVE_SILENT_RETRY_TRANSACTION = 1806 ER_DISCARD_FK_CHECKS_RUNNING = 1807 ER_TABLE_SCHEMA_MISMATCH = 1808 ER_TABLE_IN_SYSTEM_TABLESPACE = 1809 ER_IO_READ_ERROR = 1810 ER_IO_WRITE_ERROR = 1811 ER_TABLESPACE_MISSING = 1812 ER_TABLESPACE_EXISTS = 1813 ER_TABLESPACE_DISCARDED = 1814 ER_INTERNAL_ERROR = 1815 ER_INNODB_IMPORT_ERROR = 1816 ER_INNODB_INDEX_CORRUPT = 1817 ER_INVALID_YEAR_COLUMN_LENGTH = 1818 ER_NOT_VALID_PASSWORD = 1819 ER_MUST_CHANGE_PASSWORD = 1820 ER_FK_NO_INDEX_CHILD = 1821 ER_FK_NO_INDEX_PARENT = 1822 ER_FK_FAIL_ADD_SYSTEM = 1823 ER_FK_CANNOT_OPEN_PARENT = 1824 ER_FK_INCORRECT_OPTION = 1825 ER_FK_DUP_NAME = 1826 ER_PASSWORD_FORMAT = 1827 ER_FK_COLUMN_CANNOT_DROP = 1828 ER_FK_COLUMN_CANNOT_DROP_CHILD = 1829 ER_FK_COLUMN_NOT_NULL = 1830 ER_DUP_INDEX = 1831 ER_FK_COLUMN_CANNOT_CHANGE = 1832 ER_FK_COLUMN_CANNOT_CHANGE_CHILD = 1833 ER_FK_CANNOT_DELETE_PARENT = 1834 ER_MALFORMED_PACKET = 1835 ER_READ_ONLY_MODE = 1836 ER_GTID_NEXT_TYPE_UNDEFINED_GROUP = 1837 ER_VARIABLE_NOT_SETTABLE_IN_SP = 1838 ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF = 1839 ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY = 1840 ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY = 1841 ER_GTID_PURGED_WAS_CHANGED = 1842 ER_GTID_EXECUTED_WAS_CHANGED = 1843 ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES = 1844 ER_ALTER_OPERATION_NOT_SUPPORTED = 1845 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON = 1846 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY = 1847 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION = 1848 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME = 1849 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE = 1850 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK = 1851 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE = 1852 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK = 1853 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC = 1854 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS = 1855 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS = 1856 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS = 1857 ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE = 1858 ER_DUP_UNKNOWN_IN_INDEX = 1859 ER_IDENT_CAUSES_TOO_LONG_PATH = 1860 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL = 1861 ER_MUST_CHANGE_PASSWORD_LOGIN = 1862 ER_ROW_IN_WRONG_PARTITION = 1863 ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX = 1864 ER_INNODB_NO_FT_USES_PARSER = 1865 ER_BINLOG_LOGICAL_CORRUPTION = 1866 ER_WARN_PURGE_LOG_IN_USE = 1867 ER_WARN_PURGE_LOG_IS_ACTIVE = 1868 ER_AUTO_INCREMENT_CONFLICT = 1869 WARN_ON_BLOCKHOLE_IN_RBR = 1870 ER_SLAVE_MI_INIT_REPOSITORY = 1871 ER_SLAVE_RLI_INIT_REPOSITORY = 1872 ER_ACCESS_DENIED_CHANGE_USER_ERROR = 1873 ER_INNODB_READ_ONLY = 1874 ER_STOP_SLAVE_SQL_THREAD_TIMEOUT = 1875 ER_STOP_SLAVE_IO_THREAD_TIMEOUT = 1876 ER_TABLE_CORRUPT = 1877 ER_FILE_CORRUPT = 1878 ER_ERROR_ON_MASTER = 1879 ER_INCONSISTENT_ERROR = 1880 ER_STORAGE_ENGINE_NOT_LOADED = 1881 ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER = 1882 ER_WARN_LEGACY_SYNTAX_CONVERTED = 1883 ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN = 1884 ER_CANNOT_DISCARD_TEMPORARY_TABLE = 1885 ER_FK_DEPTH_EXCEEDED = 1886 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 = 1887 ER_WARN_TRIGGER_DOESNT_HAVE_CREATED = 1888 ER_REFERENCED_TRG_DOES_NOT_EXIST = 1889 ER_EXPLAIN_NOT_SUPPORTED = 1890 ER_INVALID_FIELD_SIZE = 1891 ER_MISSING_HA_CREATE_OPTION = 1892 CR_UNKNOWN_ERROR = 2000 CR_SOCKET_CREATE_ERROR = 2001 CR_CONNECTION_ERROR = 2002 CR_CONN_HOST_ERROR = 2003 CR_IPSOCK_ERROR = 2004 CR_UNKNOWN_HOST = 2005 CR_SERVER_GONE_ERROR = 2006 CR_VERSION_ERROR = 2007 CR_OUT_OF_MEMORY = 2008 CR_WRONG_HOST_INFO = 2009 CR_LOCALHOST_CONNECTION = 2010 CR_TCP_CONNECTION = 2011 CR_SERVER_HANDSHAKE_ERR = 2012 CR_SERVER_LOST = 2013 CR_COMMANDS_OUT_OF_SYNC = 2014 CR_NAMEDPIPE_CONNECTION = 2015 CR_NAMEDPIPEWAIT_ERROR = 2016 CR_NAMEDPIPEOPEN_ERROR = 2017 CR_NAMEDPIPESETSTATE_ERROR = 2018 CR_CANT_READ_CHARSET = 2019 CR_NET_PACKET_TOO_LARGE = 2020 CR_EMBEDDED_CONNECTION = 2021 CR_PROBE_SLAVE_STATUS = 2022 CR_PROBE_SLAVE_HOSTS = 2023 CR_PROBE_SLAVE_CONNECT = 2024 CR_PROBE_MASTER_CONNECT = 2025 CR_SSL_CONNECTION_ERROR = 2026 CR_MALFORMED_PACKET = 2027 CR_WRONG_LICENSE = 2028 CR_NULL_POINTER = 2029 CR_NO_PREPARE_STMT = 2030 CR_PARAMS_NOT_BOUND = 2031 CR_DATA_TRUNCATED = 2032 CR_NO_PARAMETERS_EXISTS = 2033 CR_INVALID_PARAMETER_NO = 2034 CR_INVALID_BUFFER_USE = 2035 CR_UNSUPPORTED_PARAM_TYPE = 2036 CR_SHARED_MEMORY_CONNECTION = 2037 CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR = 2038 CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR = 2039 CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR = 2040 CR_SHARED_MEMORY_CONNECT_MAP_ERROR = 2041 CR_SHARED_MEMORY_FILE_MAP_ERROR = 2042 CR_SHARED_MEMORY_MAP_ERROR = 2043 CR_SHARED_MEMORY_EVENT_ERROR = 2044 CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR = 2045 CR_SHARED_MEMORY_CONNECT_SET_ERROR = 2046 CR_CONN_UNKNOW_PROTOCOL = 2047 CR_INVALID_CONN_HANDLE = 2048 CR_SECURE_AUTH = 2049 CR_FETCH_CANCELED = 2050 CR_NO_DATA = 2051 CR_NO_STMT_METADATA = 2052 CR_NO_RESULT_SET = 2053 CR_NOT_IMPLEMENTED = 2054 CR_SERVER_LOST_EXTENDED = 2055 CR_STMT_CLOSED = 2056 CR_NEW_STMT_METADATA = 2057 CR_ALREADY_CONNECTED = 2058 CR_AUTH_PLUGIN_CANNOT_LOAD = 2059 CR_DUPLICATE_CONNECTION_ATTR = 2060 CR_AUTH_PLUGIN_ERR = 2061 # End MySQL Errors mysql-connector-python-1.1.6/python2/mysql/connector/dbapi.py0000644001577100000120000000431412276514013023637 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ This module implements some constructors and singletons as required by the DB API v2.0 (PEP-249). """ # Python Db API v2 apilevel = '2.0' threadsafety = 1 paramstyle = 'pyformat' import time import datetime from mysql.connector import constants class _DBAPITypeObject: def __init__(self, *values): self.values = values def __cmp__(self, other): if other in self.values: return 0 if other < self.values: return 1 else: return -1 Date = datetime.date Time = datetime.time Timestamp = datetime.datetime def DateFromTicks(ticks): return Date(*time.localtime(ticks)[:3]) def TimeFromTicks(ticks): return Time(*time.localtime(ticks)[3:6]) def TimestampFromTicks(ticks): return Timestamp(*time.localtime(ticks)[:6]) Binary = str STRING = _DBAPITypeObject(constants.FieldType.get_string_types()) BINARY = _DBAPITypeObject(constants.FieldType.get_binary_types()) NUMBER = _DBAPITypeObject(constants.FieldType.get_number_types()) DATETIME = _DBAPITypeObject(constants.FieldType.get_timestamp_types()) ROWID = _DBAPITypeObject() mysql-connector-python-1.1.6/python2/mysql/connector/locales/0000755001577100000120000000000012276514327023636 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/connector/locales/eng/0000755001577100000120000000000012276514327024407 5ustar pb2userwheelmysql-connector-python-1.1.6/python2/mysql/connector/locales/eng/client_error.py0000644001577100000120000001356512276514013027452 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. _GENERATED_ON = '2013-10-04' _MYSQL_VERSION = (5, 7, 2) # Start MySQL Error messages CR_UNKNOWN_ERROR = u"Unknown MySQL error" CR_SOCKET_CREATE_ERROR = u"Can't create UNIX socket (%s)" CR_CONNECTION_ERROR = u"Can't connect to local MySQL server through socket '%-.100s' (%s)" CR_CONN_HOST_ERROR = u"Can't connect to MySQL server on '%-.100s' (%s)" CR_IPSOCK_ERROR = u"Can't create TCP/IP socket (%s)" CR_UNKNOWN_HOST = u"Unknown MySQL server host '%-.100s' (%s)" CR_SERVER_GONE_ERROR = u"MySQL server has gone away" CR_VERSION_ERROR = u"Protocol mismatch; server version = %s, client version = %s" CR_OUT_OF_MEMORY = u"MySQL client ran out of memory" CR_WRONG_HOST_INFO = u"Wrong host info" CR_LOCALHOST_CONNECTION = u"Localhost via UNIX socket" CR_TCP_CONNECTION = u"%-.100s via TCP/IP" CR_SERVER_HANDSHAKE_ERR = u"Error in server handshake" CR_SERVER_LOST = u"Lost connection to MySQL server during query" CR_COMMANDS_OUT_OF_SYNC = u"Commands out of sync; you can't run this command now" CR_NAMEDPIPE_CONNECTION = u"Named pipe: %-.32s" CR_NAMEDPIPEWAIT_ERROR = u"Can't wait for named pipe to host: %-.64s pipe: %-.32s (%s)" CR_NAMEDPIPEOPEN_ERROR = u"Can't open named pipe to host: %-.64s pipe: %-.32s (%s)" CR_NAMEDPIPESETSTATE_ERROR = u"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%s)" CR_CANT_READ_CHARSET = u"Can't initialize character set %-.32s (path: %-.100s)" CR_NET_PACKET_TOO_LARGE = u"Got packet bigger than 'max_allowed_packet' bytes" CR_EMBEDDED_CONNECTION = u"Embedded server" CR_PROBE_SLAVE_STATUS = u"Error on SHOW SLAVE STATUS:" CR_PROBE_SLAVE_HOSTS = u"Error on SHOW SLAVE HOSTS:" CR_PROBE_SLAVE_CONNECT = u"Error connecting to slave:" CR_PROBE_MASTER_CONNECT = u"Error connecting to master:" CR_SSL_CONNECTION_ERROR = u"SSL connection error: %-.100s" CR_MALFORMED_PACKET = u"Malformed packet" CR_WRONG_LICENSE = u"This client library is licensed only for use with MySQL servers having '%s' license" CR_NULL_POINTER = u"Invalid use of null pointer" CR_NO_PREPARE_STMT = u"Statement not prepared" CR_PARAMS_NOT_BOUND = u"No data supplied for parameters in prepared statement" CR_DATA_TRUNCATED = u"Data truncated" CR_NO_PARAMETERS_EXISTS = u"No parameters exist in the statement" CR_INVALID_PARAMETER_NO = u"Invalid parameter number" CR_INVALID_BUFFER_USE = u"Can't send long data for non-string/non-binary data types (parameter: %s)" CR_UNSUPPORTED_PARAM_TYPE = u"Using unsupported buffer type: %s (parameter: %s)" CR_SHARED_MEMORY_CONNECTION = u"Shared memory: %-.100s" CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR = u"Can't open shared memory; client could not create request event (%s)" CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR = u"Can't open shared memory; no answer event received from server (%s)" CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR = u"Can't open shared memory; server could not allocate file mapping (%s)" CR_SHARED_MEMORY_CONNECT_MAP_ERROR = u"Can't open shared memory; server could not get pointer to file mapping (%s)" CR_SHARED_MEMORY_FILE_MAP_ERROR = u"Can't open shared memory; client could not allocate file mapping (%s)" CR_SHARED_MEMORY_MAP_ERROR = u"Can't open shared memory; client could not get pointer to file mapping (%s)" CR_SHARED_MEMORY_EVENT_ERROR = u"Can't open shared memory; client could not create %s event (%s)" CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR = u"Can't open shared memory; no answer from server (%s)" CR_SHARED_MEMORY_CONNECT_SET_ERROR = u"Can't open shared memory; cannot send request event to server (%s)" CR_CONN_UNKNOW_PROTOCOL = u"Wrong or unknown protocol" CR_INVALID_CONN_HANDLE = u"Invalid connection handle" CR_SECURE_AUTH = u"Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)" CR_FETCH_CANCELED = u"Row retrieval was canceled by mysql_stmt_close() call" CR_NO_DATA = u"Attempt to read column without prior row fetch" CR_NO_STMT_METADATA = u"Prepared statement contains no metadata" CR_NO_RESULT_SET = u"Attempt to read a row while there is no result set associated with the statement" CR_NOT_IMPLEMENTED = u"This feature is not implemented yet" CR_SERVER_LOST_EXTENDED = u"Lost connection to MySQL server at '%s', system error: %s" CR_STMT_CLOSED = u"Statement closed indirectly because of a preceeding %s() call" CR_NEW_STMT_METADATA = u"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again" CR_ALREADY_CONNECTED = u"This handle is already connected. Use a separate handle for each connection." CR_AUTH_PLUGIN_CANNOT_LOAD = u"Authentication plugin '%s' cannot be loaded: %s" CR_DUPLICATE_CONNECTION_ATTR = u"There is an attribute with the same name already" CR_AUTH_PLUGIN_ERR = u"Authentication plugin '%s' reported error: %s" # End MySQL Error messages mysql-connector-python-1.1.6/python2/mysql/connector/locales/eng/__init__.py0000644001577100000120000000220112276514013026503 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """English Content """ mysql-connector-python-1.1.6/python2/mysql/connector/locales/__init__.py0000644001577100000120000000461612276514013025746 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Translations """ __all__ = [ 'get_client_error' ] from mysql.connector import errorcode def get_client_error(error, language='eng'): """Lookup client error This function will lookup the client error message based on the given error and return the error message. If the error was not found, None will be returned. Error can be either an integer or a string. For example: error: 2000 error: CR_UNKNOWN_ERROR The language attribute can be used to retrieve a localized message, when available. Returns a string or None. """ try: tmp = __import__('mysql.connector.locales.%s' % language, globals(), locals(), ['client_error']) except ImportError: raise ImportError("No localization support for language '%s'" % ( language)) client_error = tmp.client_error if isinstance(error, int): errno = error for key, value in errorcode.__dict__.items(): if value == errno: error = key break if isinstance(error, (str)): try: return getattr(client_error, error) except AttributeError: return None raise ValueError("error argument needs to be either an integer or string") mysql-connector-python-1.1.6/setup.cfg0000644001577100000120000000007412276514013017264 0ustar pb2userwheel[sdist] formats = gztar zip [sdist_com] formats = gztar zipmysql-connector-python-1.1.6/metasetupinfo.py0000644001577100000120000001270012276514013020677 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys import os from distutils.sysconfig import get_python_lib from distutils.file_util import copy_file from distutils.dir_util import mkpath, copy_tree from distutils.errors import DistutilsError from distutils import util from version import VERSION, LICENSE if LICENSE == 'Commercial': util.orig_byte_compile = util.byte_compile def _byte_compile(py_files, optimize=0, force=0, prefix=None, base_dir=None, verbose=1, dry_run=0, direct=None): """Byte-compile Python source files This function calls the original distutils.util.byte_compile function and it removes the original Python source files. This function is only to be used for non GPLv2 sources. """ util.orig_byte_compile(py_files, optimize, force, prefix, base_dir, verbose, dry_run, direct) for pyfile in py_files: if 'mysql/__init__.py' in pyfile: continue os.unlink(pyfile) if LICENSE == 'Commercial': util.byte_compile = _byte_compile # Development Status Trove Classifiers significant for Connector/Python DEVELOPMENT_STATUSES = { 'a': '3 - Alpha', 'b': '4 - Beta', '': '5 - Production/Stable' } if sys.version_info >= (3, 1): sys.path = ['python3/'] + sys.path package_dir = { '': 'python3' } elif sys.version_info >= (2, 6) and sys.version_info < (3, 0): sys.path = ['python2/'] + sys.path package_dir = { '': 'python2' } else: raise RuntimeError( "Python v%d.%d is not supported" % sys.version_info[0:2]) package_dir['mysql.connector.django'] = os.path.join('python23', 'django') name = 'mysql-connector-python' version = '{0}.{1}.{2}'.format(*VERSION[0:3]) try: from support.distribution.commands import ( sdist, bdist, dist_rpm, build, dist_deb, dist_osx ) from distutils import dir_util dir_util.copy_tree = copy_tree cmdclasses = { 'build': build.Build, 'sdist': sdist.GenericSourceGPL, 'sdist_gpl': sdist.SourceGPL, 'bdist_com': bdist.BuiltCommercial, 'bdist_com_rpm': dist_rpm.BuiltCommercialRPM, 'sdist_gpl_rpm': dist_rpm.SDistGPLRPM, 'sdist_com': sdist.SourceCommercial, 'sdist_gpl_deb': dist_deb.DebianBuiltDist, 'bdist_com_deb': dist_deb.DebianCommercialBuilt, 'sdist_gpl_osx': dist_osx.BuildDistOSX, 'bdist_com_osx': dist_osx.BuildDistOSXcom, } if sys.version_info >= (2, 7): # MSI only supported for Python 2.7 and greater from support.distribution.commands import (dist_msi) cmdclasses.update({ 'bdist_com': bdist.BuiltCommercial, 'bdist_com_msi': dist_msi.BuiltCommercialMSI, 'sdist_gpl_msi': dist_msi.SourceMSI, }) except ImportError: # Part of Source Distribution cmdclasses = {} packages = [ 'mysql', 'mysql.connector', 'mysql.connector.locales', 'mysql.connector.locales.eng', 'mysql.connector.django', ] description = "MySQL driver written in Python" long_description = """\ MySQL driver written in Python which does not depend on MySQL C client libraries and implements the DB API v2.0 specification (PEP-249). """ author = 'Oracle and/or its affiliates' author_email = '' maintainer = 'Geert Vanderkelen' maintainer_email = 'geert.vanderkelen@oracle.com' license = "GNU GPLv2 (with FOSS License Exception)" keywords = "mysql db", url = 'http://dev.mysql.com/doc/connector-python/en/index.html' download_url = 'http://dev.mysql.com/downloads/connector/python/' classifiers = [ 'Development Status :: %s' % (DEVELOPMENT_STATUSES[VERSION[3]]), 'Environment :: Other Environment', 'Intended Audience :: Developers', 'Intended Audience :: Education', 'Intended Audience :: Information Technology', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.1', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Topic :: Database', 'Topic :: Software Development', 'Topic :: Software Development :: Libraries :: Application Frameworks', 'Topic :: Software Development :: Libraries :: Python Modules' ] mysql-connector-python-1.1.6/python23/0000755001577100000120000000000012276514327017140 5ustar pb2userwheelmysql-connector-python-1.1.6/python23/django/0000755001577100000120000000000012276514327020402 5ustar pb2userwheelmysql-connector-python-1.1.6/python23/django/base.py0000644001577100000120000005703212276514013021665 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. """Django database Backend using MySQL Connector/Python This Django database backend is heavily based on the MySQL backend coming with Django. Changes include: * Support for microseconds (MySQL 5.6.3 and later) * Using INFORMATION_SCHEMA where possible * Using new defaults for, for example SQL_AUTO_IS_NULL Requires and comes with MySQL Connector/Python v1.1 and later: http://dev.mysql.com/downloads/connector/python/ """ from __future__ import unicode_literals import sys import warnings import django try: import mysql.connector from mysql.connector.conversion import MySQLConverter except ImportError as err: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "Error loading mysql.connector module: {0}".format(err)) try: version = mysql.connector.__version_info__[0:3] except AttributeError: from mysql.connector.version import VERSION version = VERSION[0:3] if version < (1, 1): from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured( "MySQL Connector/Python v1.1.0 or newer " "is required; you have %s" % mysql.connector.__version__) from django.db import utils from django.db.backends import * from django.db.backends.signals import connection_created from django.utils import (six, timezone, dateparse) from django.conf import settings from mysql.connector.django.client import DatabaseClient from mysql.connector.django.creation import DatabaseCreation from mysql.connector.django.introspection import DatabaseIntrospection from mysql.connector.django.validation import DatabaseValidation # Raise exceptions for database warnings if DEBUG is on # Note: PEP-249 says Warning must be subclass of StandardError mysql.connector.Warning = Warning if settings.DEBUG: warnings.filterwarnings("error", category=mysql.connector.Warning) DatabaseError = mysql.connector.DatabaseError IntegrityError = mysql.connector.IntegrityError NotSupportedError = mysql.connector.NotSupportedError class DjangoMySQLConverter(MySQLConverter): """Custom converter for Django""" def _TIME_to_python(self, value, dsc=None): """Return MySQL TIME data type as datetime.time() Returns datetime.time() """ return dateparse.parse_time(value) def _DATETIME_to_python(self, value, dsc=None): """Connector/Python always returns naive datetime.datetime Connector/Python always returns naive timestamps since MySQL has no time zone support. Since Django needs non-naive, we need to add the UTC time zone. Returns datetime.datetime() """ if not value: return None dt = MySQLConverter._DATETIME_to_python(self, value) if settings.USE_TZ and timezone.is_naive(dt): dt = dt.replace(tzinfo=timezone.utc) return dt class CursorWrapper(object): """Wrapper around MySQL Connector/Python's cursor class. The cursor class is defined by the options passed to MySQL Connector/Python. If buffered option is True in those options, MySQLCursorBuffered will be used. """ def __init__(self, cursor): self.cursor = cursor def _execute_wrapper(self, method, query, args): """Wrapper around execute() and executemany()""" try: return method(query, args) except (mysql.connector.ProgrammingError, mysql.connector.IntegrityError) as err: six.reraise(utils.IntegrityError, utils.IntegrityError(err.msg), sys.exc_info()[2]) except mysql.connector.OperationalError as err: six.reraise(utils.DatabaseError, utils.DatabaseError(err.msg), sys.exc_info()[2]) except mysql.connector.DatabaseError as err: six.reraise(utils.DatabaseError, utils.DatabaseError(err.msg), sys.exc_info()[2]) def execute(self, query, args=None): """Executes the given operation This wrapper method around the execute()-method of the cursor is mainly needed to re-raise using different exceptions. """ return self._execute_wrapper(self.cursor.execute, query, args) def executemany(self, query, args): """Executes the given operation This wrapper method around the executemany()-method of the cursor is mainly needed to re-raise using different exceptions. """ return self._execute_wrapper(self.cursor.execute, query, args) def __getattr__(self, attr): """Return attribute of wrapped cursor""" return getattr(self.cursor, attr) def __iter__(self): """Returns iterator over wrapped cursor""" return iter(self.cursor) class DatabaseFeatures(BaseDatabaseFeatures): """Features specific to MySQL Microsecond precision is supported since MySQL 5.6.3 and turned on by default. """ empty_fetchmany_value = [] update_can_self_select = False allows_group_by_pk = True related_fields_match_type = True allow_sliced_subqueries = False has_bulk_insert = True has_select_for_update = True has_select_for_update_nowait = False supports_forward_references = False supports_long_model_names = False supports_microsecond_precision = False # toggled in __init__() supports_regex_backreferencing = False supports_date_lookup_using_string = False supports_timezones = False requires_explicit_null_ordering_when_grouping = True allows_primary_key_0 = False uses_savepoints = True atomic_transactions = False def __init__(self, connection): super(DatabaseFeatures, self).__init__(connection) self.supports_microsecond_precision = self._microseconds_precision() def _microseconds_precision(self): if self.connection.get_server_version() >= (5, 6, 3): return True return False def _mysql_storage_engine(self): """Get default storage engine of MySQL This method creates a table without ENGINE table option and inspects which engine was used. Used by Django tests. """ cursor = self.connection.cursor() tblname = 'INTROSPECT_TEST' droptable = 'DROP TABLE IF EXISTS {table}'.format(table=tblname) cursor.execute(droptable) cursor.execute('CREATE TABLE {table} (X INT)'.format(table=tblname)) if self.connection.get_server_version() >= (5, 0, 0): cursor.execute( "SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES " "WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s", (self.connection.settings_dict['NAME'], tblname)) engine = cursor.fetchone()[0] else: # Very old MySQL servers.. cursor.execute("SHOW TABLE STATUS WHERE Name='{table}'".format( table=tblname)) engine = cursor.fetchone()[1] cursor.execute(droptable) return engine def can_introspect_foreign_keys(self): """Confirm support for introspected foreign keys Only the InnoDB storage engine supports Foreigen Key (not taking into account MySQL Cluster here). """ return self._mysql_storage_engine == 'InnoDB' def has_zoneinfo_database(self): """Tests if the time zone definitions are installed MySQL accepts full time zones names (eg. Africa/Nairobi) but rejects abbreviations (eg. EAT). When pytz isn't installed and the current time zone is LocalTimezone (the only sensible value in this context), the current time zone name will be an abbreviation. As a consequence, MySQL cannot perform time zone conversions reliably. """ # Django 1.6 if pytz is None: return False self.connection.cmd_query("SELECT 1 FROM mysql.time_zone LIMIT 1") return self.connection.get_rows()[0] is not [] class DatabaseOperations(BaseDatabaseOperations): compiler_module = "mysql.connector.django.compiler" def date_extract_sql(self, lookup_type, field_name): # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html if lookup_type == 'week_day': # DAYOFWEEK() returns an integer, 1-7, Sunday=1. # Note: WEEKDAY() returns 0-6, Monday=0. return "DAYOFWEEK({0})".format(field_name) else: return "EXTRACT({0} FROM {1})".format( lookup_type.upper(), field_name) def date_trunc_sql(self, lookup_type, field_name): """Returns SQL simulating DATE_TRUNC This function uses MySQL functions DATE_FORMAT and CAST to simulate DATE_TRUNC. The field_name is returned when lookup_type is not supported. """ fields = ['year', 'month', 'day', 'hour', 'minute', 'second'] format = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s') format_def = ('0000-', '01', '-01', ' 00:', '00', ':00') try: i = fields.index(lookup_type) + 1 except ValueError: # Wrong lookup type, just return the value from MySQL as-is sql = field_name else: format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]]) sql = "CAST(DATE_FORMAT({0}, '{1}') AS DATETIME)".format( field_name, format_str) return sql def datetime_extract_sql(self, lookup_type, field_name, tzname): # Django 1.6 if settings.USE_TZ: field_name = "CONVERT_TZ({0}, 'UTC', %s)".format(field_name) params = [tzname] else: params = [] # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html if lookup_type == 'week_day': # DAYOFWEEK() returns an integer, 1-7, Sunday=1. # Note: WEEKDAY() returns 0-6, Monday=0. sql = "DAYOFWEEK({0})".format(field_name) else: sql = "EXTRACT({0} FROM {1})".format(lookup_type.upper(), field_name) return sql, params def datetime_trunc_sql(self, lookup_type, field_name, tzname): # Django 1.6 if settings.USE_TZ: field_name = "CONVERT_TZ({0}, 'UTC', %s)".format(field_name) params = [tzname] else: params = [] fields = ['year', 'month', 'day', 'hour', 'minute', 'second'] format_ = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s') format_def = ('0000-', '01', '-01', ' 00:', '00', ':00') try: i = fields.index(lookup_type) + 1 except ValueError: sql = field_name else: format_str = ''.join([f for f in format_[:i]] + [f for f in format_def[i:]]) sql = "CAST(DATE_FORMAT({0}, '{1}') AS DATETIME)".format( field_name, format_str) return sql, params def date_interval_sql(self, sql, connector, timedelta): """Returns SQL for calculating date/time intervals """ fmt = ( "({sql} {connector} INTERVAL '{days} " "0:0:{secs}:{msecs}' DAY_MICROSECOND)" ) return fmt.format( sql=sql, connector=connector, days=timedelta.days, secs=timedelta.seconds, msecs=timedelta.microseconds ) def drop_foreignkey_sql(self): return "DROP FOREIGN KEY" def force_no_ordering(self): """ "ORDER BY NULL" prevents MySQL from implicitly ordering by grouped columns. If no ordering would otherwise be applied, we don't want any implicit sorting going on. """ return ["NULL"] def fulltext_search_sql(self, field_name): return 'MATCH ({0}) AGAINST (%s IN BOOLEAN MODE)'.format(field_name) def last_executed_query(self, cursor, sql, params): return cursor.statement def no_limit_value(self): # 2**64 - 1, as recommended by the MySQL documentation return 18446744073709551615 def quote_name(self, name): if name.startswith("`") and name.endswith("`"): return name # Quoting once is enough. return "`{0}`".format(name) def random_function_sql(self): return 'RAND()' def sql_flush(self, style, tables, sequences, allow_cascade=False): if tables: sql = ['SET FOREIGN_KEY_CHECKS = 0;'] for table in tables: sql.append('{keyword} {table};'.format( keyword=style.SQL_KEYWORD('TRUNCATE'), table=style.SQL_FIELD(self.quote_name(table)))) sql.append('SET FOREIGN_KEY_CHECKS = 1;') sql.extend(self.sequence_reset_by_name_sql(style, sequences)) return sql else: return [] def sequence_reset_by_name_sql(self, style, sequences): # Truncate already resets the AUTO_INCREMENT field from # MySQL version 5.0.13 onwards. Refs #16961. res = [] if self.connection.get_server_version() < (5, 0, 13): fmt = "{alter} {table} {{tablename}} {auto_inc} {field};".format( alter=style.SQL_KEYWORD('ALTER'), table=style.SQL_KEYWORD('TABLE'), auto_inc=style.SQL_KEYWORD('AUTO_INCREMENT'), field=style.SQL_FIELD('= 1') ) for sequence in sequences: tablename = style.SQL_TABLE(self.quote_name(sequence['table'])) res.append(fmt.format(tablename=tablename)) return res return res def validate_autopk_value(self, value): # MySQLism: zero in AUTO_INCREMENT field does not work. Refs #17653. if not value: raise ValueError('The database backend does not accept 0 as a ' 'value for AutoField.') return value def value_to_db_datetime(self, value): if not value: return None # MySQL doesn't support tz-aware times if timezone.is_aware(value): if settings.USE_TZ: value = value.astimezone(timezone.utc).replace(tzinfo=None) else: raise ValueError( "MySQL backend does not support timezone-aware times." ) return self.connection.connection.converter._datetime_to_mysql(value) def value_to_db_time(self, value): if not value: return None # MySQL doesn't support tz-aware times if timezone.is_aware(value): raise ValueError("MySQL backend does not support timezone-aware " "times.") return self.connection.connection.converter._time_to_mysql(value) def year_lookup_bounds(self, value): # Again, no microseconds first = '{0}-01-01 00:00:00' second = '{0}-12-31 23:59:59.999999' return [first.format(value), second.format(value)] def year_lookup_bounds_for_datetime_field(self, value): # Django 1.6 # Again, no microseconds first, second = super(DatabaseOperations, self).year_lookup_bounds_for_datetime_field(value) if self.connection.get_server_version() >= (5, 6, 4): return [first.replace(microsecond=0), second] else: return [first.replace(microsecond=0), second.replace(microsecond=0)] def max_name_length(self): return 64 def bulk_insert_sql(self, fields, num_values): items_sql = "({0})".format(", ".join(["%s"] * len(fields))) return "VALUES " + ", ".join([items_sql] * num_values) def savepoint_create_sql(self, sid): return "SAVEPOINT {0}".format(sid) def savepoint_commit_sql(self, sid): return "RELEASE SAVEPOINT {0}".format(sid) def savepoint_rollback_sql(self, sid): return "ROLLBACK TO SAVEPOINT {0}".format(sid) class DatabaseWrapper(BaseDatabaseWrapper): vendor = 'mysql' operators = { 'exact': '= %s', 'iexact': 'LIKE %s', 'contains': 'LIKE BINARY %s', 'icontains': 'LIKE %s', 'regex': 'REGEXP BINARY %s', 'iregex': 'REGEXP %s', 'gt': '> %s', 'gte': '>= %s', 'lt': '< %s', 'lte': '<= %s', 'startswith': 'LIKE BINARY %s', 'endswith': 'LIKE BINARY %s', 'istartswith': 'LIKE %s', 'iendswith': 'LIKE %s', } Database = mysql.connector def __init__(self, *args, **kwargs): super(DatabaseWrapper, self).__init__(*args, **kwargs) self.server_version = None # Since some features depend on the MySQL version, we need to connect self._connect() self.features = DatabaseFeatures(self) self.ops = DatabaseOperations(self) self.client = DatabaseClient(self) self.creation = DatabaseCreation(self) self.introspection = DatabaseIntrospection(self) self.validation = DatabaseValidation(self) def _valid_connection(self): if self.connection: return self.connection.is_connected() return False def get_connection_params(self): # Django 1.6 kwargs = { 'charset': 'utf8', 'use_unicode': True, 'sql_mode': 'TRADITIONAL', 'buffered': True, } settings_dict = self.settings_dict if settings_dict['USER']: kwargs['user'] = settings_dict['USER'] if settings_dict['NAME']: kwargs['database'] = settings_dict['NAME'] if settings_dict['PASSWORD']: kwargs['passwd'] = settings_dict['PASSWORD'] if settings_dict['HOST'].startswith('/'): kwargs['unix_socket'] = settings_dict['HOST'] elif settings_dict['HOST']: kwargs['host'] = settings_dict['HOST'] if settings_dict['PORT']: kwargs['port'] = int(settings_dict['PORT']) kwargs['client_flags'] = [ # Need potentially affected rows on UPDATE mysql.connector.constants.ClientFlag.FOUND_ROWS, ] kwargs.update(settings_dict['OPTIONS']) return kwargs def get_new_connection(self, conn_params): # Django 1.6 cnx = mysql.connector.connect(**conn_params) self.server_version = cnx.get_server_version() cnx.set_converter_class(DjangoMySQLConverter) connection_created.send(sender=self.__class__, connection=self) return cnx def init_connection_state(self): # Django 1.6 if self.server_version < (5, 5, 3): # See sysvar_sql_auto_is_null in MySQL Reference manual self.connection.cmd_query("SET SQL_AUTO_IS_NULL = 0") if self.settings_dict['AUTOCOMMIT']: self.set_autocommit(self.settings_dict['AUTOCOMMIT']) def create_cursor(self): # Django 1.6 cursor = self.connection.cursor() return CursorWrapper(cursor) def _connect(self): """Setup the connection with MySQL""" self.connection = self.get_new_connection(self.get_connection_params()) self.init_connection_state() def _cursor(self): """Return a CursorWrapper object Returns a CursorWrapper """ try: # Django 1.6 return super(DatabaseWrapper, self)._cursor() except AttributeError: if not self.connection: self._connect() return self.create_cursor() def get_server_version(self): """Returns the MySQL server version of current connection Returns a tuple """ return self.server_version def disable_constraint_checking(self): """Disables foreign key checks Disables foreign key checks, primarily for use in adding rows with forward references. Always returns True, to indicate constraint checks need to be re-enabled. Returns True """ self.cursor().execute('SET @@session.foreign_key_checks = 0') return True def enable_constraint_checking(self): """Re-enable foreign key checks Re-enable foreign key checks after they have been disabled. """ # Override needs_rollback in case constraint_checks_disabled is # nested inside transaction.atomic. if django.VERSION >= (1, 6): self.needs_rollback, needs_rollback = False, self.needs_rollback try: self.cursor().execute('SET @@session.foreign_key_checks = 1') finally: if django.VERSION >= (1, 6): self.needs_rollback = needs_rollback def check_constraints(self, table_names=None): """Check rows in tables for invalid foreign key references Checks each table name in `table_names` for rows with invalid foreign key references. This method is intended to be used in conjunction with `disable_constraint_checking()` and `enable_constraint_checking()`, to determine if rows with invalid references were entered while constraint checks were off. Raises an IntegrityError on the first invalid foreign key reference encountered (if any) and provides detailed information about the invalid reference in the error message. Backends can override this method if they can more directly apply constraint checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE") """ ref_query = """ SELECT REFERRING.`{0}`, REFERRING.`{1}` FROM `{2}` as REFERRING LEFT JOIN `{3}` as REFERRED ON (REFERRING.`{4}` = REFERRED.`{5}`) WHERE REFERRING.`{6}` IS NOT NULL AND REFERRED.`{7}` IS NULL""" cursor = self.cursor() if table_names is None: table_names = self.introspection.table_names(cursor) for table_name in table_names: primary_key_column_name = \ self.introspection.get_primary_key_column(cursor, table_name) if not primary_key_column_name: continue key_columns = self.introspection.get_key_columns(cursor, table_name) for column_name, referenced_table_name, referenced_column_name \ in key_columns: cursor.execute(ref_query.format(primary_key_column_name, column_name, table_name, referenced_table_name, column_name, referenced_column_name, column_name, referenced_column_name)) for bad_row in cursor.fetchall(): msg = ("The row in table '{0}' with primary key '{1}' has " "an invalid foreign key: {2}.{3} contains a value " "'{4}' that does not have a corresponding value in " "{5}.{6}.".format(table_name, bad_row[0], table_name, column_name, bad_row[1], referenced_table_name, referenced_column_name)) raise utils.IntegrityError(msg) def _rollback(self): try: BaseDatabaseWrapper._rollback(self) except NotSupportedError: pass def _set_autocommit(self, autocommit): # Django 1.6 self.connection.autocommit = autocommit def is_usable(self): # Django 1.6 return self.connection.is_connected() mysql-connector-python-1.1.6/python23/django/client.py0000644001577100000120000000332512276514013022225 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. import os import sys from django.db.backends import BaseDatabaseClient class DatabaseClient(BaseDatabaseClient): executable_name = 'mysql' def runshell(self): settings_dict = self.connection.settings_dict args = [self.executable_name] db = settings_dict['OPTIONS'].get('database', settings_dict['NAME']) user = settings_dict['OPTIONS'].get('user', settings_dict['USER']) passwd = settings_dict['OPTIONS'].get('password', settings_dict['PASSWORD']) host = settings_dict['OPTIONS'].get('host', settings_dict['HOST']) port = settings_dict['OPTIONS'].get('port', settings_dict['PORT']) defaults_file = settings_dict['OPTIONS'].get('read_default_file') # --defaults-file should always be the first option if defaults_file: args.append("--defaults-file={0}".format(defaults_file)) # We force SQL_MODE to TRADITIONAL args.append("--init-command=SET @@session.SQL_MODE=TRADITIONAL") if user: args.append("--user={0}".format(user)) if passwd: args.append("--password={0}".format(passwd)) if host: if '/' in host: args.append("--socket={0}".format(host)) else: args.append("--host={0}".format(host)) if port: args.append("--port={0}".format(port)) if db: args.append("--database={0}".format(db)) if os.name == 'nt': sys.exit(os.system(' '.join(args))) else: os.execvp(self.executable_name, args) mysql-connector-python-1.1.6/python23/django/validation.py0000644001577100000120000000161012276514013023074 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. from django.db import models from django.db.backends import BaseDatabaseValidation class DatabaseValidation(BaseDatabaseValidation): def validate_field(self, errors, opts, f): """ MySQL has the following field length restriction: No character (varchar) fields can have a length exceeding 255 characters if they have a unique index on them. """ varchar_fields = (models.CharField, models.CommaSeparatedIntegerField, models.SlugField) if isinstance(f, varchar_fields) and f.max_length > 255 and f.unique: msg = ('"%(name)s": %(cls)s cannot have a "max_length" greater ' 'than 255 when using "unique=True".') errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__}) mysql-connector-python-1.1.6/python23/django/compiler.py0000644001577100000120000000301712276514013022557 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. import django from django.db.models.sql import compiler from django.utils.six.moves import zip_longest class SQLCompiler(compiler.SQLCompiler): def resolve_columns(self, row, fields=()): values = [] index_extra_select = len(self.query.extra_select) bool_fields = ("BooleanField", "NullBooleanField") for value, field in zip_longest(row[index_extra_select:], fields): if (field and field.get_internal_type() in bool_fields and value in (0, 1)): value = bool(value) values.append(value) return row[:index_extra_select] + tuple(values) def as_subquery_condition(self, alias, columns, qn): # Django 1.6 qn2 = self.connection.ops.quote_name sql, params = self.as_sql() column_list = ', '.join( ['%s.%s' % (qn(alias), qn2(column)) for column in columns]) return '({0}) IN ({1})'.format(column_list, sql), params class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler): pass class SQLDeleteCompiler(compiler.SQLDeleteCompiler, SQLCompiler): pass class SQLUpdateCompiler(compiler.SQLUpdateCompiler, SQLCompiler): pass class SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler): pass class SQLDateCompiler(compiler.SQLDateCompiler, SQLCompiler): pass if django.VERSION >= (1, 6): class SQLDateTimeCompiler(compiler.SQLDateTimeCompiler, SQLCompiler): # Django 1.6 pass mysql-connector-python-1.1.6/python23/django/creation.py0000644001577100000120000001165512276514013022560 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. import django from django.db import models from django.db.backends.creation import BaseDatabaseCreation from django.db.backends.util import truncate_name class DatabaseCreation(BaseDatabaseCreation): """Maps Django Field object with MySQL data types """ def __init__(self, connection): super(DatabaseCreation, self).__init__(connection) self.data_types = { 'AutoField': 'integer AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', # ms support set later 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', # ms support set later } # Support for microseconds if self.connection.get_server_version() >= (5, 6, 4): self.data_types.update({ 'DateTimeField': 'datetime(6)', 'TimeField': 'time(6)', }) def sql_table_creation_suffix(self): suffix = [] if self.connection.settings_dict['TEST_CHARSET']: suffix.append('CHARACTER SET {0}'.format( self.connection.settings_dict['TEST_CHARSET'])) if self.connection.settings_dict['TEST_COLLATION']: suffix.append('COLLATE {0}'.format( self.connection.settings_dict['TEST_COLLATION'])) return ' '.join(suffix) if django.VERSION < (1, 6): def sql_for_inline_foreign_key_references(self, field, known_models, style): "All inline references are pending under MySQL" return [], True else: def sql_for_inline_foreign_key_references(self, model, field, known_models, style): "All inline references are pending under MySQL" return [], True def sql_for_inline_many_to_many_references(self, model, field, style): opts = model._meta qn = self.connection.ops.quote_name columndef = ' {column} {type} {options},' table_output = [ columndef.format( column=style.SQL_FIELD(qn(field.m2m_column_name())), type=style.SQL_COLTYPE(models.ForeignKey(model).db_type( connection=self.connection)), options=style.SQL_KEYWORD('NOT NULL') ), columndef.format( column=style.SQL_FIELD(qn(field.m2m_reverse_name())), type=style.SQL_COLTYPE(models.ForeignKey(field.rel.to).db_type( connection=self.connection)), options=style.SQL_KEYWORD('NOT NULL') ), ] deferred = [ (field.m2m_db_table(), field.m2m_column_name(), opts.db_table, opts.pk.column), (field.m2m_db_table(), field.m2m_reverse_name(), field.rel.to._meta.db_table, field.rel.to._meta.pk.column) ] return table_output, deferred def sql_destroy_indexes_for_fields(self, model, fields, style): # Django 1.6 if len(fields) == 1 and fields[0].db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( fields[0].db_tablespace) elif model._meta.db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( model._meta.db_tablespace) else: tablespace_sql = "" if tablespace_sql: tablespace_sql = " " + tablespace_sql field_names = [] qn = self.connection.ops.quote_name for f in fields: field_names.append(style.SQL_FIELD(qn(f.column))) index_name = "{0}_{1}".format(model._meta.db_table, self._digest([f.name for f in fields])) return [ style.SQL_KEYWORD("DROP INDEX") + " " + style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + " " + style.SQL_KEYWORD("ON") + " " + style.SQL_TABLE(qn(model._meta.db_table)) + ";", ] mysql-connector-python-1.1.6/python23/django/__init__.py0000644001577100000120000000000012276514013022471 0ustar pb2userwheelmysql-connector-python-1.1.6/python23/django/introspection.py0000644001577100000120000001377412276514013023660 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. import re import django from django.db.backends import BaseDatabaseIntrospection if django.VERSION >= (1, 6): from django.db.backends import FieldInfo from django.utils.encoding import force_text from mysql.connector.constants import FieldType foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) " r"REFERENCES `([^`]*)` \(`([^`]*)`\)") class DatabaseIntrospection(BaseDatabaseIntrospection): data_types_reverse = { FieldType.BLOB: 'TextField', FieldType.DECIMAL: 'DecimalField', FieldType.NEWDECIMAL: 'DecimalField', FieldType.DATE: 'DateField', FieldType.DATETIME: 'DateTimeField', FieldType.DOUBLE: 'FloatField', FieldType.FLOAT: 'FloatField', FieldType.INT24: 'IntegerField', FieldType.LONG: 'IntegerField', FieldType.LONGLONG: 'BigIntegerField', FieldType.SHORT: 'IntegerField', FieldType.STRING: 'CharField', FieldType.TIME: 'TimeField', FieldType.TIMESTAMP: 'DateTimeField', FieldType.TINY: 'IntegerField', FieldType.TINY_BLOB: 'TextField', FieldType.MEDIUM_BLOB: 'TextField', FieldType.LONG_BLOB: 'TextField', FieldType.VAR_STRING: 'CharField', } def get_table_list(self, cursor): "Returns a list of table names in the current database." cursor.execute("SHOW TABLES") return [row[0] for row in cursor.fetchall()] def get_table_description(self, cursor, table_name): """ Returns a description of the table, with the DB-API cursor.description interface." """ # varchar length returned by cursor.description is an internal length, # not visible length (#5725), use information_schema database to fix # this cursor.execute( "SELECT column_name, character_maximum_length " "FROM INFORMATION_SCHEMA.COLUMNS " "WHERE table_name = %s AND table_schema = DATABASE() " "AND character_maximum_length IS NOT NULL", [table_name]) length_map = dict(cursor.fetchall()) # Also getting precision and scale from information_schema (see #5014) cursor.execute( "SELECT column_name, numeric_precision, numeric_scale FROM " "INFORMATION_SCHEMA.COLUMNS WHERE table_name = %s AND " "table_schema = DATABASE() AND data_type='decimal", [table_name]) numeric_map = dict([(line[0], tuple([int(n) for n in line[1:]])) for line in cursor.fetchall()]) cursor.execute("SELECT * FROM {0} LIMIT 1".format( self.connection.ops.quote_name(table_name))) if django.VERSION >= (1, 6): return [FieldInfo(*((force_text(line[0]),) + line[1:3] + (length_map.get(line[0], line[3]),) + numeric_map.get(line[0], line[4:6]) + (line[6],))) for line in cursor.description] else: return [line[:3] + (length_map.get(line[0], line[3]),) + line[4:] for line in cursor.description] def _name_to_index(self, cursor, table_name): """ Returns a dictionary of {field_name: field_index} for the given table. Indexes are 0-based. """ return dict([(d[0], i) for i, d in enumerate( self.get_table_description(cursor, table_name))]) def get_relations(self, cursor, table_name): """ Returns a dictionary of {field_index: (field_index_other_table, other_table)} representing all relationships to the given table. Indexes are 0-based. """ my_field_dict = self._name_to_index(cursor, table_name) constraints = self.get_key_columns(cursor, table_name) relations = {} for my_fieldname, other_table, other_field in constraints: other_field_index = self._name_to_index(cursor, other_table)[other_field] my_field_index = my_field_dict[my_fieldname] relations[my_field_index] = (other_field_index, other_table) return relations def get_key_columns(self, cursor, table_name): """ Returns a list of (column_name, referenced_table_name, referenced_column_name) for all key columns in given table. """ key_columns = [] cursor.execute(""" SELECT column_name, referenced_table_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_name = %s AND table_schema = DATABASE() AND referenced_table_name IS NOT NULL AND referenced_column_name IS NOT NULL""", [table_name]) key_columns.extend(cursor.fetchall()) return key_columns def get_indexes(self, cursor, table_name): cursor.execute("SHOW INDEX FROM {0}" "".format(self.connection.ops.quote_name(table_name))) # Do a two-pass search for indexes: on first pass check which indexes # are multicolumn, on second pass check which single-column indexes # are present. rows = list(cursor.fetchall()) multicol_indexes = set() for row in rows: if row[3] > 1: multicol_indexes.add(row[2]) indexes = {} for row in rows: if row[2] in multicol_indexes: continue indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])} return indexes def get_primary_key_column(self, cursor, table_name): """ Returns the name of the primary key column for the given table """ # Django 1.6 for column in self.get_indexes(cursor, table_name).iteritems(): if column[1]['primary_key']: return column[0] return None mysql-connector-python-1.1.6/python23/__init__.py0000644001577100000120000000000012276514013021227 0ustar pb2userwheelmysql-connector-python-1.1.6/python3/0000755001577100000120000000000012276514327017056 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/examples/0000755001577100000120000000000012276514327020674 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/examples/multi_resultsets.py0000644001577100000120000000564612276514013024700 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * sending multiple statements and iterating over the results """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, info TEXT DEFAULT '', age TINYINT UNSIGNED DEFAULT '30', PRIMARY KEY (id) )""" cursor.execute(stmt_create) info = "abc"*10000 stmts = [ "INSERT INTO names (name) VALUES ('Geert')", "SELECT COUNT(*) AS cnt FROM names", "INSERT INTO names (name) VALUES ('Jan'),('Michel')", "SELECT name FROM names", ] # Note 'multi=True' when calling cursor.execute() for result in cursor.execute(' ; '.join(stmts), multi=True): if result.with_rows: if result.statement == stmts[3]: output.append("Names in table: " + ' '.join([ name[0] for name in result])) else: output.append( "Number of rows: {}".format(result.fetchone()[0])) else: output.append("Inserted {} row{}".format(result.rowcount, 's' if result.rowcount > 1 else '')) cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/unicode.py0000755001577100000120000000550612276514013022675 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * the usefulness of unicode, if it works correctly.. * dropping and creating a table * inserting and selecting a row """ info = """ For this to work you need to make sure your terminal can output unicode character correctly. Check if the encoding of your terminal is set to UTF-8. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Show the unicode string we're going to use unistr = "\u00bfHabla espa\u00f1ol?" output.append("Unicode string: %s" % unistr) # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS unicode" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE unicode ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, str VARCHAR(50) DEFAULT '' NOT NULL, PRIMARY KEY (id) ) CHARACTER SET 'utf8'""" cursor.execute(stmt_create) # Insert a row stmt_insert = "INSERT INTO unicode (str) VALUES (%s)" cursor.execute(stmt_insert, (unistr,)) # Select it again and show it stmt_select = "SELECT str FROM unicode WHERE id = %s" cursor.execute(stmt_select, (1,)) row = cursor.fetchone() output.append("Unicode string coming from db: " + row[0]) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() print(info) out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/warnings.py0000755001577100000120000000403412276514013023072 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * using warnings """ STMT = "SELECT 'abc'+1" def main(config): output = [] config['get_warnings'] = True db = mysql.connector.Connect(**config) cursor = db.cursor() db.sql_mode = '' output.append("Executing '%s'" % STMT) cursor.execute(STMT) cursor.fetchall() warnings = cursor.fetchwarnings() if warnings: for w in warnings: output.append("%d: %s" % (w[1],w[2])) else: output.append("We should have got warnings.") raise Exception("Got no warnings") cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/inserts.py0000755001577100000120000000531112276514013022730 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * dropping and creating a table * inserting 3 rows using executemany() * selecting data and showing it """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, info TEXT DEFAULT '', age TINYINT UNSIGNED DEFAULT '30', PRIMARY KEY (id) )""" cursor.execute(stmt_create) info = "abc"*10000 # Insert 3 records names = ( ('Geert',info), ('Jan',info), ('Michel',info) ) stmt_insert = "INSERT INTO names (name,info) VALUES (%s,%s)" cursor.executemany(stmt_insert, names) db.commit() # Read the names again and print them stmt_select = "SELECT id, name, info, age FROM names ORDER BY id" cursor.execute(stmt_select) for row in cursor.fetchall(): output.append("%d | %s | %d\nInfo: %s..\n" % ( row[0], row[1], row[3], row[2][20])) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/microseconds.py0000644001577100000120000000640312276514013023731 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from datetime import time import mysql.connector """ Example using MySQL Connector/Python showing: * How to save timestamps including microseconds * Check the MySQL server version NOTE: This only works with MySQL 5.6.4 or greater. This example will work with earlier versions, but the microseconds information will be lost. Story: We keep track of swimmers in a freestyle 4x 100m relay swimming event with millisecond precision. """ CREATE_TABLE = """ CREATE TABLE relay_laps ( teamid TINYINT UNSIGNED NOT NULL, swimmer TINYINT UNSIGNED NOT NULL, lap TIME(3), PRIMARY KEY (teamid, swimmer) ) ENGINE=InnoDB """ def main(config): output = [] cnx = mysql.connector.Connect(**config) if cnx.get_server_version() < (5,6,4): output.append( "MySQL {} does not support fractional precision"\ " for timestamps.".format(cnx.get_server_info())) return output cursor = cnx.cursor() try: cursor.execute("DROP TABLE IF EXISTS relay_laps") except: # Ignoring the fact that it was not there pass cursor.execute(CREATE_TABLE) teams = {} teams[1] = [ (1, time(second=47, microsecond=510000)), (2, time(second=47, microsecond=20000)), (3, time(second=47, microsecond=650000)), (4, time(second=46, microsecond=60000)), ] insert = "INSERT INTO relay_laps (teamid,swimmer,lap) VALUES (%s,%s,%s)" for team, swimmers in teams.items(): for swimmer in swimmers: cursor.execute(insert, (team, swimmer[0], swimmer[1])) cnx.commit() cursor.execute("SELECT * FROM relay_laps") for row in cursor: output.append("{: 2d} | {: 2d} | {}".format(*row)) try: cursor.execute("DROP TABLE IF EXISTS relay_laps") except: # Ignoring the fact that it was not there pass cursor.close() cnx.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/dates.py0000644001577100000120000000664512276514013022351 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os from datetime import datetime import mysql.connector """ Example using MySQL Connector/Python showing: * How to get datetime, date and time types * Shows also invalid dates returned and handled * Force sql_mode to be not set for the active session """ # Note that by default MySQL takes invalid timestamps. This is for # backward compatibility. As of 5.0, use sql modes NO_ZERO_IN_DATE,NO_ZERO_DATE # to prevent this. _adate = datetime(1977,6,14,21,10,00) DATA = [ (_adate.date(), _adate, _adate.time()), ('0000-00-00','0000-00-00 00:00:00','00:00:00'), ('1000-00-00','9999-00-00 00:00:00','00:00:00'), ] def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() tbl = 'myconnpy_dates' cursor.execute('SET sql_mode = ""') # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS %s" % (tbl) cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE %s ( `id` tinyint(4) NOT NULL AUTO_INCREMENT, `c1` date DEFAULT NULL, `c2` datetime NOT NULL, `c3` time DEFAULT NULL, `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) )""" % (tbl) cursor.execute(stmt_create) # not using executemany to handle errors better stmt_insert = ("INSERT INTO {} (c1,c2,c3) VALUES " "(%s,%s,%s)".format(tbl)) for d in DATA: try: cursor.execute(stmt_insert, d) except (mysql.connector.errors.Error, TypeError) as e: output.append("Failed inserting %s\nError: %s\n" % (d,e)) raise # Read the names again and print them stmt_select = "SELECT * FROM %s ORDER BY id" % (tbl) cursor.execute(stmt_select) for row in cursor.fetchall(): output.append("%3s | %10s | %19s | %8s |" % ( row[0], row[1], row[2], row[3], )) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/prepared_statements.py0000644001577100000120000000550212276514013025311 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Example using MySQL Prepared Statements Example using MySQL Connector/Python showing: * usage of Prepared Statements """ import mysql.connector from mysql.connector.cursor import MySQLCursorPrepared def main(config): output = [] cnx = mysql.connector.Connect(**config) curprep = cnx.cursor(cursor_class=MySQLCursorPrepared) cur = cnx.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cur.execute(stmt_drop) stmt_create = ( "CREATE TABLE names (" "id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, " "name VARCHAR(30) DEFAULT '' NOT NULL, " "cnt TINYINT UNSIGNED DEFAULT 0, " "PRIMARY KEY (id))" ) cur.execute(stmt_create) # Connector/Python also allows ? as placeholders for MySQL Prepared # statements. prepstmt = "INSERT INTO names (name) VALUES (%s)" # Preparing the statement is done only once. It can be done before # without data, or later with data. curprep.execute(prepstmt) # Insert 3 records names = ('Geert', 'Jan', 'Michel') for name in names: curprep.execute(prepstmt, (name,)) cnx.commit() # We use a normal cursor issue a SELECT output.append("Inserted data") cur.execute("SELECT id, name FROM names") for row in cur: output.append("{} | {}".format(*row)) # Cleaning up, dropping the table again cur.execute(stmt_drop) cnx.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # from config import Config config = Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/transaction.py0000755001577100000120000000745512276514013023601 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * dropping and creating a table * using warnings * doing a transaction, rolling it back and committing one. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Drop table if exists, and create it new stmt_drop = "DROP TABLE IF EXISTS names" cursor.execute(stmt_drop) stmt_create = """ CREATE TABLE names ( id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(30) DEFAULT '' NOT NULL, cnt TINYINT UNSIGNED DEFAULT 0, PRIMARY KEY (id) ) ENGINE=InnoDB""" cursor.execute(stmt_create) warnings = cursor.fetchwarnings() if warnings: ids = [ i for l,i,m in warnings] output.append("Oh oh.. we got warnings..") if 1266 in ids: output.append(""" Table was created as MYISAM, no transaction support. Bailing out, no use to continue. Make sure InnoDB is available! """) db.close() return # Insert 3 records output.append("Inserting data") names = ( ('Geert',), ('Jan',), ('Michel',) ) stmt_insert = "INSERT INTO names (name) VALUES (%s)" cursor.executemany(stmt_insert, names) # Roll back!!!! output.append("Rolling back transaction") db.rollback() # There should be no data! stmt_select = "SELECT id, name FROM names ORDER BY id" cursor.execute(stmt_select) rows = None try: rows = cursor.fetchall() except (mysql.connector.errors.InterfaceError) as e: raise if rows == []: output.append("No data, all is fine.") else: output.append("Something is wrong, we have data although we rolled back!") output.append(rows) raise # Do the insert again. cursor.executemany(stmt_insert, names) # Data should be already there cursor.execute(stmt_select) output.append("Data before commit:") for row in cursor.fetchall(): output.append("%d | %s" % (row[0], row[1])) # Do a commit db.commit() cursor.execute(stmt_select) output.append("Data after commit:") for row in cursor.fetchall(): output.append("%d | %s" % (row[0], row[1])) # Cleaning up, dropping the table again cursor.execute(stmt_drop) cursor.close() db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/examples/__init__.py0000644001577100000120000000000012276514013022763 0ustar pb2userwheelmysql-connector-python-1.1.6/python3/examples/config.py0000644001577100000120000000344612276514013022512 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class Config(object): """Configure me so examples work Use me like this: mysql.connector.Connect(**Config.dbinfo()) """ HOST = 'localhost' DATABASE = 'test' USER = '' PASSWORD = '' PORT = 3306 CHARSET = 'utf8' UNICODE = True WARNINGS = True @classmethod def dbinfo(cls): return { 'host': cls.HOST, 'database': cls.DATABASE, 'user': cls.USER, 'password': cls.PASSWORD, 'charset': cls.CHARSET, 'use_unicode': cls.UNICODE, 'get_warnings': cls.WARNINGS, 'port': cls.PORT, } mysql-connector-python-1.1.6/python3/examples/engines.py0000755001577100000120000000345512276514013022700 0ustar pb2userwheel#!/usr/bin/env python # -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys, os import mysql.connector """ Example using MySQL Connector/Python showing: * that show engines works.. """ def main(config): output = [] db = mysql.connector.Connect(**config) cursor = db.cursor() # Select it again and show it stmt_select = "SHOW ENGINES" cursor.execute(stmt_select) rows = cursor.fetchall() for row in rows: output.append(repr(row)) db.close() return output if __name__ == '__main__': # # Configure MySQL login and database to use in config.py # import config config = config.Config.dbinfo().copy() out = main(config) print('\n'.join(out)) mysql-connector-python-1.1.6/python3/__init__.py0000644001577100000120000000000012276514013021145 0ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/0000755001577100000120000000000012276514327020223 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/__init__.py0000644001577100000120000000000012276514013022312 0ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/connector/0000755001577100000120000000000012276514327022215 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/connector/connection.py0000644001577100000120000015063512276514013024730 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implementing communication with MySQL servers. """ import os import time import re from io import IOBase from mysql.connector.network import MySQLUnixSocket, MySQLTCPSocket from mysql.connector.constants import ( ClientFlag, ServerCmd, CharacterSet, ServerFlag, flag_is_set, ShutdownType, NET_BUFFER_LENGTH ) from mysql.connector.conversion import (MySQLConverterBase, MySQLConverter) from mysql.connector.protocol import MySQLProtocol from mysql.connector import errors from mysql.connector.utils import int4store from mysql.connector.cursor import (CursorBase, MySQLCursor, MySQLCursorRaw, MySQLCursorBuffered, MySQLCursorBufferedRaw, MySQLCursorPrepared) DEFAULT_CONFIGURATION = { 'database': None, 'user': '', 'password': '', 'host': '127.0.0.1', 'port': 3306, 'unix_socket': None, 'use_unicode': True, 'charset': 'utf8', 'collation': None, 'converter_class': MySQLConverter, 'autocommit': False, 'time_zone': None, 'sql_mode': None, 'get_warnings': False, 'raise_on_warnings': False, 'connection_timeout': None, 'client_flags': 0, 'compress': False, 'buffered': False, 'raw': False, 'ssl_ca': None, 'ssl_cert': None, 'ssl_key': None, 'ssl_verify_cert': False, 'passwd': None, 'db': None, 'connect_timeout': None, 'dsn': None, 'force_ipv6': False, } class MySQLConnection(object): """Connection to a MySQL Server""" def __init__(self, *args, **kwargs): self._protocol = None self._socket = None self._handshake = None self._server_version = None self.converter = None self._converter_class = MySQLConverter self._client_flags = ClientFlag.get_default() self._charset_id = 33 self._sql_mode = None self._time_zone = None self._autocommit = False self._user = '' self._password = '' self._database = '' self._host = '127.0.0.1' self._port = 3306 self._unix_socket = None self._client_host = '' self._client_port = 0 self._ssl = {} self._force_ipv6 = False self._use_unicode = True self._get_warnings = False self._raise_on_warnings = False self._connection_timeout = None self._buffered = False self._unread_result = False self._have_next_result = False self._raw = False self._in_transaction = False self._prepared_statements = None if len(kwargs) > 0: self.connect(**kwargs) def _get_self(self): """Return self for weakref.proxy This method is used when the original object is needed when using weakref.proxy. """ return self def _do_handshake(self): """Get the handshake from the MySQL server""" packet = self._socket.recv() if packet[4] == 255: raise errors.get_exception(packet) try: handshake = self._protocol.parse_handshake(packet) except Exception as err: raise errors.InterfaceError( 'Failed parsing handshake; {}'.format(err)) regex_ver = re.compile(br"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)") match = regex_ver.match(handshake['server_version_original']) if not match: raise errors.InterfaceError("Failed parsing MySQL version") version = tuple([int(v) for v in match.groups()[0:3]]) if version < (4, 1): raise errors.InterfaceError( "MySQL Version '{}' is not supported.".format( handshake['server_version_original'])) self._handshake = handshake self._server_version = version def _do_auth(self, username=None, password=None, database=None, client_flags=0, charset=33, ssl_options=None): """Authenticate with the MySQL server """ if client_flags & ClientFlag.SSL and ssl_options: packet = self._protocol.make_auth_ssl(charset=charset, client_flags=client_flags) self._socket.send(packet) self._socket.switch_to_ssl(**ssl_options) packet = self._protocol.make_auth( seed=self._handshake['scramble'], username=username, password=password, database=database, charset=charset, client_flags=client_flags) self._socket.send(packet) packet = self._socket.recv() if packet[4] == 254: raise errors.NotSupportedError( "Authentication with old (insecure) passwords " "is not supported. For more information, lookup " "Password Hashing in the latest MySQL manual") elif packet[4] == 255: raise errors.get_exception(packet) try: if (not (client_flags & ClientFlag.CONNECT_WITH_DB) and database): self.cmd_init_db(database) except: raise return True def config(self, *args, **kwargs): """Configure the MySQL Connection This method allows you to configure the MySQLConnection instance. Raises on errors. """ config = kwargs.copy() if 'dsn' in config: raise errors.NotSupportedError("Data source name is not supported") # Configure how we handle MySQL warnings try: self.get_warnings = config['get_warnings'] del config['get_warnings'] except KeyError: pass # Leave what was set or default try: self.raise_on_warnings = config['raise_on_warnings'] del config['raise_on_warnings'] except KeyError: pass # Leave what was set or default # Configure client flags try: default = ClientFlag.get_default() self.set_client_flags(config['client_flags'] or default) del config['client_flags'] except KeyError: pass # Missing client_flags-argument is OK try: if config['compress']: self.set_client_flags([ClientFlag.COMPRESS]) except KeyError: pass # Missing compress argument is OK # Configure character set and collation if ('charset' in config or 'collation' in config): try: charset = config['charset'] del config['charset'] except KeyError: charset = None try: collation = config['collation'] del config['collation'] except KeyError: collation = None self._charset_id = CharacterSet.get_charset_info(charset, collation)[0] # Set converter class try: self.set_converter_class(config['converter_class']) except KeyError: pass # Using default converter class except TypeError: raise AttributeError("Converter class should be a subclass " "of conversion.MySQLConverterBase.") # Compatible configuration with other drivers compat_map = [ # (,) ('db', 'database'), ('passwd', 'password'), ('connect_timeout', 'connection_timeout'), ] for compat, translate in compat_map: try: if translate not in config: config[translate] = config[compat] del config[compat] except KeyError: pass # Missing compat argument is OK # Configure login information if ('user' in config or 'password' in config): try: user = config['user'] del config['user'] except KeyError: user = self._user try: password = config['password'] del config['password'] except KeyError: password = self._password self.set_login(user, password) # Check network locations try: self._port = int(config['port']) del config['port'] except KeyError: pass # Missing port argument is OK except ValueError: raise errors.InterfaceError( "TCP/IP port number should be an integer") # Other configuration set_ssl_flag = False for key, value in config.items(): try: DEFAULT_CONFIGURATION[key] except KeyError: raise AttributeError("Unsupported argument '{}'".format(key)) # SSL Configuration if key == 'ssl_verify_cert': set_ssl_flag = True self._ssl.update({'verify_cert': value}) elif key.startswith('ssl_') and value: set_ssl_flag = True self._ssl.update({key.replace('ssl_', ''): value}) else: attribute = '_' + key try: setattr(self, attribute, value.strip()) except AttributeError: setattr(self, attribute, value) if set_ssl_flag: if 'verify_cert' not in self._ssl: self._ssl['verify_cert'] = \ DEFAULT_CONFIGURATION['ssl_verify_cert'] required_keys = set(['ca', 'cert', 'key']) diff = list(required_keys - set(self._ssl.keys())) if diff: missing_attrs = ["ssl_" + val for val in diff] raise AttributeError("Missing SSL argument(s): {0}".format( ', '.join(missing_attrs))) self.set_client_flags([ClientFlag.SSL]) def _get_connection(self, prtcls=None): """Get connection based on configuration This method will return the appropriated connection object using the connection parameters. Returns subclass of MySQLBaseSocket. """ conn = None if self.unix_socket and os.name != 'nt': conn = MySQLUnixSocket(unix_socket=self.unix_socket) else: conn = MySQLTCPSocket(host=self.server_host, port=self.server_port, force_ipv6=self._force_ipv6) conn.set_connection_timeout(self._connection_timeout) return conn def _open_connection(self): """Open the connection to the MySQL server This method sets up and opens the connection to the MySQL server. Raises on errors. """ self._socket = self._get_connection() self._socket.open_connection() self._do_handshake() self._do_auth(self._user, self._password, self._database, self._client_flags, self._charset_id, self._ssl) self.set_converter_class(self._converter_class) if self._client_flags & ClientFlag.COMPRESS: self._socket.recv = self._socket.recv_compressed self._socket.send = self._socket.send_compressed def _post_connection(self): """Executes commands after connection has been established This method executes commands after the connection has been established. Some setting like autocommit, character set, and SQL mode are set using this method. """ self.set_charset_collation(self._charset_id) self.autocommit = self._autocommit if self._time_zone: self.time_zone = self._time_zone if self._sql_mode: self.sql_mode = self._sql_mode def connect(self, **kwargs): """Connect to the MySQL server This method sets up the connection to the MySQL server. If no arguments are given, it will use the already configured or default values. """ if len(kwargs) > 0: self.config(**kwargs) self._protocol = MySQLProtocol() self.disconnect() self._open_connection() self._post_connection() def disconnect(self): """Disconnect from the MySQL server """ if not self._socket: return try: self.cmd_quit() self._socket.close_connection() except (AttributeError, errors.Error): pass # Getting an exception would mean we are disconnected. close = disconnect def _send_cmd(self, command, argument=None, packet_number=0, packet=None, expect_response=True): """Send a command to the MySQL server This method sends a command with an optional argument. If packet is not None, it will be sent and the argument will be ignored. The packet_number is optional and should usually not be used. Some commands might not result in the MySQL server returning a response. If a command does not return anything, you should set expect_response to False. The _send_cmd method will then return None instead of a MySQL packet. Returns a MySQL packet or None. """ if self.unread_result: raise errors.InternalError("Unread result found.") try: self._socket.send( self._protocol.make_command(command, packet or argument), packet_number) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") if not expect_response: return None return self._socket.recv() def _send_data(self, data_file, send_empty_packet=False): """Send data to the MySQL server This method accepts a file-like object and sends its data as is to the MySQL server. If the send_empty_packet is True, it will send an extra empty package (for example when using LOAD LOCAL DATA INFILE). Returns a MySQL packet. """ if self.unread_result: raise errors.InternalError("Unread result found.") if not hasattr(data_file, 'read'): raise ValueError("expecting a file-like object") try: buf = data_file.read(NET_BUFFER_LENGTH - 16) while buf: self._socket.send(buf) buf = data_file.read(NET_BUFFER_LENGTH - 16) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") if send_empty_packet: try: self._socket.send(b'') except AttributeError: raise errors.OperationalError( "MySQL Connection not available.") return self._socket.recv() def _handle_server_status(self, flags): """Handle the server flags found in MySQL packets This method handles the server flags send by MySQL OK and EOF packets. It, for example, checks whether there exists more result sets or whether there is an ongoing transaction. """ self._have_next_result = flag_is_set(ServerFlag.MORE_RESULTS_EXISTS, flags) self._in_transaction = flag_is_set(ServerFlag.STATUS_IN_TRANS, flags) @property def in_transaction(self): """MySQL session has started a transaction """ return self._in_transaction def _handle_ok(self, packet): """Handle a MySQL OK packet This method handles a MySQL OK packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither an OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == 0: ok_pkt = self._protocol.parse_ok(packet) self._handle_server_status(ok_pkt['server_status']) return ok_pkt elif packet[4] == 255: raise errors.get_exception(packet) raise errors.InterfaceError('Expected OK packet') def _handle_eof(self, packet): """Handle a MySQL EOF packet This method handles a MySQL EOF packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither and OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == 254: eof = self._protocol.parse_eof(packet) self._handle_server_status(eof['status_flag']) return eof elif packet[4] == 255: raise errors.get_exception(packet) raise errors.InterfaceError('Expected EOF packet') def _handle_load_data_infile(self, filename): """Handle a LOAD DATA INFILE LOCAL request""" try: data_file = open(filename, 'rb') except IOError: # Send a empty packet to cancel the operation try: self._socket.send(b'') except AttributeError: raise errors.OperationalError( "MySQL Connection not available.") raise errors.InterfaceError("File '{0}' could not be read".format( filename)) return self._handle_ok(self._send_data(data_file, send_empty_packet=True)) def _handle_result(self, packet): """Handle a MySQL Result This method handles a MySQL result, for example, after sending the query command. OK and EOF packets will be handled and returned. If the packet is an Error packet, an errors.Error-exception will be raised. The dictionary returned of: - columns: column information - eof: the EOF-packet information Returns a dict() """ if not packet or len(packet) < 4: raise errors.InterfaceError('Empty response') elif packet[4] == 0: return self._handle_ok(packet) elif packet[4] == 251: return self._handle_load_data_infile(packet[5:]) elif packet[4] == 254: return self._handle_eof(packet) elif packet[4] == 255: raise errors.get_exception(packet) # We have a text result set column_count = self._protocol.parse_column_count(packet) if not column_count or not isinstance(column_count, int): raise errors.InterfaceError('Illegal result set.') columns = [None,] * column_count for i in range(0, column_count): columns[i] = self._protocol.parse_column(self._socket.recv()) eof = self._handle_eof(self._socket.recv()) self.unread_result = True return {'columns': columns, 'eof': eof} def get_rows(self, count=None, binary=False, columns=None): """Get all rows returned by the MySQL server This method gets all rows returned by the MySQL server after sending, for example, the query command. The result is a tuple consisting of a list of rows and the EOF packet. Returns a tuple() """ if not self.unread_result: raise errors.InternalError("No result set available.") if binary: rows = self._protocol.read_binary_result( self._socket, columns, count) else: rows = self._protocol.read_text_result(self._socket, count) if rows[-1] is not None: self._handle_server_status(rows[-1]['status_flag']) self.unread_result = False return rows def get_row(self, binary=False, columns=None): """Get the next rows returned by the MySQL server This method gets one row from the result set after sending, for example, the query command. The result is a tuple consisting of the row and the EOF packet. If no row was available in the result set, the row data will be None. Returns a tuple. """ (rows, eof) = self.get_rows(count=1, binary=binary, columns=columns) if len(rows): return (rows[0], eof) return (None, eof) def cmd_init_db(self, database): """Change the current database This method changes the current (default) database by sending the INIT_DB command. The result is a dictionary containing the OK packet information. Returns a dict() """ return self._handle_ok( self._send_cmd(ServerCmd.INIT_DB, database.encode('utf-8'))) def cmd_query(self, query): """Send a query to the MySQL server This method send the query to the MySQL server and returns the result. If there was a text result, a tuple will be returned consisting of the number of columns and a list containing information about these columns. When the query doesn't return a text result, the OK or EOF packet information as dictionary will be returned. In case the result was an error, exception errors.Error will be raised. Returns a tuple() """ if not isinstance(query, bytes): query = query.encode('utf-8') result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query)) if self._have_next_result: raise errors.InterfaceError( 'Use cmd_query_iter for statements with multiple queries.') return result def cmd_query_iter(self, statements): """Send one or more statements to the MySQL server Similar to the cmd_query method, but instead returns a generator object to iterate through results. It sends the statements to the MySQL server and through the iterator you can get the results. statement = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2' for result in cnx.cmd_query(statement, iterate=True): if 'columns' in result: columns = result['columns'] rows = cnx.get_rows() else: # do something useful with INSERT result Returns a generator. """ if not isinstance(statements, bytes): statements = statements.encode('utf-8') # Handle the first query result yield self._handle_result(self._send_cmd(ServerCmd.QUERY, statements)) # Handle next results, if any while self._have_next_result: if self.unread_result: raise errors.InternalError("Unread result found.") else: result = self._handle_result(self._socket.recv()) yield result def cmd_refresh(self, options): """Send the Refresh command to the MySQL server This method sends the Refresh command to the MySQL server. The options argument should be a bitwise value using constants.RefreshOption. Usage example: RefreshOption = mysql.connector.RefreshOption refresh = RefreshOption.LOG | RefreshOption.THREADS cnx.cmd_refresh(refresh) The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok( self._send_cmd(ServerCmd.REFRESH, int4store(options))) def cmd_quit(self): """Close the current connection with the server This method sends the QUIT command to the MySQL server, closing the current connection. Since the no response can be returned to the client, cmd_quit() will return the packet it send. Returns a str() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_command(ServerCmd.QUIT) self._socket.send(packet, 0) return packet def cmd_shutdown(self, shutdown_type=None): """Shut down the MySQL Server This method sends the SHUTDOWN command to the MySQL server and is only possible if the current user has SUPER privileges. The result is a dictionary containing the OK packet information. Note: Most applications and scripts do not the SUPER privilege. Returns a dict() """ if shutdown_type: if not ShutdownType.get_info(shutdown_type): raise errors.InterfaceError("Invalid shutdown type") atype = shutdown_type else: atype = ShutdownType.SHUTDOWN_DEFAULT return self._handle_eof(self._send_cmd(ServerCmd.SHUTDOWN, atype)) def cmd_statistics(self): """Send the statistics command to the MySQL Server This method sends the STATISTICS command to the MySQL server. The result is a dictionary with various statistical information. Returns a dict() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_command(ServerCmd.STATISTICS) self._socket.send(packet, 0) return self._protocol.parse_statistics(self._socket.recv()) def cmd_process_info(self): """Get the process list of the MySQL Server This method is a placeholder to notify that the PROCESS_INFO command is not supported by raising the NotSupportedError. The command "SHOW PROCESSLIST" should be send using the cmd_query()-method or using the INFORMATION_SCHEMA database. Raises NotSupportedError exception """ raise errors.NotSupportedError( "Not implemented. Use SHOW PROCESSLIST or INFORMATION_SCHEMA") def cmd_process_kill(self, mysql_pid): """Kill a MySQL process This method send the PROCESS_KILL command to the server along with the process ID. The result is a dictionary with the OK packet information. Returns a dict() """ return self._handle_ok( self._send_cmd(ServerCmd.PROCESS_KILL, int4store(mysql_pid))) def cmd_debug(self): """Send the DEBUG command This method sends the DEBUG command to the MySQL server, which requires the MySQL user to have SUPER privilege. The output will go to the MySQL server error log and the result of this method is a dictionary with EOF packet information. Returns a dict() """ return self._handle_eof(self._send_cmd(ServerCmd.DEBUG)) def cmd_ping(self): """Send the PING command This method sends the PING command to the MySQL server. It is used to check if the the connection is still valid. The result of this method is dictionary with OK packet information. Returns a dict() """ return self._handle_ok(self._send_cmd(ServerCmd.PING)) def cmd_change_user(self, username='', password='', database='', charset=33): """Change the current logged in user This method allows to change the current logged in user information. The result is a dictionary with OK packet information. Returns a dict() """ if self.unread_result: raise errors.InternalError("Unread result found.") packet = self._protocol.make_change_user( seed=self._handshake['scramble'], username=username, password=password, database=database, charset=charset, client_flags=self._client_flags) self._socket.send(packet, 0) return self._handle_ok(self._socket.recv()) def is_connected(self): """Reports whether the connection to MySQL Server is available This method checks whether the connection to MySQL is available. It is similar to ping(), but unlike the ping()-method, either True or False is returned and no exception is raised. Returns True or False. """ try: self.cmd_ping() except: return False # This method does not raise return True def reconnect(self, attempts=1, delay=0): """Attempt to reconnect to the MySQL server The argument attempts should be the number of times a reconnect is tried. The delay argument is the number of seconds to wait between each retry. You may want to set the number of attempts higher and use delay when you expect the MySQL server to be down for maintenance or when you expect the network to be temporary unavailable. Raises InterfaceError on errors. """ counter = 0 while counter != attempts: counter = counter + 1 try: self.disconnect() self.connect() if self.is_connected(): break except Exception as err: # pylint: disable=W0703 if counter == attempts: msg = "Can not reconnect to MySQL after {} "\ "attempt(s): {}".format(attempts, str(err)) raise errors.InterfaceError(msg) if delay > 0: time.sleep(delay) def ping(self, reconnect=False, attempts=1, delay=0): """Check availability to the MySQL server When reconnect is set to True, one or more attempts are made to try to reconnect to the MySQL server using the reconnect()-method. delay is the number of seconds to wait between each retry. When the connection is not available, an InterfaceError is raised. Use the is_connected()-method if you just want to check the connection without raising an error. Raises InterfaceError on errors. """ try: self.cmd_ping() except: if reconnect: self.reconnect(attempts=attempts, delay=delay) else: raise errors.InterfaceError("Connection to MySQL is" " not available.") def set_converter_class(self, convclass): """ Set the converter class to be used. This should be a class overloading methods and members of conversion.MySQLConverter. """ if issubclass(convclass, MySQLConverterBase): charset_name = CharacterSet.get_info(self._charset_id)[0] self._converter_class = convclass self.converter = convclass(charset_name, self._use_unicode) else: raise TypeError("Converter class should be a subclass " "of conversion.MySQLConverterBase.") def get_server_version(self): """Get the MySQL version This method returns the MySQL server version as a tuple. If not previously connected, it will return None. Returns a tuple or None. """ return self._server_version def get_server_info(self): """Get the original MySQL version information This method returns the original MySQL server as text. If not previously connected, it will return None. Returns a string or None. """ try: return self._handshake['server_version_original'] except (TypeError, KeyError): return None @property def connection_id(self): """MySQL connection ID""" try: return self._handshake['server_threadid'] except KeyError: return None def set_login(self, username=None, password=None): """Set login information for MySQL Set the username and/or password for the user connecting to the MySQL Server. """ if username is not None: self._user = username.strip() else: self._user = '' if password is not None: self._password = password.strip() else: self._password = '' def set_unicode(self, value=True): """Toggle unicode mode Set whether we return string fields as unicode or not. Default is True. """ self._use_unicode = value if self.converter: self.converter.set_unicode(value) def set_charset_collation(self, charset=None, collation=None): """Sets the character set and collation for the current connection This method sets the character set and collation to be used for the current connection. The charset argument can be either the name of a character set as a string, or the numerical equivalent as defined in constants.CharacterSet. When the collation is not given, the default will be looked up and used. For example, the following will set the collation for the latin1 character set to latin1_general_ci: set_charset('latin1','latin1_general_ci') """ if charset: if isinstance(charset, int): self._charset_id = charset (charset_name, collation_name) = CharacterSet.get_info( self._charset_id) elif isinstance(charset, str): (self._charset_id, charset_name, collation_name) = \ CharacterSet.get_charset_info(charset, collation) else: raise ValueError( "charset should be either integer, string or None") elif collation: (self._charset_id, charset_name, collation_name) = \ CharacterSet.get_charset_info(collation=collation) self._execute_query("SET NAMES '{}' COLLATE '{}'".format( charset_name, collation_name)) self.converter.set_charset(charset_name) @property def charset(self): """Returns the character set for current connection This property returns the character set name of the current connection. The server is queried when the connection is active. If not connected, the configured character set name is returned. Returns a string. """ return CharacterSet.get_info(self._charset_id)[0] @property def python_charset(self): """Returns the Python character set for current connection This property returns the character set name of the current connection. Note that, unlike property charset, this checks if the previously set character set is supported by Python and if not, it returns the equivalent character set that Python supports. Returns a string. """ encoding = CharacterSet.get_info(self._charset_id)[0] if encoding == 'utf8mb4': return 'utf8' else: return encoding @property def collation(self): """Returns the collation for current connection This property returns the collation name of the current connection. The server is queried when the connection is active. If not connected, the configured collation name is returned. Returns a string. """ return CharacterSet.get_charset_info(self._charset_id)[2] def set_client_flags(self, flags): """Set the client flags The flags-argument can be either an int or a list (or tuple) of ClientFlag-values. If it is an integer, it will set client_flags to flags as is. If flags is a list (or tuple), each flag will be set or unset when it's negative. set_client_flags([ClientFlag.FOUND_ROWS,-ClientFlag.LONG_FLAG]) Raises ProgrammingError when the flags argument is not a set or an integer bigger than 0. Returns self.client_flags """ if isinstance(flags, int) and flags > 0: self._client_flags = flags elif isinstance(flags, (tuple, list)): for flag in flags: if flag < 0: self._client_flags &= ~abs(flag) else: self._client_flags |= flag else: raise errors.ProgrammingError( "set_client_flags expect integer (>0) or set") return self._client_flags def isset_client_flag(self, flag): """Check if a client flag is set""" if (self._client_flags & flag) > 0: return True return False @property def user(self): """User used while connecting to MySQL""" return self._user @property def server_host(self): """MySQL server IP address or name""" return self._host @property def server_port(self): "MySQL server TCP/IP port" return self._port @property def unix_socket(self): "MySQL Unix socket file location" return self._unix_socket def _set_unread_result(self, toggle): """Set whether there is an unread result This method is used by cursors to let other cursors know there is still a result set that needs to be retrieved. Raises ValueError on errors. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._unread_result = toggle def _get_unread_result(self): """Get whether there is an unread result This method is used by cursors to check whether another cursor still needs to retrieve its result set. Returns True, or False when there is no unread result. """ return self._unread_result unread_result = property(_get_unread_result, _set_unread_result, doc="Unread result for this MySQL connection") def set_database(self, value): """Set the current database""" self.cmd_query("USE %s" % value) def get_database(self): """Get the current database""" return self._info_query("SELECT DATABASE()")[0] database = property(get_database, set_database, doc="Current database") def set_time_zone(self, value): """Set the time zone""" self.cmd_query("SET @@session.time_zone = '{}'".format(value)) self._time_zone = value def get_time_zone(self): """Get the current time zone""" return self._info_query("SELECT @@session.time_zone")[0] time_zone = property(get_time_zone, set_time_zone, doc="time_zone value for current MySQL session") def set_sql_mode(self, value): """Set the SQL mode This method sets the SQL Mode for the current connection. The value argument can be either a string with comma separate mode names, or a sequence of mode names. It is good practice to use the constants class SQLMode: from mysql.connector.constants import SQLMode cnx.sql_mode = [SQLMode.NO_ZERO_DATE, SQLMode.REAL_AS_FLOAT] """ if isinstance(value, (list, tuple)): value = ','.join(value) self.cmd_query("SET @@session.sql_mode = '{}'".format(value)) self._sql_mode = value def get_sql_mode(self): """Get the SQL mode""" return self._info_query("SELECT @@session.sql_mode")[0] sql_mode = property(get_sql_mode, set_sql_mode, doc="sql_mode value for current MySQL session") def set_autocommit(self, value): """Toggle autocommit""" switch = 'ON' if value else 'OFF' self._execute_query("SET @@session.autocommit = {}".format(switch)) def get_autocommit(self): """Get whether autocommit is on or off""" value = self._info_query("SELECT @@session.autocommit")[0] return True if value == 1 else False autocommit = property(get_autocommit, set_autocommit, doc="autocommit value for current MySQL session") def _set_getwarnings(self, toggle): """Set whether warnings should be automatically retrieved The toggle-argument must be a boolean. When True, cursors for this connection will retrieve information about warnings (if any). Raises ValueError on error. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._get_warnings = toggle def _get_getwarnings(self): """Get whether this connection retrieves warnings automatically This method returns whether this connection retrieves warnings automatically. Returns True, or False when warnings are not retrieved. """ return self._get_warnings get_warnings = property(_get_getwarnings, _set_getwarnings, doc="Toggle and check whether to retrieve " "warnings automatically") def _set_raise_on_warnings(self, toggle): """Set whether warnings raise an error The toggle-argument must be a boolean. When True, cursors for this connection will raise an error when MySQL reports warnings. Raising on warnings implies retrieving warnings automatically. In other words: warnings will be set to True. If set to False, warnings will be also set to False. Raises ValueError on error. """ if not isinstance(toggle, bool): raise ValueError("Expected a boolean type") self._raise_on_warnings = toggle self._get_warnings = toggle def _get_raise_on_warnings(self): """Get whether this connection raises an error on warnings This method returns whether this connection will raise errors when MySQL reports warnings. Returns True or False. """ return self._raise_on_warnings raise_on_warnings = property(_get_raise_on_warnings, _set_raise_on_warnings, doc="Toggle whether to raise on warnings " "(implies retrieving warnings).") def cursor(self, buffered=None, raw=None, prepared=None, cursor_class=None): """Instantiates and returns a cursor By default, MySQLCursor is returned. Depending on the options while connecting, a buffered and/or raw cursor instantiated instead. It is possible to also give a custom cursor through the cursor_class parameter, but it needs to be a subclass of mysql.connector.cursor.CursorBase. Returns a cursor-object """ if self._unread_result is True: raise errors.InternalError("Unread result found.") if not self.is_connected(): raise errors.OperationalError("MySQL Connection not available.") if cursor_class is not None: if not issubclass(cursor_class, CursorBase): raise errors.ProgrammingError( "Cursor class needs be to subclass of cursor.CursorBase") return (cursor_class)(self) if prepared is True: return MySQLCursorPrepared(self) buffered = buffered or self._buffered raw = raw or self._raw cursor_type = 0 if buffered is True: cursor_type |= 1 if raw is True: cursor_type |= 2 types = ( MySQLCursor, # 0 MySQLCursorBuffered, MySQLCursorRaw, MySQLCursorBufferedRaw, ) return (types[cursor_type])(self) def start_transaction(self, consistent_snapshot=False, isolation_level=None, readonly=None): """Start a transaction This method explicitly starts a transaction sending the START TRANSACTION statement to the MySQL server. You can optionally set whether there should be a consistent snapshot, which isolation level you need or which access mode i.e. READ ONLY or READ WRITE. For example, to start a transaction with isolation level SERIALIZABLE, you would do the following: >>> cnx = mysql.connector.connect(..) >>> cnx.start_transaction(isolation_level='SERIALIZABLE') Raises ProgrammingError when a transaction is already in progress and when ValueError when isolation_level specifies an Unknown level. """ if self.in_transaction: raise errors.ProgrammingError("Transaction already in progress") if isolation_level: level = isolation_level.strip().replace('-', ' ').upper() levels = ['READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ', 'SERIALIZABLE'] if level not in levels: raise ValueError( 'Unknown isolation level "{0}"'.format(isolation_level)) self._execute_query( "SET TRANSACTION ISOLATION LEVEL {0}".format(level)) if readonly is not None: if self._server_version < (5, 6, 5): raise ValueError( "MySQL server version {0} does not support " "this feature".format(self._server_version)) if readonly: access_mode = 'READ ONLY' else: access_mode = 'READ WRITE' self._execute_query( "SET TRANSACTION {0}".format(access_mode)) query = "START TRANSACTION" if consistent_snapshot: query += " WITH CONSISTENT SNAPSHOT" self._execute_query(query) def commit(self): """Commit current transaction""" self._execute_query("COMMIT") def rollback(self): """Rollback current transaction""" if self._unread_result: self.get_rows() self._execute_query("ROLLBACK") def _execute_query(self, query): """Execute a query This method simply calls cmd_query() after checking for unread result. If there are still unread result, an errors.InterfaceError is raised. Otherwise whatever cmd_query() returns is returned. Returns a dict() """ if self._unread_result is True: raise errors.InternalError("Unread result found.") self.cmd_query(query) def _info_query(self, query): """Send a query which only returns 1 row""" cursor = self.cursor(buffered=True) cursor.execute(query) return cursor.fetchone() def _handle_binary_ok(self, packet): """Handle a MySQL Binary Protocol OK packet This method handles a MySQL Binary Protocol OK packet. When the packet is found to be an Error packet, an error will be raised. If the packet is neither an OK or an Error packet, errors.InterfaceError will be raised. Returns a dict() """ if packet[4] == 0: return self._protocol.parse_binary_prepare_ok(packet) elif packet[4] == 255: raise errors.get_exception(packet) raise errors.InterfaceError('Expected Binary OK packet') def _handle_binary_result(self, packet): """Handle a MySQL Result This method handles a MySQL result, for example, after sending the query command. OK and EOF packets will be handled and returned. If the packet is an Error packet, an errors.Error-exception will be raised. The tuple returned by this method consist of: - the number of columns in the result, - a list of tuples with information about the columns, - the EOF packet information as a dictionary. Returns tuple() or dict() """ if not packet or len(packet) < 4: raise errors.InterfaceError('Empty response') elif packet[4] == 0: return self._handle_ok(packet) elif packet[4] == 254: return self._handle_eof(packet) elif packet[4] == 255: raise errors.get_exception(packet) # We have a binary result set column_count = self._protocol.parse_column_count(packet) if not column_count or not isinstance(column_count, int): raise errors.InterfaceError('Illegal result set.') columns = [None] * column_count for i in range(0, column_count): columns[i] = self._protocol.parse_column(self._socket.recv()) eof = self._handle_eof(self._socket.recv()) return (column_count, columns, eof) def cmd_stmt_prepare(self, statement): """Prepare a MySQL statement This method will send the PREPARE command to MySQL together with the given statement. Returns a dict() """ packet = self._send_cmd(ServerCmd.STMT_PREPARE, statement) result = self._handle_binary_ok(packet) result['columns'] = [] result['parameters'] = [] if result['num_params'] > 0: for _ in range(0, result['num_params']): result['parameters'].append( self._protocol.parse_column(self._socket.recv())) self._handle_eof(self._socket.recv()) if result['num_columns'] > 0: for _ in range(0, result['num_columns']): result['columns'].append( self._protocol.parse_column(self._socket.recv())) self._handle_eof(self._socket.recv()) return result def cmd_stmt_execute(self, statement_id, data=(), parameters=(), flags=0): """Execute a prepared MySQL statement""" parameters = list(parameters) long_data_used = {} if data: for param_id, _ in enumerate(parameters): if isinstance(data[param_id], IOBase): binary = True try: binary = 'b' not in data[param_id].mode except AttributeError: pass self.cmd_stmt_send_long_data(statement_id, param_id, data[param_id]) long_data_used[param_id] = (binary,) execute_packet = self._protocol.make_stmt_execute( statement_id, data, tuple(parameters), flags, long_data_used) packet = self._send_cmd(ServerCmd.STMT_EXECUTE, packet=execute_packet) result = self._handle_binary_result(packet) return result def cmd_stmt_close(self, statement_id): """Deallocate a prepared MySQL statement This method deallocates the prepared statement using the statement_id. Note that the MySQL server does not return anything. """ self._send_cmd(ServerCmd.STMT_CLOSE, int4store(statement_id), expect_response=False) def cmd_stmt_send_long_data(self, statement_id, param_id, data): """Send data for a column This methods send data for a column (for example BLOB) for statement identified by statement_id. The param_id indicate which parameter the data belongs too. The data argument should be a file-like object. Since MySQL does not send anything back, no error is raised. When the MySQL server is not reachable, an OperationalError is raised. cmd_stmt_send_long_data should be called before cmd_stmt_execute. The total bytes send is returned. Returns int. """ chunk_size = 8192 total_sent = 0 # pylint: disable=W0212 prepare_packet = self._protocol._prepare_stmt_send_long_data # pylint: enable=W0212 try: buf = data.read(chunk_size) while buf: packet = prepare_packet(statement_id, param_id, buf) self._send_cmd(ServerCmd.STMT_SEND_LONG_DATA, packet=packet, expect_response=False) total_sent += len(buf) buf = data.read(chunk_size) except AttributeError: raise errors.OperationalError("MySQL Connection not available.") return total_sent def cmd_stmt_reset(self, statement_id): """Reset data for prepared statement sent as long data The result is a dictionary with OK packet information. Returns a dict() """ self._handle_ok(self._send_cmd(ServerCmd.STMT_RESET, int4store(statement_id))) mysql-connector-python-1.1.6/python3/mysql/connector/utils.py0000644001577100000120000001771112276514013023726 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Utilities """ __MYSQL_DEBUG__ = False import struct def intread(buf): """Unpacks the given buffer to an integer""" try: if isinstance(buf, int): return buf length = len(buf) if length == 1: return buf[0] elif length <= 4: tmp = buf + b'\x00'*(4-length) return struct.unpack(' 255: raise ValueError('int1store requires 0 <= i <= 255') else: return struct.pack(' 65535: raise ValueError('int2store requires 0 <= i <= 65535') else: return struct.pack(' 16777215: raise ValueError('int3store requires 0 <= i <= 16777215') else: return struct.pack(' 4294967295: raise ValueError('int4store requires 0 <= i <= 4294967295') else: return struct.pack(' 18446744073709551616: raise ValueError('int4store requires 0 <= i <= 2^64') else: return struct.pack(' 18446744073709551616: raise ValueError('intstore requires 0 <= i <= 2^64') if i <= 255: formed_string = int1store elif i <= 65535: formed_string = int2store elif i <= 16777215: formed_string = int3store elif i <= 4294967295: formed_string = int4store else: formed_string = int8store return formed_string(i) def read_bytes(buf, size): """ Reads bytes from a buffer. Returns a tuple with buffer less the read bytes, and the bytes. """ res = buf[0:size] return (buf[size:], res) def read_lc_string(buf): """ Takes a buffer and reads a length coded string from the start. This is how Length coded strings work If the string is 250 bytes long or smaller, then it looks like this: <-- 1b --> +----------+------------------------- | length | a string goes here +----------+------------------------- If the string is bigger than 250, then it looks like this: <- 1b -><- 2/3/8 -> +------+-----------+------------------------- | type | length | a string goes here +------+-----------+------------------------- if type == \xfc: length is code in next 2 bytes elif type == \xfd: length is code in next 3 bytes elif type == \xfe: length is code in next 8 bytes NULL has a special value. If the buffer starts with \xfb then it's a NULL and we return None as value. Returns a tuple (trucated buffer, bytes). """ if buf[0] == 251: # \xfb # NULL value return (buf[1:], None) length = lsize = 0 fst = buf[0] if fst <= 250: # \xFA length = fst return (buf[1 + length:], buf[1:length + 1]) elif fst == 252: lsize = 2 elif fst == 253: lsize = 3 if fst == 254: lsize = 8 length = intread(buf[1:lsize + 1]) return (buf[lsize + length + 1:], buf[lsize + 1:length + lsize + 1]) def read_lc_string_list(buf): """Reads all length encoded strings from the given buffer Returns a list of bytes """ byteslst = [] view = memoryview(buf) sizes = { b'\xfc': 2, b'\xfd': 3, b'\xfe': 8 } while view: first = bytes(view[0:1]) if first == b'\xff': # Special case when MySQL error 1317 is returned by MySQL. # We simply return None. return None if first == b'\xfb': # NULL value byteslst.append(None) view = view[1:] else: if first <= b'\xfa': length = first[0] byteslst.append(bytes(view[1:length + 1])) view = view[1 + length:] else: lsize = 0 try: lsize = sizes[first] except KeyError: print(buf) print(_digest_buffer(buf)) return None length = intread(bytes(view[1:lsize + 1])) byteslst.append(bytes(view[lsize + 1:length + lsize + 1])) view = view[lsize + length + 1:] return tuple(byteslst) def read_string(buf, end=None, size=None): """ Reads a string up until a character or for a given size. Returns a tuple (trucated buffer, string). """ if end is None and size is None: raise ValueError('read_string() needs either end or size') if end is not None: try: idx = buf.index(end) except (ValueError): raise ValueError("end byte not precent in buffer") return (buf[idx + 1:], buf[0:idx]) elif size is not None: return read_bytes(buf, size) raise ValueError('read_string() needs either end or size (weird)') def read_int(buf, size): """Read an integer from buffer Returns a tuple (truncated buffer, int) """ try: res = intread(buf[0:size]) except: raise return (buf[size:], res) def read_lc_int(buf): """ Takes a buffer and reads an length code string from the start. Returns a tuple with buffer less the integer and the integer read. """ if not buf: raise ValueError("Empty buffer.") lcbyte = buf[0] if lcbyte == 251: return (buf[1:], None) elif lcbyte < 251: return (buf[1:], int(lcbyte)) elif lcbyte == 252: return (buf[3:], struct.unpack(', like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implementing pooling of connections to MySQL servers. """ import re from uuid import uuid4 import queue import threading from mysql.connector import errors from mysql.connector.connection import MySQLConnection CONNECTION_POOL_LOCK = threading.RLock() CNX_POOL_ARGS = ('pool_name', 'pool_size', 'pool_cnx') CNX_POOL_MAXSIZE = 32 CNX_POOL_MAXNAMESIZE = 64 CNX_POOL_NAMEREGEX = re.compile(r'[^a-zA-Z0-9._\-*$#]') def generate_pool_name(**kwargs): """Generate a pool name This function takes keyword arguments, usually the connection arguments for MySQLConnection, and tries to generate a name for a pool. Raises PoolError when no name can be generated. Returns a string. """ parts = [] for key in ('host', 'port', 'user', 'database'): try: parts.append(str(kwargs[key])) except KeyError: pass if not parts: raise errors.PoolError( "Failed generating pool name; specify pool_name") return '_'.join(parts) class PooledMySQLConnection(object): """Class holding a MySQL Connection in a pool PooledMySQLConnection is used by MySQLConnectionPool to return an instance holding a MySQL connection. It works like a MySQLConnection except for methods like close() and config(). The close()-method will add the connection back to the pool rather than disconnecting from the MySQL server. Configuring the connection have to be done through the MySQLConnectionPool method set_config(). Using config() on pooled connection will raise a PoolError. """ def __init__(self, pool, cnx): """Initialize The pool argument must be an instance of MySQLConnectionPoll. cnx if an instance of MySQLConnection. """ if not isinstance(pool, MySQLConnectionPool): raise AttributeError( "pool should be a MySQLConnectionPool") if not isinstance(cnx, MySQLConnection): raise AttributeError( "cnx should be a MySQLConnection") self._cnx_pool = pool self._cnx = cnx def __getattr__(self, attr): """Calls attributes of the MySQLConnection instance""" return getattr(self._cnx, attr) def close(self): """Do not close, but add connection back to pool The close() method does not close the connection with the MySQL server. The connection is added back to the pool so it can be reused. """ cnx = self._cnx if self._cnx_pool.reset_session: # pylint: disable=W0212 cnx.cmd_change_user(cnx._user, cnx._password, cnx._database, cnx._charset_id) # pylint: enable=W0212 self._cnx_pool.add_connection(cnx) self._cnx = None def config(self, **kwargs): """Configuration is done through the pool""" raise errors.PoolError( "Configuration for pooled connections should " "be done through the pool itself." ) @property def pool_name(self): """Return the name of the connection pool""" return self._cnx_pool.pool_name class MySQLConnectionPool(object): """Class defining a pool of MySQL connections""" def __init__(self, pool_size=5, pool_name=None, pool_reset_session=True, **kwargs): """Initialize Initialize a MySQL connection pool with a maximum number of connections set to pool_size. The rest of the keywords arguments, kwargs, are configuration arguments for MySQLConnection instances. """ self._pool_size = None self._pool_name = None self._reset_session = pool_reset_session self._set_pool_size(pool_size) self._set_pool_name(pool_name or generate_pool_name(**kwargs)) self._cnx_config = {} self._cnx_queue = queue.Queue(self._pool_size) self._config_version = uuid4() if kwargs: self.set_config(**kwargs) cnt = 0 while cnt < self._pool_size: self.add_connection() cnt += 1 @property def pool_name(self): """Return the name of the connection pool""" return self._pool_name @property def pool_size(self): """Return number of connections managed by the pool""" return self._pool_size @property def reset_session(self): """Return whether to reset session""" return self._reset_session def set_config(self, **kwargs): """Set the connection configuration for MySQLConnection instances This method sets the configuration used for creating MySQLConnection instances. See MySQLConnection for valid connection arguments. Raises PoolError when a connection argument is not valid, missing or not supported by MySQLConnection. """ if not kwargs: return with CONNECTION_POOL_LOCK: try: test_cnx = MySQLConnection() test_cnx.config(**kwargs) self._cnx_config = kwargs self._config_version = uuid4() except AttributeError as err: raise errors.PoolError( "Connection configuration not valid: {0}".format(err)) def _set_pool_size(self, pool_size): """Set the size of the pool This method sets the size of the pool but it will not resize the pool. Raises an AttributeError when the pool_size is not valid. Invalid size is 0, negative or higher than pooling.CNX_POOL_MAXSIZE. """ if pool_size <= 0 or pool_size > CNX_POOL_MAXSIZE: raise AttributeError( "Pool size should be higher than 0 and " "lower or equal to {0}".format(CNX_POOL_MAXSIZE)) self._pool_size = pool_size def _set_pool_name(self, pool_name): r"""Set the name of the pool This method checks the validity and sets the name of the pool. Raises an AttributeError when pool_name contains illegal characters ([^a-zA-Z0-9._\-*$#]) or is longer than pooling.CNX_POOL_MAXNAMESIZE. """ if CNX_POOL_NAMEREGEX.search(pool_name): raise AttributeError( "Pool name '{0}' contains illegal characters".format(pool_name)) if len(pool_name) > CNX_POOL_MAXNAMESIZE: raise AttributeError( "Pool name '{0}' is too long".format(pool_name)) self._pool_name = pool_name def _queue_connection(self, cnx): """Put connection back in the queue This method is putting a connection back in the queue. It will not acquire a lock as the methods using _queue_connection() will have it set. Raises PoolError on errors. """ if not isinstance(cnx, MySQLConnection): raise errors.PoolError( "Connection instance not subclass of MySQLConnection.") try: self._cnx_queue.put(cnx, block=False) except queue.Full: errors.PoolError("Failed adding connection; queue is full") def add_connection(self, cnx=None): """Add a connection to the pool This method instantiates a MySQLConnection using the configuration passed when initializing the MySQLConnectionPool instance or using the set_config() method. If cnx is a MySQLConnection instance, it will be added to the queue. Raises PoolError when no configuration is set, when no more connection can be added (maximum reached) or when the connection can not be instantiated. """ with CONNECTION_POOL_LOCK: if not self._cnx_config: raise errors.PoolError( "Connection configuration not available") if self._cnx_queue.full(): raise errors.PoolError( "Failed adding connection; queue is full") if not cnx: cnx = MySQLConnection(**self._cnx_config) # pylint: disable=W0212 cnx._pool_config_version = self._config_version # pylint: enable=W0212 else: if not isinstance(cnx, MySQLConnection): raise errors.PoolError( "Connection instance not subclass of MySQLConnection.") self._queue_connection(cnx) def get_connection(self): """Get a connection from the pool This method returns an PooledMySQLConnection instance which has a reference to the pool that created it, and the next available MySQL connection. When the MySQL connection is not connect, a reconnect is attempted. Raises PoolError on errors. Returns a PooledMySQLConnection instance. """ with CONNECTION_POOL_LOCK: try: cnx = self._cnx_queue.get(block=False) except queue.Empty: raise errors.PoolError( "Failed getting connection; pool exhausted") # pylint: disable=W0212 if (not cnx.is_connected() or self._config_version != cnx._pool_config_version): cnx.config(**self._cnx_config) try: cnx.reconnect() except errors.InterfaceError: # Failed to reconnect, give connection back to pool self._queue_connection(cnx) raise cnx._pool_config_version = self._config_version # pylint: enable=W0212 return PooledMySQLConnection(self, cnx) def _remove_connections(self): """Close all connections This method closes all connections. It returns the number of connections it closed. Used mostly for tests. Returns int. """ with CONNECTION_POOL_LOCK: cnt = 0 cnxq = self._cnx_queue while cnxq.qsize(): try: cnx = cnxq.get(block=False) cnx.disconnect() cnt += 1 except queue.Empty: return cnt except errors.PoolError: raise except errors.Error: # Any other error when closing means connection is closed pass return cnt mysql-connector-python-1.1.6/python3/mysql/connector/version.py0000644001577100000120000000303012276514013024240 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """MySQL Connector/Python version information The file version.py gets installed and is available after installation as mysql.connector.version. """ VERSION = (1, 1, 6, '', 0) if VERSION[3] and VERSION[4]: VERSION_TEXT = '{0}.{1}.{2}{3}{4}'.format(*VERSION) else: VERSION_TEXT = '{0}.{1}.{2}'.format(*VERSION[0:3]) LICENSE = 'GPLv2 with FOSS License Exception' EDITION = '' # Added in package names, after the version mysql-connector-python-1.1.6/python3/mysql/connector/protocol.py0000644001577100000120000005514112276514013024426 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Implements the MySQL Client/Server protocol """ import struct import datetime from decimal import Decimal # pylint: disable=F0401 try: from hashlib import sha1 except ImportError: from sha import new as sha1 # pylint: enable=F0401 from mysql.connector.constants import (FieldFlag, ServerCmd, FieldType) from mysql.connector import (errors, utils) class MySQLProtocol(object): """ Implemets MySQL client/server protocol. Creates and parse packets based on MySQL client/server protocol. """ def _scramble_password(self, passwd, seed): """Scramble a password ready to send to MySQL""" hash4 = None try: hash1 = sha1(passwd).digest() hash2 = sha1(hash1).digest() # Password as found in mysql.user() hash3 = sha1(seed + hash2).digest() xored = [h1 ^ h3 for (h1, h3) in zip(hash1, hash3)] hash4 = struct.pack('20B', *xored) except Exception as err: raise errors.InterfaceError('Failed scrambling password; %s' % err) return hash4 def _prepare_auth(self, usr, pwd, dbname, flags, seed): """Prepare elements of the authentication packet""" if usr is not None and len(usr) > 0: _username = usr.encode('utf-8') + b'\x00' else: _username = b'\x00' if pwd is not None and len(pwd) > 0: _password = utils.int1store(20) +\ self._scramble_password(pwd.encode('utf-8'), seed) else: _password = b'\x00' if dbname is not None and len(dbname): _database = dbname.encode('utf-8') + b'\x00' else: _database = b'\x00' return (_username, _password, _database) def make_auth(self, seed, username=None, password=None, database=None, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a MySQL Authentication packet""" if not seed: raise errors.ProgrammingError('Seed missing') auth = self._prepare_auth(username, password, database, client_flags, seed) data = utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ b'\x00' * 23 + auth[0] + auth[1] + auth[2] return data def make_auth_ssl(self, charset=33, client_flags=0, max_allowed_packet=1073741824): """Make a SSL authentication packet""" return utils.int4store(client_flags) +\ utils.int4store(max_allowed_packet) +\ utils.int1store(charset) +\ b'\x00' * 23 def make_command(self, command, argument=None): """Make a MySQL packet containing a command""" data = utils.int1store(command) if argument is not None: data += argument return data def make_change_user(self, seed, username=None, password=None, database=None, charset=33, client_flags=0): """Make a MySQL packet with the Change User command""" if not seed: raise errors.ProgrammingError('Seed missing') auth = self._prepare_auth(username, password, database, client_flags, seed) data = utils.int1store(ServerCmd.CHANGE_USER) +\ auth[0] + auth[1] + auth[2] + utils.int2store(charset) return data def parse_handshake(self, packet): """Parse a MySQL Handshake-packet""" res = {} (packet, res['protocol']) = utils.read_int(packet[4:], 1) (packet, res['server_version_original']) = utils.read_string( packet, end=b'\x00') (packet, res['server_threadid']) = utils.read_int(packet, 4) (packet, res['scramble']) = utils.read_bytes(packet, 8) packet = packet[1:] # Filler 1 * \x00 (packet, res['capabilities']) = utils.read_int(packet, 2) (packet, res['charset']) = utils.read_int(packet, 1) (packet, res['server_status']) = utils.read_int(packet, 2) packet = packet[13:] # Filler 13 * \x00 (packet, scramble_next) = utils.read_bytes(packet, 12) res['scramble'] += scramble_next return res def parse_ok(self, packet): """Parse a MySQL OK-packet""" if not packet[4] == 0: raise errors.InterfaceError("Failed parsing OK packet.") ok_packet = {} try: ok_packet['field_count'] = struct.unpack('= 7: mcs = 0 if length == 11: mcs = struct.unpack('I', packet[8:length + 1])[0] value = datetime.datetime( year=struct.unpack('H', packet[1:3])[0], month=packet[3], day=packet[4], hour=packet[5], minute=packet[6], second=packet[7], microsecond=mcs) return (packet[length + 1:], value) def _parse_binary_time(self, packet, field): """Parse a time value from a binary packet""" length = packet[0] data = packet[1:length + 1] mcs = 0 if length > 8: mcs = struct.unpack('I', data[8:])[0] days = struct.unpack('I', data[1:5])[0] if data[0] == 1: days *= -1 tmp = datetime.timedelta(days=days, seconds=data[7], microseconds=mcs, minutes=data[6], hours=data[5]) return (packet[length + 1:], tmp) def _parse_binary_values(self, fields, packet): """Parse values from a binary result packet""" null_bitmap_length = (len(fields) + 7 + 2) // 8 null_bitmap = utils.intread(packet[0:null_bitmap_length]) packet = packet[null_bitmap_length:] values = [] for pos, field in enumerate(fields): if null_bitmap & 1 << (pos + 2): values.append(None) continue elif field[1] in (FieldType.TINY, FieldType.SHORT, FieldType.INT24, FieldType.LONG, FieldType.LONGLONG): (packet, value) = self._parse_binary_integer(packet, field) values.append(value) elif field[1] in (FieldType.DOUBLE, FieldType.FLOAT): (packet, value) = self._parse_binary_float(packet, field) values.append(value) elif field[1] in (FieldType.DATETIME, FieldType.DATE, FieldType.TIMESTAMP): (packet, value) = self._parse_binary_timestamp(packet, field) values.append(value) elif field[1] == FieldType.TIME: (packet, value) = self._parse_binary_time(packet, field) values.append(value) else: (packet, value) = utils.read_lc_string(packet) values.append(value) return tuple(values) def read_binary_result(self, sock, columns, count=1): """Read MySQL binary protocol result Reads all or given number of binary resultset rows from the socket. """ rows = [] eof = None values = None i = 0 while True: if eof is not None: break if i == count: break packet = sock.recv() if packet[4] == 254: eof = self.parse_eof(packet) values = None elif packet[4] == 0: eof = None values = self._parse_binary_values(columns, packet[5:]) if eof is None and values is not None: rows.append(values) i += 1 return (rows, eof) def parse_binary_prepare_ok(self, packet): """Parse a MySQL Binary Protocol OK packet""" if not packet[4] == 0: raise errors.InterfaceError("Failed parsing Binary OK packet") ok_pkt = {} try: (packet, ok_pkt['statement_id']) = utils.read_int(packet[5:], 4) (packet, ok_pkt['num_columns']) = utils.read_int(packet, 2) (packet, ok_pkt['num_params']) = utils.read_int(packet, 2) packet = packet[1:] # Filler 1 * \x00 (packet, ok_pkt['warning_count']) = utils.read_int(packet, 2) except ValueError: raise errors.InterfaceError("Failed parsing Binary OK packet") return ok_pkt def _prepare_binary_integer(self, value): """Prepare an integer for the MySQL binary protocol""" field_type = None flags = 0 if value < 0: if value >= -128: format_ = 'b' field_type = FieldType.TINY elif value >= -32768: format_ = 'h' field_type = FieldType.SHORT elif value >= -2147483648: format_ = 'i' field_type = FieldType.LONG else: format_ = 'q' field_type = FieldType.LONGLONG else: flags = 128 if value <= 255: format_ = 'B' field_type = FieldType.TINY elif value <= 65535: format_ = 'H' field_type = FieldType.SHORT elif value <= 4294967295: format_ = 'I' field_type = FieldType.LONG else: field_type = FieldType.LONGLONG format_ = 'Q' return (struct.pack(format_, value), field_type, flags) def _prepare_binary_timestamp(self, value): """Prepare a timestamp object for the MySQL binary protocol This method prepares a timestamp of type datetime.datetime or datetime.date for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if isinstance(value, datetime.datetime): field_type = FieldType.DATETIME elif isinstance(value, datetime.date): field_type = FieldType.DATE else: raise ValueError( "Argument must a datetime.datetime or datetime.date") packed = (utils.int2store(value.year) + utils.int1store(value.month) + utils.int1store(value.day)) if isinstance(value, datetime.datetime): packed = (packed + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) if value.microsecond > 0: packed += utils.int4store(value.microsecond) packed = utils.int1store(len(packed)) + packed return (packed, field_type) def _prepare_binary_time(self, value): """Prepare a time object for the MySQL binary protocol This method prepares a time object of type datetime.timedelta or datetime.time for sending over the MySQL binary protocol. A tuple is returned with the prepared value and field type as elements. Raises ValueError when the argument value is of invalid type. Returns a tuple. """ if not isinstance(value, (datetime.timedelta, datetime.time)): raise ValueError( "Argument must a datetime.timedelta or datetime.time") field_type = FieldType.TIME negative = 0 mcs = None packed = b'' if isinstance(value, datetime.timedelta): if value.days < 0: negative = 1 (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) packed += (utils.int4store(abs(value.days)) + utils.int1store(hours) + utils.int1store(mins) + utils.int1store(secs)) mcs = value.microseconds else: packed += (utils.int4store(0) + utils.int1store(value.hour) + utils.int1store(value.minute) + utils.int1store(value.second)) mcs = value.microsecond if mcs: packed += utils.int4store(mcs) packed = utils.int1store(negative) + packed packed = utils.int1store(len(packed)) + packed return (packed, field_type) def _prepare_stmt_send_long_data(self, statement, param, data): """Prepare long data for prepared statments Returns a string. """ packet = ( utils.int4store(statement) + utils.int2store(param) + data) return packet def make_stmt_execute(self, statement_id, data=(), parameters=(), flags=0, long_data_used=None): """Make a MySQL packet with the Statement Execute command""" iteration_count = 1 null_bitmap = [0] * ((len(data) + 7) // 8) values = [] types = [] packed = b'' if long_data_used is None: long_data_used = {} if parameters and data: if len(data) != len(parameters): raise errors.InterfaceError( "Failed executing prepared statement: data values does not" " match number of parameters") for pos, _ in enumerate(parameters): value = data[pos] flags = 0 if value is None: null_bitmap[(pos // 8)] |= 1 << (pos % 8) continue elif pos in long_data_used: if long_data_used[pos][0]: # We suppose binary data field_type = FieldType.BLOB else: # We suppose text data field_type = FieldType.STRING elif isinstance(value, int): (packed, field_type, flags) = self._prepare_binary_integer(value) values.append(packed) elif isinstance(value, str): values.append( utils.intstore(len(value)) + value.encode('utf8')) field_type = FieldType.VARCHAR elif isinstance(value, Decimal): values.append( utils.intstore(len(str(value))) +\ str(value).encode('utf8')) field_type = FieldType.DECIMAL elif isinstance(value, float): values.append(struct.pack('d', value)) field_type = FieldType.DOUBLE elif isinstance(value, (datetime.datetime, datetime.date)): (packed, field_type) = self._prepare_binary_timestamp( value) values.append(packed) elif isinstance(value, (datetime.timedelta, datetime.time)): (packed, field_type) = self._prepare_binary_time(value) values.append(packed) else: raise errors.ProgrammingError( "MySQL binary protocol can not handle " "'{classname}' objects".format( classname=value.__class__.__name__)) types.append(utils.int1store(field_type) + utils.int1store(flags)) packet = ( utils.int4store(statement_id), utils.int1store(flags), utils.int4store(iteration_count), b''.join([struct.pack('B', bit) for bit in null_bitmap]), utils.int1store(1), b''.join(types), b''.join(values) ) return b''.join(packet) mysql-connector-python-1.1.6/python3/mysql/connector/charsets.py0000644001577100000120000002760712276514013024407 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. # GENERATED_ON = '2013-12-18' # MYSQL_VERSION = (5, 7, 2) """This module contains the MySQL Server Character Sets""" MYSQL_CHARACTER_SETS = [ # (character set name, collation, default) None, ("big5", "big5_chinese_ci", True), # 1 ("latin2", "latin2_czech_cs", False), # 2 ("dec8", "dec8_swedish_ci", True), # 3 ("cp850", "cp850_general_ci", True), # 4 ("latin1", "latin1_german1_ci", False), # 5 ("hp8", "hp8_english_ci", True), # 6 ("koi8r", "koi8r_general_ci", True), # 7 ("latin1", "latin1_swedish_ci", True), # 8 ("latin2", "latin2_general_ci", True), # 9 ("swe7", "swe7_swedish_ci", True), # 10 ("ascii", "ascii_general_ci", True), # 11 ("ujis", "ujis_japanese_ci", True), # 12 ("sjis", "sjis_japanese_ci", True), # 13 ("cp1251", "cp1251_bulgarian_ci", False), # 14 ("latin1", "latin1_danish_ci", False), # 15 ("hebrew", "hebrew_general_ci", True), # 16 None, ("tis620", "tis620_thai_ci", True), # 18 ("euckr", "euckr_korean_ci", True), # 19 ("latin7", "latin7_estonian_cs", False), # 20 ("latin2", "latin2_hungarian_ci", False), # 21 ("koi8u", "koi8u_general_ci", True), # 22 ("cp1251", "cp1251_ukrainian_ci", False), # 23 ("gb2312", "gb2312_chinese_ci", True), # 24 ("greek", "greek_general_ci", True), # 25 ("cp1250", "cp1250_general_ci", True), # 26 ("latin2", "latin2_croatian_ci", False), # 27 ("gbk", "gbk_chinese_ci", True), # 28 ("cp1257", "cp1257_lithuanian_ci", False), # 29 ("latin5", "latin5_turkish_ci", True), # 30 ("latin1", "latin1_german2_ci", False), # 31 ("armscii8", "armscii8_general_ci", True), # 32 ("utf8", "utf8_general_ci", True), # 33 ("cp1250", "cp1250_czech_cs", False), # 34 ("ucs2", "ucs2_general_ci", True), # 35 ("cp866", "cp866_general_ci", True), # 36 ("keybcs2", "keybcs2_general_ci", True), # 37 ("macce", "macce_general_ci", True), # 38 ("macroman", "macroman_general_ci", True), # 39 ("cp852", "cp852_general_ci", True), # 40 ("latin7", "latin7_general_ci", True), # 41 ("latin7", "latin7_general_cs", False), # 42 ("macce", "macce_bin", False), # 43 ("cp1250", "cp1250_croatian_ci", False), # 44 ("utf8mb4", "utf8mb4_general_ci", True), # 45 ("utf8mb4", "utf8mb4_bin", False), # 46 ("latin1", "latin1_bin", False), # 47 ("latin1", "latin1_general_ci", False), # 48 ("latin1", "latin1_general_cs", False), # 49 ("cp1251", "cp1251_bin", False), # 50 ("cp1251", "cp1251_general_ci", True), # 51 ("cp1251", "cp1251_general_cs", False), # 52 ("macroman", "macroman_bin", False), # 53 ("utf16", "utf16_general_ci", True), # 54 ("utf16", "utf16_bin", False), # 55 ("utf16le", "utf16le_general_ci", True), # 56 ("cp1256", "cp1256_general_ci", True), # 57 ("cp1257", "cp1257_bin", False), # 58 ("cp1257", "cp1257_general_ci", True), # 59 ("utf32", "utf32_general_ci", True), # 60 ("utf32", "utf32_bin", False), # 61 ("utf16le", "utf16le_bin", False), # 62 ("binary", "binary", True), # 63 ("armscii8", "armscii8_bin", False), # 64 ("ascii", "ascii_bin", False), # 65 ("cp1250", "cp1250_bin", False), # 66 ("cp1256", "cp1256_bin", False), # 67 ("cp866", "cp866_bin", False), # 68 ("dec8", "dec8_bin", False), # 69 ("greek", "greek_bin", False), # 70 ("hebrew", "hebrew_bin", False), # 71 ("hp8", "hp8_bin", False), # 72 ("keybcs2", "keybcs2_bin", False), # 73 ("koi8r", "koi8r_bin", False), # 74 ("koi8u", "koi8u_bin", False), # 75 None, ("latin2", "latin2_bin", False), # 77 ("latin5", "latin5_bin", False), # 78 ("latin7", "latin7_bin", False), # 79 ("cp850", "cp850_bin", False), # 80 ("cp852", "cp852_bin", False), # 81 ("swe7", "swe7_bin", False), # 82 ("utf8", "utf8_bin", False), # 83 ("big5", "big5_bin", False), # 84 ("euckr", "euckr_bin", False), # 85 ("gb2312", "gb2312_bin", False), # 86 ("gbk", "gbk_bin", False), # 87 ("sjis", "sjis_bin", False), # 88 ("tis620", "tis620_bin", False), # 89 ("ucs2", "ucs2_bin", False), # 90 ("ujis", "ujis_bin", False), # 91 ("geostd8", "geostd8_general_ci", True), # 92 ("geostd8", "geostd8_bin", False), # 93 ("latin1", "latin1_spanish_ci", False), # 94 ("cp932", "cp932_japanese_ci", True), # 95 ("cp932", "cp932_bin", False), # 96 ("eucjpms", "eucjpms_japanese_ci", True), # 97 ("eucjpms", "eucjpms_bin", False), # 98 ("cp1250", "cp1250_polish_ci", False), # 99 None, ("utf16", "utf16_unicode_ci", False), # 101 ("utf16", "utf16_icelandic_ci", False), # 102 ("utf16", "utf16_latvian_ci", False), # 103 ("utf16", "utf16_romanian_ci", False), # 104 ("utf16", "utf16_slovenian_ci", False), # 105 ("utf16", "utf16_polish_ci", False), # 106 ("utf16", "utf16_estonian_ci", False), # 107 ("utf16", "utf16_spanish_ci", False), # 108 ("utf16", "utf16_swedish_ci", False), # 109 ("utf16", "utf16_turkish_ci", False), # 110 ("utf16", "utf16_czech_ci", False), # 111 ("utf16", "utf16_danish_ci", False), # 112 ("utf16", "utf16_lithuanian_ci", False), # 113 ("utf16", "utf16_slovak_ci", False), # 114 ("utf16", "utf16_spanish2_ci", False), # 115 ("utf16", "utf16_roman_ci", False), # 116 ("utf16", "utf16_persian_ci", False), # 117 ("utf16", "utf16_esperanto_ci", False), # 118 ("utf16", "utf16_hungarian_ci", False), # 119 ("utf16", "utf16_sinhala_ci", False), # 120 ("utf16", "utf16_german2_ci", False), # 121 ("utf16", "utf16_croatian_ci", False), # 122 ("utf16", "utf16_unicode_520_ci", False), # 123 ("utf16", "utf16_vietnamese_ci", False), # 124 None, None, None, ("ucs2", "ucs2_unicode_ci", False), # 128 ("ucs2", "ucs2_icelandic_ci", False), # 129 ("ucs2", "ucs2_latvian_ci", False), # 130 ("ucs2", "ucs2_romanian_ci", False), # 131 ("ucs2", "ucs2_slovenian_ci", False), # 132 ("ucs2", "ucs2_polish_ci", False), # 133 ("ucs2", "ucs2_estonian_ci", False), # 134 ("ucs2", "ucs2_spanish_ci", False), # 135 ("ucs2", "ucs2_swedish_ci", False), # 136 ("ucs2", "ucs2_turkish_ci", False), # 137 ("ucs2", "ucs2_czech_ci", False), # 138 ("ucs2", "ucs2_danish_ci", False), # 139 ("ucs2", "ucs2_lithuanian_ci", False), # 140 ("ucs2", "ucs2_slovak_ci", False), # 141 ("ucs2", "ucs2_spanish2_ci", False), # 142 ("ucs2", "ucs2_roman_ci", False), # 143 ("ucs2", "ucs2_persian_ci", False), # 144 ("ucs2", "ucs2_esperanto_ci", False), # 145 ("ucs2", "ucs2_hungarian_ci", False), # 146 ("ucs2", "ucs2_sinhala_ci", False), # 147 ("ucs2", "ucs2_german2_ci", False), # 148 ("ucs2", "ucs2_croatian_ci", False), # 149 ("ucs2", "ucs2_unicode_520_ci", False), # 150 ("ucs2", "ucs2_vietnamese_ci", False), # 151 None, None, None, None, None, None, None, ("ucs2", "ucs2_general_mysql500_ci", False), # 159 ("utf32", "utf32_unicode_ci", False), # 160 ("utf32", "utf32_icelandic_ci", False), # 161 ("utf32", "utf32_latvian_ci", False), # 162 ("utf32", "utf32_romanian_ci", False), # 163 ("utf32", "utf32_slovenian_ci", False), # 164 ("utf32", "utf32_polish_ci", False), # 165 ("utf32", "utf32_estonian_ci", False), # 166 ("utf32", "utf32_spanish_ci", False), # 167 ("utf32", "utf32_swedish_ci", False), # 168 ("utf32", "utf32_turkish_ci", False), # 169 ("utf32", "utf32_czech_ci", False), # 170 ("utf32", "utf32_danish_ci", False), # 171 ("utf32", "utf32_lithuanian_ci", False), # 172 ("utf32", "utf32_slovak_ci", False), # 173 ("utf32", "utf32_spanish2_ci", False), # 174 ("utf32", "utf32_roman_ci", False), # 175 ("utf32", "utf32_persian_ci", False), # 176 ("utf32", "utf32_esperanto_ci", False), # 177 ("utf32", "utf32_hungarian_ci", False), # 178 ("utf32", "utf32_sinhala_ci", False), # 179 ("utf32", "utf32_german2_ci", False), # 180 ("utf32", "utf32_croatian_ci", False), # 181 ("utf32", "utf32_unicode_520_ci", False), # 182 ("utf32", "utf32_vietnamese_ci", False), # 183 None, None, None, None, None, None, None, None, ("utf8", "utf8_unicode_ci", False), # 192 ("utf8", "utf8_icelandic_ci", False), # 193 ("utf8", "utf8_latvian_ci", False), # 194 ("utf8", "utf8_romanian_ci", False), # 195 ("utf8", "utf8_slovenian_ci", False), # 196 ("utf8", "utf8_polish_ci", False), # 197 ("utf8", "utf8_estonian_ci", False), # 198 ("utf8", "utf8_spanish_ci", False), # 199 ("utf8", "utf8_swedish_ci", False), # 200 ("utf8", "utf8_turkish_ci", False), # 201 ("utf8", "utf8_czech_ci", False), # 202 ("utf8", "utf8_danish_ci", False), # 203 ("utf8", "utf8_lithuanian_ci", False), # 204 ("utf8", "utf8_slovak_ci", False), # 205 ("utf8", "utf8_spanish2_ci", False), # 206 ("utf8", "utf8_roman_ci", False), # 207 ("utf8", "utf8_persian_ci", False), # 208 ("utf8", "utf8_esperanto_ci", False), # 209 ("utf8", "utf8_hungarian_ci", False), # 210 ("utf8", "utf8_sinhala_ci", False), # 211 ("utf8", "utf8_german2_ci", False), # 212 ("utf8", "utf8_croatian_ci", False), # 213 ("utf8", "utf8_unicode_520_ci", False), # 214 ("utf8", "utf8_vietnamese_ci", False), # 215 None, None, None, None, None, None, None, ("utf8", "utf8_general_mysql500_ci", False), # 223 ("utf8mb4", "utf8mb4_unicode_ci", False), # 224 ("utf8mb4", "utf8mb4_icelandic_ci", False), # 225 ("utf8mb4", "utf8mb4_latvian_ci", False), # 226 ("utf8mb4", "utf8mb4_romanian_ci", False), # 227 ("utf8mb4", "utf8mb4_slovenian_ci", False), # 228 ("utf8mb4", "utf8mb4_polish_ci", False), # 229 ("utf8mb4", "utf8mb4_estonian_ci", False), # 230 ("utf8mb4", "utf8mb4_spanish_ci", False), # 231 ("utf8mb4", "utf8mb4_swedish_ci", False), # 232 ("utf8mb4", "utf8mb4_turkish_ci", False), # 233 ("utf8mb4", "utf8mb4_czech_ci", False), # 234 ("utf8mb4", "utf8mb4_danish_ci", False), # 235 ("utf8mb4", "utf8mb4_lithuanian_ci", False), # 236 ("utf8mb4", "utf8mb4_slovak_ci", False), # 237 ("utf8mb4", "utf8mb4_spanish2_ci", False), # 238 ("utf8mb4", "utf8mb4_roman_ci", False), # 239 ("utf8mb4", "utf8mb4_persian_ci", False), # 240 ("utf8mb4", "utf8mb4_esperanto_ci", False), # 241 ("utf8mb4", "utf8mb4_hungarian_ci", False), # 242 ("utf8mb4", "utf8mb4_sinhala_ci", False), # 243 ("utf8mb4", "utf8mb4_german2_ci", False), # 244 ("utf8mb4", "utf8mb4_croatian_ci", False), # 245 ("utf8mb4", "utf8mb4_unicode_520_ci", False), # 246 ("utf8mb4", "utf8mb4_vietnamese_ci", False), # 247 ] mysql-connector-python-1.1.6/python3/mysql/connector/constants.py0000644001577100000120000005471012276514013024602 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Various MySQL constants and character sets """ from mysql.connector.errors import ProgrammingError from mysql.connector.charsets import MYSQL_CHARACTER_SETS MAX_PACKET_LENGTH = 16777215 NET_BUFFER_LENGTH = 8192 def flag_is_set(flag, flags): """Checks if the flag is set Returns boolean""" if (flags & flag) > 0: return True return False class _Constants(object): """ Base class for constants """ prefix = '' desc = {} def __new__(cls): raise TypeError("Can not instanciate from %s" % cls.__name__) @classmethod def get_desc(cls, name): """Get description of given constant""" try: return cls.desc[name][1] except: return None @classmethod def get_info(cls, num): """Get information about given constant""" for name, info in cls.desc.items(): if info[0] == num: return name return None @classmethod def get_full_info(cls): """get full information about given constant""" res = () try: res = ["%s : %s" % (k, v[1]) for k, v in cls.desc.items()] except Exception as err: # pylint: disable=W0703 res = ('No information found in constant class.%s' % err) return res class _Flags(_Constants): """Base class for classes describing flags """ @classmethod def get_bit_info(cls, value): """Get the name of all bits set Returns a list of strings.""" res = [] for name, info in cls.desc.items(): if value & info[0]: res.append(name) return res class FieldType(_Constants): """MySQL Field Types """ prefix = 'FIELD_TYPE_' DECIMAL = 0x00 TINY = 0x01 SHORT = 0x02 LONG = 0x03 FLOAT = 0x04 DOUBLE = 0x05 NULL = 0x06 TIMESTAMP = 0x07 LONGLONG = 0x08 INT24 = 0x09 DATE = 0x0a TIME = 0x0b DATETIME = 0x0c YEAR = 0x0d NEWDATE = 0x0e VARCHAR = 0x0f BIT = 0x10 NEWDECIMAL = 0xf6 ENUM = 0xf7 SET = 0xf8 TINY_BLOB = 0xf9 MEDIUM_BLOB = 0xfa LONG_BLOB = 0xfb BLOB = 0xfc VAR_STRING = 0xfd STRING = 0xfe GEOMETRY = 0xff desc = { 'DECIMAL': (0x00, 'DECIMAL'), 'TINY': (0x01, 'TINY'), 'SHORT': (0x02, 'SHORT'), 'LONG': (0x03, 'LONG'), 'FLOAT': (0x04, 'FLOAT'), 'DOUBLE': (0x05, 'DOUBLE'), 'NULL': (0x06, 'NULL'), 'TIMESTAMP': (0x07, 'TIMESTAMP'), 'LONGLONG': (0x08, 'LONGLONG'), 'INT24': (0x09, 'INT24'), 'DATE': (0x0a, 'DATE'), 'TIME': (0x0b, 'TIME'), 'DATETIME': (0x0c, 'DATETIME'), 'YEAR': (0x0d, 'YEAR'), 'NEWDATE': (0x0e, 'NEWDATE'), 'VARCHAR': (0x0f, 'VARCHAR'), 'BIT': (0x10, 'BIT'), 'NEWDECIMAL': (0xf6, 'NEWDECIMAL'), 'ENUM': (0xf7, 'ENUM'), 'SET': (0xf8, 'SET'), 'TINY_BLOB': (0xf9, 'TINY_BLOB'), 'MEDIUM_BLOB': (0xfa, 'MEDIUM_BLOB'), 'LONG_BLOB': (0xfb, 'LONG_BLOB'), 'BLOB': (0xfc, 'BLOB'), 'VAR_STRING': (0xfd, 'VAR_STRING'), 'STRING': (0xfe, 'STRING'), 'GEOMETRY': (0xff, 'GEOMETRY'), } @classmethod def get_string_types(cls): """Get the list of all string types""" return [ cls.VARCHAR, cls.ENUM, cls.VAR_STRING, cls.STRING, ] @classmethod def get_binary_types(cls): """Get the list of all binary types""" return [ cls.TINY_BLOB, cls.MEDIUM_BLOB, cls.LONG_BLOB, cls.BLOB, ] @classmethod def get_number_types(cls): """Get the list of all number types""" return [ cls.DECIMAL, cls.NEWDECIMAL, cls.TINY, cls.SHORT, cls.LONG, cls.FLOAT, cls.DOUBLE, cls.LONGLONG, cls.INT24, cls.BIT, cls.YEAR, ] @classmethod def get_timestamp_types(cls): """Get the list of all timestamp types""" return [ cls.DATETIME, cls.TIMESTAMP, ] class FieldFlag(_Flags): """MySQL Field Flags Field flags as found in MySQL sources mysql-src/include/mysql_com.h """ _prefix = '' NOT_NULL = 1 << 0 PRI_KEY = 1 << 1 UNIQUE_KEY = 1 << 2 MULTIPLE_KEY = 1 << 3 BLOB = 1 << 4 UNSIGNED = 1 << 5 ZEROFILL = 1 << 6 BINARY = 1 << 7 ENUM = 1 << 8 AUTO_INCREMENT = 1 << 9 TIMESTAMP = 1 << 10 SET = 1 << 11 NO_DEFAULT_VALUE = 1 << 12 ON_UPDATE_NOW = 1 << 13 NUM = 1 << 14 PART_KEY = 1 << 15 GROUP = 1 << 14 # SAME AS NUM !!!!!!!???? UNIQUE = 1 << 16 BINCMP = 1 << 17 GET_FIXED_FIELDS = 1 << 18 FIELD_IN_PART_FUNC = 1 << 19 FIELD_IN_ADD_INDEX = 1 << 20 FIELD_IS_RENAMED = 1 << 21 desc = { 'NOT_NULL': (1 << 0, "Field can't be NULL"), 'PRI_KEY': (1 << 1, "Field is part of a primary key"), 'UNIQUE_KEY': (1 << 2, "Field is part of a unique key"), 'MULTIPLE_KEY': (1 << 3, "Field is part of a key"), 'BLOB': (1 << 4, "Field is a blob"), 'UNSIGNED': (1 << 5, "Field is unsigned"), 'ZEROFILL': (1 << 6, "Field is zerofill"), 'BINARY': (1 << 7, "Field is binary "), 'ENUM': (1 << 8, "field is an enum"), 'AUTO_INCREMENT': (1 << 9, "field is a autoincrement field"), 'TIMESTAMP': (1 << 10, "Field is a timestamp"), 'SET': (1 << 11, "field is a set"), 'NO_DEFAULT_VALUE': (1 << 12, "Field doesn't have default value"), 'ON_UPDATE_NOW': (1 << 13, "Field is set to NOW on UPDATE"), 'NUM': (1 << 14, "Field is num (for clients)"), 'PART_KEY': (1 << 15, "Intern; Part of some key"), 'GROUP': (1 << 14, "Intern: Group field"), # Same as NUM 'UNIQUE': (1 << 16, "Intern: Used by sql_yacc"), 'BINCMP': (1 << 17, "Intern: Used by sql_yacc"), 'GET_FIXED_FIELDS': (1 << 18, "Used to get fields in item tree"), 'FIELD_IN_PART_FUNC': (1 << 19, "Field part of partition func"), 'FIELD_IN_ADD_INDEX': (1 << 20, "Intern: Field used in ADD INDEX"), 'FIELD_IS_RENAMED': (1 << 21, "Intern: Field is being renamed"), } class ServerCmd(_Constants): """MySQL Server Commands """ _prefix = 'COM_' SLEEP = 0 QUIT = 1 INIT_DB = 2 QUERY = 3 FIELD_LIST = 4 CREATE_DB = 5 DROP_DB = 6 REFRESH = 7 SHUTDOWN = 8 STATISTICS = 9 PROCESS_INFO = 10 CONNECT = 11 PROCESS_KILL = 12 DEBUG = 13 PING = 14 TIME = 15 DELAYED_INSERT = 16 CHANGE_USER = 17 BINLOG_DUMP = 18 TABLE_DUMP = 19 CONNECT_OUT = 20 REGISTER_SLAVE = 21 STMT_PREPARE = 22 STMT_EXECUTE = 23 STMT_SEND_LONG_DATA = 24 STMT_CLOSE = 25 STMT_RESET = 26 SET_OPTION = 27 STMT_FETCH = 28 DAEMON = 29 desc = { 'SLEEP': (0, 'SLEEP'), 'QUIT': (1, 'QUIT'), 'INIT_DB': (2, 'INIT_DB'), 'QUERY': (3, 'QUERY'), 'FIELD_LIST': (4, 'FIELD_LIST'), 'CREATE_DB': (5, 'CREATE_DB'), 'DROP_DB': (6, 'DROP_DB'), 'REFRESH': (7, 'REFRESH'), 'SHUTDOWN': (8, 'SHUTDOWN'), 'STATISTICS': (9, 'STATISTICS'), 'PROCESS_INFO': (10, 'PROCESS_INFO'), 'CONNECT': (11, 'CONNECT'), 'PROCESS_KILL': (12, 'PROCESS_KILL'), 'DEBUG': (13, 'DEBUG'), 'PING': (14, 'PING'), 'TIME': (15, 'TIME'), 'DELAYED_INSERT': (16, 'DELAYED_INSERT'), 'CHANGE_USER': (17, 'CHANGE_USER'), 'BINLOG_DUMP': (18, 'BINLOG_DUMP'), 'TABLE_DUMP': (19, 'TABLE_DUMP'), 'CONNECT_OUT': (20, 'CONNECT_OUT'), 'REGISTER_SLAVE': (21, 'REGISTER_SLAVE'), 'STMT_PREPARE': (22, 'STMT_PREPARE'), 'STMT_EXECUTE': (23, 'STMT_EXECUTE'), 'STMT_SEND_LONG_DATA': (24, 'STMT_SEND_LONG_DATA'), 'STMT_CLOSE': (25, 'STMT_CLOSE'), 'STMT_RESET': (26, 'STMT_RESET'), 'SET_OPTION': (27, 'SET_OPTION'), 'STMT_FETCH': (28, 'STMT_FETCH'), 'DAEMON': (29, 'DAEMON'), } class ClientFlag(_Flags): """MySQL Client Flags Client options as found in the MySQL sources mysql-src/include/mysql_com.h """ LONG_PASSWD = 1 << 0 FOUND_ROWS = 1 << 1 LONG_FLAG = 1 << 2 CONNECT_WITH_DB = 1 << 3 NO_SCHEMA = 1 << 4 COMPRESS = 1 << 5 ODBC = 1 << 6 LOCAL_FILES = 1 << 7 IGNORE_SPACE = 1 << 8 PROTOCOL_41 = 1 << 9 INTERACTIVE = 1 << 10 SSL = 1 << 11 IGNORE_SIGPIPE = 1 << 12 TRANSACTIONS = 1 << 13 RESERVED = 1 << 14 SECURE_CONNECTION = 1 << 15 MULTI_STATEMENTS = 1 << 16 MULTI_RESULTS = 1 << 17 SSL_VERIFY_SERVER_CERT = 1 << 30 REMEMBER_OPTIONS = 1 << 31 desc = { 'LONG_PASSWD': (1 << 0, 'New more secure passwords'), 'FOUND_ROWS': (1 << 1, 'Found instead of affected rows'), 'LONG_FLAG': (1 << 2, 'Get all column flags'), 'CONNECT_WITH_DB': (1 << 3, 'One can specify db on connect'), 'NO_SCHEMA': (1 << 4, "Don't allow database.table.column"), 'COMPRESS': (1 << 5, 'Can use compression protocol'), 'ODBC': (1 << 6, 'ODBC client'), 'LOCAL_FILES': (1 << 7, 'Can use LOAD DATA LOCAL'), 'IGNORE_SPACE': (1 << 8, "Ignore spaces before ''"), 'PROTOCOL_41': (1 << 9, 'New 4.1 protocol'), 'INTERACTIVE': (1 << 10, 'This is an interactive client'), 'SSL': (1 << 11, 'Switch to SSL after handshake'), 'IGNORE_SIGPIPE': (1 << 12, 'IGNORE sigpipes'), 'TRANSACTIONS': (1 << 13, 'Client knows about transactions'), 'RESERVED': (1 << 14, 'Old flag for 4.1 protocol'), 'SECURE_CONNECTION': (1 << 15, 'New 4.1 authentication'), 'MULTI_STATEMENTS': (1 << 16, 'Enable/disable multi-stmt support'), 'MULTI_RESULTS': (1 << 17, 'Enable/disable multi-results'), 'SSL_VERIFY_SERVER_CERT': (1 << 30, ''), 'REMEMBER_OPTIONS': (1 << 31, ''), } default = [ LONG_PASSWD, LONG_FLAG, CONNECT_WITH_DB, PROTOCOL_41, TRANSACTIONS, SECURE_CONNECTION, MULTI_STATEMENTS, MULTI_RESULTS, ] @classmethod def get_default(cls): """Get the default client options set Returns a flag with all the default client options set""" flags = 0 for option in cls.default: flags |= option return flags class ServerFlag(_Flags): """MySQL Server Flags Server flags as found in the MySQL sources mysql-src/include/mysql_com.h """ _prefix = 'SERVER_' STATUS_IN_TRANS = 1 << 0 STATUS_AUTOCOMMIT = 1 << 1 MORE_RESULTS_EXISTS = 1 << 3 QUERY_NO_GOOD_INDEX_USED = 1 << 4 QUERY_NO_INDEX_USED = 1 << 5 STATUS_CURSOR_EXISTS = 1 << 6 STATUS_LAST_ROW_SENT = 1 << 7 STATUS_DB_DROPPED = 1 << 8 STATUS_NO_BACKSLASH_ESCAPES = 1 << 9 desc = { 'SERVER_STATUS_IN_TRANS': (1 << 0, 'Transaction has started'), 'SERVER_STATUS_AUTOCOMMIT': (1 << 1, 'Server in auto_commit mode'), 'SERVER_MORE_RESULTS_EXISTS': (1 << 3, 'Multi query - ' 'next query exists'), 'SERVER_QUERY_NO_GOOD_INDEX_USED': (1 << 4, ''), 'SERVER_QUERY_NO_INDEX_USED': (1 << 5, ''), 'SERVER_STATUS_CURSOR_EXISTS': (1 << 6, ''), 'SERVER_STATUS_LAST_ROW_SENT': (1 << 7, ''), 'SERVER_STATUS_DB_DROPPED': (1 << 8, 'A database was dropped'), 'SERVER_STATUS_NO_BACKSLASH_ESCAPES': (1 << 9, ''), } class RefreshOption(_Constants): """MySQL Refresh command options Options used when sending the COM_REFRESH server command. """ _prefix = 'REFRESH_' GRANT = 1 << 0 LOG = 1 << 1 TABLES = 1 << 2 HOST = 1 << 3 STATUS = 1 << 4 THREADS = 1 << 5 SLAVE = 1 << 6 desc = { 'GRANT': (1 << 0, 'Refresh grant tables'), 'LOG': (1 << 1, 'Start on new log file'), 'TABLES': (1 << 2, 'close all tables'), 'HOSTS': (1 << 3, 'Flush host cache'), 'STATUS': (1 << 4, 'Flush status variables'), 'THREADS': (1 << 5, 'Flush thread cache'), 'SLAVE': (1 << 6, 'Reset master info and restart slave thread'), } class ShutdownType(_Constants): """MySQL Shutdown types Shutdown types used by the COM_SHUTDOWN server command. """ _prefix = '' SHUTDOWN_DEFAULT = b'\x00' SHUTDOWN_WAIT_CONNECTIONS = b'\x01' SHUTDOWN_WAIT_TRANSACTIONS = b'\x02' SHUTDOWN_WAIT_UPDATES = b'\x08' SHUTDOWN_WAIT_ALL_BUFFERS = b'\x10' SHUTDOWN_WAIT_CRITICAL_BUFFERS = b'\x11' KILL_QUERY = b'\xfe' KILL_CONNECTION = b'\xff' desc = { 'SHUTDOWN_DEFAULT': (SHUTDOWN_DEFAULT, "defaults to SHUTDOWN_WAIT_ALL_BUFFERS"), 'SHUTDOWN_WAIT_CONNECTIONS': (SHUTDOWN_WAIT_CONNECTIONS, "wait for existing connections to finish"), 'SHUTDOWN_WAIT_TRANSACTIONS': (SHUTDOWN_WAIT_TRANSACTIONS, "wait for existing trans to finish"), 'SHUTDOWN_WAIT_UPDATES': (SHUTDOWN_WAIT_UPDATES, "wait for existing updates to finish"), 'SHUTDOWN_WAIT_ALL_BUFFERS': (SHUTDOWN_WAIT_ALL_BUFFERS, "flush InnoDB and other storage engine buffers"), 'SHUTDOWN_WAIT_CRITICAL_BUFFERS': (SHUTDOWN_WAIT_CRITICAL_BUFFERS, "don't flush InnoDB buffers, " "flush other storage engines' buffers"), 'KILL_QUERY': (KILL_QUERY, "(no description)"), 'KILL_CONNECTION': (KILL_CONNECTION, "(no description)"), } class CharacterSet(_Constants): """MySQL supported character sets and collations List of character sets with their collations supported by MySQL. This maps to the character set we get from the server within the handshake packet. The list is hardcode so we avoid a database query when getting the name of the used character set or collation. """ desc = MYSQL_CHARACTER_SETS # Multi-byte character sets which use 5c (backslash) in characters slash_charsets = (1, 13, 28, 84, 87, 88) @classmethod def get_info(cls, setid): """Retrieves character set information as tuple using an ID Retrieves character set and collation information based on the given MySQL ID. Raises ProgrammingError when character set is not supported. Returns a tuple. """ try: return cls.desc[setid][0:2] except IndexError: raise ProgrammingError( "Character set '{0}' unsupported".format(setid)) @classmethod def get_desc(cls, setid): """Retrieves character set information as string using an ID Retrieves character set and collation information based on the given MySQL ID. Returns a tuple. """ try: return "%s/%s" % cls.get_info(setid) except: raise @classmethod def get_default_collation(cls, charset): """Retrieves the default collation for given character set Raises ProgrammingError when character set is not supported. Returns list (collation, charset, index) """ if isinstance(charset, int): try: info = cls.desc[charset] return info[1], info[0], charset except: ProgrammingError("Character set ID '%s' unsupported." % ( charset)) for cid, info in enumerate(cls.desc): if info is None: continue if info[0] == charset and info[2] is True: return info[1], info[0], cid raise ProgrammingError("Character set '%s' unsupported." % (charset)) @classmethod def get_charset_info(cls, charset=None, collation=None): """Get character set information using charset name and/or collation Retrieves character set and collation information given character set name and/or a collation name. If charset is an integer, it will look up the character set based on the MySQL's ID. For example: get_charset_info('utf8',None) get_charset_info(collation='utf8_general_ci') get_charset_info(47) Raises ProgrammingError when character set is not supported. Returns a tuple with (id, characterset name, collation) """ if isinstance(charset, int): try: info = cls.desc[charset] return (charset, info[0], info[1]) except IndexError: ProgrammingError("Character set ID {0} unknown.".format( charset)) if charset is not None and collation is None: info = cls.get_default_collation(charset) return (info[2], info[1], info[0]) elif charset is None and collation is not None: for cid, info in enumerate(cls.desc): if info is None: continue if collation == info[1]: return (cid, info[0], info[1]) raise ProgrammingError("Collation '{0}' unknown.".format(collation)) else: for cid, info in enumerate(cls.desc): if info is None: continue if info[0] == charset and info[1] == collation: return (cid, info[0], info[1]) raise ProgrammingError("Character set '{0}' unknown.".format( charset)) @classmethod def get_supported(cls): """Retrieves a list with names of all supproted character sets Returns a tuple. """ res = [] for info in cls.desc: if info and info[0] not in res: res.append(info[0]) return tuple(res) class SQLMode(_Constants): # pylint: disable=R0921 """MySQL SQL Modes The numeric values of SQL Modes are not interesting, only the names are used when setting the SQL_MODE system variable using the MySQL SET command. See http://dev.mysql.com/doc/refman/5.6/en/server-sql-mode.html """ _prefix = 'MODE_' REAL_AS_FLOAT = 'REAL_AS_FLOAT' PIPES_AS_CONCAT = 'PIPES_AS_CONCAT' ANSI_QUOTES = 'ANSI_QUOTES' IGNORE_SPACE = 'IGNORE_SPACE' NOT_USED = 'NOT_USED' ONLY_FULL_GROUP_BY = 'ONLY_FULL_GROUP_BY' NO_UNSIGNED_SUBTRACTION = 'NO_UNSIGNED_SUBTRACTION' NO_DIR_IN_CREATE = 'NO_DIR_IN_CREATE' POSTGRESQL = 'POSTGRESQL' ORACLE = 'ORACLE' MSSQL = 'MSSQL' DB2 = 'DB2' MAXDB = 'MAXDB' NO_KEY_OPTIONS = 'NO_KEY_OPTIONS' NO_TABLE_OPTIONS = 'NO_TABLE_OPTIONS' NO_FIELD_OPTIONS = 'NO_FIELD_OPTIONS' MYSQL323 = 'MYSQL323' MYSQL40 = 'MYSQL40' ANSI = 'ANSI' NO_AUTO_VALUE_ON_ZERO = 'NO_AUTO_VALUE_ON_ZERO' NO_BACKSLASH_ESCAPES = 'NO_BACKSLASH_ESCAPES' STRICT_TRANS_TABLES = 'STRICT_TRANS_TABLES' STRICT_ALL_TABLES = 'STRICT_ALL_TABLES' NO_ZERO_IN_DATE = 'NO_ZERO_IN_DATE' NO_ZERO_DATE = 'NO_ZERO_DATE' INVALID_DATES = 'INVALID_DATES' ERROR_FOR_DIVISION_BY_ZERO = 'ERROR_FOR_DIVISION_BY_ZERO' TRADITIONAL = 'TRADITIONAL' NO_AUTO_CREATE_USER = 'NO_AUTO_CREATE_USER' HIGH_NOT_PRECEDENCE = 'HIGH_NOT_PRECEDENCE' NO_ENGINE_SUBSTITUTION = 'NO_ENGINE_SUBSTITUTION' PAD_CHAR_TO_FULL_LENGTH = 'PAD_CHAR_TO_FULL_LENGTH' @classmethod def get_desc(cls, name): raise NotImplementedError @classmethod def get_info(cls, number): raise NotImplementedError @classmethod def get_full_info(cls): """Returns a sequence of all availble SQL Modes This class method returns a tuple containing all SQL Mode names. The names will be alphabetically sorted. Returns a tuple. """ res = [] for key in vars(cls).keys(): if (not key.startswith('_') and not hasattr(getattr(cls, key), '__call__')): res.append(key) return tuple(sorted(res)) mysql-connector-python-1.1.6/python3/mysql/connector/__init__.py0000644001577100000120000001120412276514013024314 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ MySQL Connector/Python - MySQL drive written in Python """ import threading from .connection import MySQLConnection from .errors import ( # pylint: disable=W0622 Error, Warning, InterfaceError, DatabaseError, NotSupportedError, DataError, IntegrityError, ProgrammingError, OperationalError, InternalError, custom_error_exception, PoolError) from .constants import FieldFlag, FieldType, CharacterSet, \ RefreshOption, ClientFlag from mysql.connector.dbapi import ( Date, Time, Timestamp, Binary, DateFromTicks, DateFromTicks, TimestampFromTicks, TimeFromTicks, STRING, BINARY, NUMBER, DATETIME, ROWID, apilevel, threadsafety, paramstyle) from mysql.connector.pooling import ( MySQLConnectionPool, generate_pool_name, CNX_POOL_ARGS, CONNECTION_POOL_LOCK) try: from mysql.connector import version except ImportError: # Development, try import from current directory try: import version except ImportError: raise ImportError("For development, make sure version.py is " "in current directory.") _CONNECTION_POOLS = {} def connect(*args, **kwargs): """Create or get a MySQL connection object In its simpliest form, Connect() will open a connection to a MySQL server and return a MySQLConnection object. When any connection pooling arguments are given, for example pool_name or pool_size, a pool is created or a previously one is used to return a PooledMySQLConnection. Returns MySQLConnection or PooledMySQLConnection. """ # Pooled connections if any([key in kwargs for key in CNX_POOL_ARGS]): # If no pool name specified, generate one try: pool_name = kwargs['pool_name'] except KeyError: pool_name = generate_pool_name(**kwargs) # Setup the pool, ensuring only 1 thread can update at a time with CONNECTION_POOL_LOCK: if pool_name not in _CONNECTION_POOLS: _CONNECTION_POOLS[pool_name] = MySQLConnectionPool( *args, **kwargs) elif isinstance(_CONNECTION_POOLS[pool_name], MySQLConnectionPool): # pool_size must be the same check_size = _CONNECTION_POOLS[pool_name].pool_size if ('pool_size' in kwargs and kwargs['pool_size'] != check_size): raise PoolError("Size can not be changed " "for active pools.") # Return pooled connection try: return _CONNECTION_POOLS[pool_name].get_connection() except AttributeError: raise InterfaceError( "Failed getting connection from pool '{0}'".format(pool_name)) # Regular connection return MySQLConnection(*args, **kwargs) Connect = connect # pylint: disable=C0103 __version_info__ = version.VERSION __version__ = version.VERSION_TEXT __all__ = [ 'MySQLConnection', 'Connect', 'custom_error_exception', # Some useful constants 'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption', # Error handling 'Error', 'Warning', 'InterfaceError', 'DatabaseError', 'NotSupportedError', 'DataError', 'IntegrityError', 'ProgrammingError', 'OperationalError', 'InternalError', # DBAPI PEP 249 required exports 'connect', 'apilevel', 'threadsafety', 'paramstyle', 'Date', 'Time', 'Timestamp', 'Binary', 'DateFromTicks', 'DateFromTicks', 'TimestampFromTicks', 'TimeFromTicks', 'STRING', 'BINARY', 'NUMBER', 'DATETIME', 'ROWID', ] mysql-connector-python-1.1.6/python3/mysql/connector/conversion.py0000644001577100000120000003721112276514013024750 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Converting MySQL and Python types """ import struct import datetime import time from decimal import Decimal from mysql.connector.constants import FieldType, FieldFlag, CharacterSet class HexLiteral(str): """Class holding MySQL hex literals""" def __new__(cls, str_, charset='utf8'): hexed = ["{0:x}".format(i) for i in str_.encode(charset)] obj = str.__new__(cls, ''.join(hexed)) obj.charset = charset obj.original = str_ return obj def __str__(self): return '0x' + self class MySQLConverterBase(object): """Base class for conversion classes All class dealing with converting to and from MySQL data types must be a subclass of this class. """ def __init__(self, charset='utf8', use_unicode=True): self.python_types = None self.mysql_types = None self.charset = None self.charset_id = 0 self.use_unicode = None self.set_charset(charset) self.set_unicode(use_unicode) def set_charset(self, charset): """Set character set""" if charset == 'utf8mb4': charset = 'utf8' if charset is not None: self.charset = charset else: # default to utf8 self.charset = 'utf8' self.charset_id = CharacterSet.get_charset_info(self.charset)[0] def set_unicode(self, value=True): """Set whether to use Unicode""" self.use_unicode = value def to_mysql(self, value): """Convert Python data type to MySQL""" return value def to_python(self, vtype, value): """Convert MySQL data type to Python""" return value def escape(self, buf): """Escape buffer for sending to MySQL""" return buf def quote(self, buf): """Quote buffer for sending to MySQL""" return str(buf) class MySQLConverter(MySQLConverterBase): """Default conversion class for MySQL Connector/Python. o escape method: for escaping values send to MySQL o quoting method: for quoting values send to MySQL in statements o conversion mapping: maps Python and MySQL data types to function for converting them. Whenever one needs to convert values differently, a converter_class argument can be given while instantiating a new connection like cnx.connect(converter_class=CustomMySQLConverterClass). """ def __init__(self, charset=None, use_unicode=True): MySQLConverterBase.__init__(self, charset, use_unicode) self._cache_field_types = {} def escape(self, value): """ Escapes special characters as they are expected to by when MySQL receives them. As found in MySQL source mysys/charset.c Returns the value if not a string, or the escaped string. """ if value is None: return value elif isinstance(value, (int, float, Decimal, HexLiteral)): return value if isinstance(value, bytes): value = value.replace(b'\\', b'\\\\') value = value.replace(b'\n', b'\\n') value = value.replace(b'\r', b'\\r') value = value.replace(b'\047', b'\134\047') # single quotes value = value.replace(b'\042', b'\134\042') # double quotes value = value.replace(b'\032', b'\134\032') # for Win32 else: value = value.replace('\\', '\\\\') value = value.replace('\n', '\\n') value = value.replace('\r', '\\r') value = value.replace('\047', '\134\047') # single quotes value = value.replace('\042', '\134\042') # double quotes value = value.replace('\032', '\134\032') # for Win32 return value def quote(self, buf): """ Quote the parameters for commands. General rules: o numbers are returns as bytes using ascii codec o None is returned as bytes('NULL') o Everything else is single quoted '' Returns a bytes object. """ if isinstance(buf, (int, float, Decimal, HexLiteral)): return str(buf).encode('ascii') elif isinstance(buf, type(None)): return b"NULL" else: return b"'" + buf + b"'" def to_mysql(self, value): """Convert Python data type to MySQL""" type_name = value.__class__.__name__.lower() return getattr(self, "_{}_to_mysql".format(type_name))(value) def _int_to_mysql(self, value): """Convert value to int""" return int(value) def _long_to_mysql(self, value): """Convert value to int""" return int(value) def _float_to_mysql(self, value): """Convert value to float""" return float(value) def _str_to_mysql(self, value): """Convert value to string""" encoded = value.encode(self.charset) if self.charset_id in CharacterSet.slash_charsets: if b'\x5c' in encoded: return HexLiteral(value, self.charset) return encoded def _bytes_to_mysql(self, value): """Convert value to bytes""" return value def _bool_to_mysql(self, value): """Convert value to boolean""" if value: return 1 else: return 0 def _nonetype_to_mysql(self, value): """ This would return what None would be in MySQL, but instead we leave it None and return it right away. The actual conversion from None to NULL happens in the quoting functionality. Return None. """ return None def _datetime_to_mysql(self, value): """ Converts a datetime instance to a string suitable for MySQL. The returned string has format: %Y-%m-%d %H:%M:%S[.%f] If the instance isn't a datetime.datetime type, it return None. Returns a bytes. """ if value.microsecond: return '{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:06d}'.format( value.year, value.month, value.day, value.hour, value.minute, value.second, value.microsecond).encode('ascii') return '{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}'.format( value.year, value.month, value.day, value.hour, value.minute, value.second).encode('ascii') def _date_to_mysql(self, value): """ Converts a date instance to a string suitable for MySQL. The returned string has format: %Y-%m-%d If the instance isn't a datetime.date type, it return None. Returns a bytes. """ return '{:d}-{:02d}-{:02d}'.format(value.year, value.month, value.day).encode('ascii') def _time_to_mysql(self, value): """ Converts a time instance to a string suitable for MySQL. The returned string has format: %H:%M:%S[.%f] If the instance isn't a datetime.time type, it return None. Returns a bytes. """ if value.microsecond: return value.strftime('%H:%M:%S.%f').encode('ascii') return value.strftime('%H:%M:%S').encode('ascii') def _struct_time_to_mysql(self, value): """ Converts a time.struct_time sequence to a string suitable for MySQL. The returned string has format: %Y-%m-%d %H:%M:%S Returns a bytes or None when not valid. """ return time.strftime('%Y-%m-%d %H:%M:%S', value).encode('ascii') def _timedelta_to_mysql(self, value): """ Converts a timedelta instance to a string suitable for MySQL. The returned string has format: %H:%M:%S Returns a bytes. """ (hours, remainder) = divmod(value.seconds, 3600) (mins, secs) = divmod(remainder, 60) hours = hours + (value.days * 24) if value.microseconds: return '{:02d}:{:02d}:{:02d}.{:06d}'.format( hours, mins, secs, value.microseconds).encode('ascii') return '{:02d}:{:02d}:{:02d}'.format( hours, mins, secs).encode('ascii') def _decimal_to_mysql(self, value): """ Converts a decimal.Decimal instance to a string suitable for MySQL. Returns a bytes or None when not valid. """ if isinstance(value, Decimal): return str(value).encode('ascii') return None def to_python(self, flddsc, value): """ Converts a given value coming from MySQL to a certain type in Python. The flddsc contains additional information for the field in the table. It's an element from MySQLCursor.description. Returns a mixed value. """ if value == 0 and flddsc[1] != FieldType.BIT: # \x00 # Don't go further when we hit a NULL value return None if value is None: return None if not self._cache_field_types: self._cache_field_types = {} for name, info in FieldType.desc.items(): try: self._cache_field_types[info[0]] = getattr( self, '_{0}_to_python'.format(name)) except AttributeError: # We ignore field types which has no method pass try: return self._cache_field_types[flddsc[1]](value, flddsc) except KeyError: # If one type is not defined, we just return the value as str return value.decode('utf-8') except ValueError as err: raise ValueError("%s (field %s)" % (err, flddsc[0])) except TypeError as err: raise TypeError("%s (field %s)" % (err, flddsc[0])) except: raise def _FLOAT_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as float type. """ return float(value) _DOUBLE_to_python = _FLOAT_to_python def _INT_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as int type. """ return int(value) _TINY_to_python = _INT_to_python _SHORT_to_python = _INT_to_python _INT24_to_python = _INT_to_python _LONG_to_python = _INT_to_python _LONGLONG_to_python = _INT_to_python def _DECIMAL_to_python(self, value, desc=None): # pylint: disable=C0103 """ Returns value as a decimal.Decimal. """ val = value.decode(self.charset) return Decimal(val) _NEWDECIMAL_to_python = _DECIMAL_to_python def _str(self, value, desc=None): """ Returns value as str type. """ return str(value) def _BIT_to_python(self, value, dsc=None): # pylint: disable=C0103 """Returns BIT columntype as integer""" int_val = value if len(int_val) < 8: int_val = b'\x00' * (8-len(int_val)) + int_val return struct.unpack('>Q', int_val)[0] def _DATE_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns DATE column type as datetime.date type. """ try: parts = value.split(b'-') return datetime.date(int(parts[0]), int(parts[1]), int(parts[2])) except ValueError: return None _NEWDATE_to_python = _DATE_to_python def _TIME_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns TIME column type as datetime.time type. """ time_val = None try: (hms, mcs) = value.split(b'.') mcs = int(mcs.ljust(6, b'0')) except ValueError: hms = value mcs = 0 try: (hrs, mins, sec) = [int(i) for i in hms.split(b':')] time_val = datetime.timedelta(hours=hrs, minutes=mins, seconds=sec, microseconds=mcs) except ValueError: raise ValueError( "Could not convert {} to python datetime.timedelta".format( value)) else: return time_val def _DATETIME_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Returns DATETIME column type as datetime.datetime type. """ datetime_val = None try: (date_, time_) = value.split(b' ') if len(time_) > 8: (hms, mcs) = time_.split(b'.') mcs = int(mcs.ljust(6, b'0')) else: hms = time_ mcs = 0 dtval = [int(i) for i in date_.split(b'-')] +\ [int(i) for i in hms.split(b':')] + [mcs,] datetime_val = datetime.datetime(*dtval) except ValueError: datetime_val = None return datetime_val _TIMESTAMP_to_python = _DATETIME_to_python def _YEAR_to_python(self, value, desc=None): # pylint: disable=C0103 """Returns YEAR column type as integer""" try: year = int(value) except ValueError: raise ValueError("Failed converting YEAR to int (%s)" % value) return year def _SET_to_python(self, value, dsc=None): # pylint: disable=C0103 """Returns SET column typs as set Actually, MySQL protocol sees a SET as a string type field. So this code isn't called directly, but used by STRING_to_python() method. Returns SET column type as a set. """ set_type = None val = value.decode(self.charset) try: set_type = set(val.split(',')) except ValueError: raise ValueError("Could not convert set %s to a sequence." % value) return set_type def _STRING_to_python(self, value, dsc=None): # pylint: disable=C0103 """ Note that a SET is a string too, but using the FieldFlag we can see whether we have to split it. Returns string typed columns as string type. """ if dsc is not None: # Check if we deal with a SET if dsc[7] & FieldFlag.SET: return self._SET_to_python(value, dsc) if dsc[7] & FieldFlag.BINARY: return value if isinstance(value, bytes) and self.use_unicode: return value.decode(self.charset) return value _VAR_STRING_to_python = _STRING_to_python def _BLOB_to_python(self, value, dsc=None): # pylint: disable=C0103 """Convert BLOB data type to Python""" if dsc is not None: if dsc[7] & FieldFlag.BINARY: return bytes(value) return self._STRING_to_python(value, dsc) _LONG_BLOB_to_python = _BLOB_to_python _MEDIUM_BLOB_to_python = _BLOB_to_python _TINY_BLOB_to_python = _BLOB_to_python mysql-connector-python-1.1.6/python3/mysql/connector/cursor.py0000644001577100000120000011004412276514013024074 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Cursor classes """ import weakref import re from mysql.connector import errors SQL_COMMENT = r"\/\*.*?\*\/" RE_SQL_COMMENT = re.compile( r'''({0})|(["'`][^"'`]*?({0})[^"'`]*?["'`])'''.format(SQL_COMMENT), re.I | re.M | re.S) RE_SQL_ON_DUPLICATE = re.compile( r'''\s*ON\s+DUPLICATE\s+KEY(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$''', re.I | re.M | re.S) RE_SQL_INSERT_STMT = re.compile( r"({0}|\s)*INSERT({0}|\s)*INTO.+VALUES.*".format(SQL_COMMENT), re.I | re.M | re.S) RE_SQL_INSERT_VALUES = re.compile(r'.*VALUES\s*(\(.*\)).*', re.I | re.M | re.S) RE_PY_PARAM = re.compile(b'(%s)') RE_SQL_SPLIT_STMTS = re.compile( b''';(?=(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$)''') RE_SQL_FIND_PARAM = re.compile( b'''%s(?=(?:[^"'`]*["'`][^"'`]*["'`])*[^"'`]*$)''') class _ParamSubstitutor(object): """ Substitutes parameters into SQL statement. """ def __init__(self, params): self.params = params self.index = 0 def __call__(self, matchobj): index = self.index self.index += 1 try: return self.params[index] except IndexError: raise errors.ProgrammingError( "Not enough parameters for the SQL statement") @property def remaining(self): """Returns number of parameters remaining to be substituted""" return len(self.params) - self.index class CursorBase(object): """ Base for defining MySQLCursor. This class is a skeleton and defines methods and members as required for the Python Database API Specification v2.0. It's better to inherite from MySQLCursor. """ def __init__(self): self._description = None self._rowcount = -1 self._last_insert_id = None self.arraysize = 1 def callproc(self, procname, args=()): """Calls a stored procedue with the given arguments The arguments will be set during this session, meaning they will be called like ___arg where is an enumeration (+1) of the arguments. Coding Example: 1) Definining the Stored Routine in MySQL: CREATE PROCEDURE multiply(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) BEGIN SET pProd := pFac1 * pFac2; END 2) Executing in Python: args = (5,5,0) # 0 is to hold pprod cursor.callproc('multiply', args) print(cursor.fetchone()) Does not return a value, but a result set will be available when the CALL-statement execute successfully. Raises exceptions when something is wrong. """ pass def close(self): """Close the cursor.""" pass def execute(self, operation, params=(), multi=False): """Executes the given operation Executes the given operation substituting any markers with the given parameters. For example, getting all rows where id is 5: cursor.execute("SELECT * FROM t1 WHERE id = %s", (5,)) The multi argument should be set to True when executing multiple statements in one operation. If not set and multiple results are found, an InterfaceError will be raised. If warnings where generated, and connection.get_warnings is True, then self._warnings will be a list containing these warnings. Returns an iterator when multi is True, otherwise None. """ pass def executemany(self, operation, seqparams): """Execute the given operation multiple times The executemany() method will execute the operation iterating over the list of parameters in seq_params. Example: Inserting 3 new employees and their phone number data = [ ('Jane','555-001'), ('Joe', '555-001'), ('John', '555-003') ] stmt = "INSERT INTO employees (name, phone) VALUES ('%s','%s')" cursor.executemany(stmt, data) INSERT statements are optimized by batching the data, that is using the MySQL multiple rows syntax. Results are discarded. If they are needed, consider looping over data using the execute() method. """ pass def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ pass def fetchmany(self, size=1): """Returns the next set of rows of a query result, returning a list of tuples. When no more rows are available, it returns an empty list. The number of rows returned can be specified using the size argument, which defaults to one """ pass def fetchall(self): """Returns all rows of a query result set Returns a list of tuples. """ pass def nextset(self): """Not Implemented.""" pass def setinputsizes(self, sizes): """Not Implemented.""" pass def setoutputsize(self, size, column=None): """Not Implemented.""" pass def reset(self): """Reset the cursor to default""" pass @property def description(self): """Returns description of columns in a result This property returns a list of tuples describing the columns in in a result set. A tuple is described as follows:: (column_name, type, None, None, None, None, null_ok, column_flags) # Addition to PEP-249 specs Returns a list of tuples. """ return self._description @property def rowcount(self): """Returns the number of rows produced or affected This property returns the number of rows produced by queries such as a SELECT, or affected rows when executing DML statements like INSERT or UPDATE. Note that for non-buffered cursors it is impossible to know the number of rows produced before having fetched them all. For those, the number of rows will be -1 right after execution, and incremented when fetching rows. Returns an integer. """ return self._rowcount @property def lastrowid(self): """Returns the value generated for an AUTO_INCREMENT column Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement or None when there is no such value available. Returns a long value or None. """ return self._last_insert_id class MySQLCursor(CursorBase): """Default cursor for interacting with MySQL This cursor will execute statements and handle the result. It will not automatically fetch all rows. MySQLCursor should be inherited whenever other functionallity is required. An example would to change the fetch* member functions to return dictionaries instead of lists of values. Implements the Python Database API Specification v2.0 (PEP-249) """ def __init__(self, connection=None): CursorBase.__init__(self) self._connection = None self._stored_results = [] self._nextrow = (None, None) self._warnings = None self._warning_count = 0 self._executed = None self._executed_list = [] self._binary = False if connection is not None: self._set_connection(connection) def __iter__(self): """ Iteration over the result set which calls self.fetchone() and returns the next row. """ return iter(self.fetchone, None) def _set_connection(self, connection): """Set the connection""" try: self._connection = weakref.proxy(connection) self._connection._protocol # pylint: disable=W0212,W0104 except (AttributeError, TypeError): raise errors.InterfaceError(errno=2048) def _reset_result(self): """Reset the cursor to default""" self._rowcount = -1 self._nextrow = (None, None) self._stored_results = [] self._warnings = None self._warning_count = 0 self._description = None self._executed = None self._executed_list = [] self.reset() def _have_unread_result(self): """Check whether there is an unread result""" try: return self._connection.unread_result except AttributeError: return False def next(self): """Used for iterating over the result set.""" return self.__next__() def __next__(self): """ Used for iterating over the result set. Calles self.fetchone() to get the next row. """ try: row = self.fetchone() except errors.InterfaceError: raise StopIteration if not row: raise StopIteration return row def close(self): """Close the cursor Returns True when successful, otherwise False. """ if self._connection is None: return False if self._have_unread_result(): raise errors.InternalError("Unread result found.") self._reset_result() self._connection = None return True def _process_params_dict(self, params): """Process query parameters given as dictionary""" try: to_mysql = self._connection.converter.to_mysql escape = self._connection.converter.escape quote = self._connection.converter.quote res = {} for key, value in list(params.items()): conv = value conv = to_mysql(conv) conv = escape(conv) conv = quote(conv) res["%({})s".format(key).encode()] = conv except Exception as err: raise errors.ProgrammingError( "Failed processing pyformat-parameters; %s" % err) else: return res return None def _process_params(self, params): """Process query parameters.""" try: res = params to_mysql = self._connection.converter.to_mysql escape = self._connection.converter.escape quote = self._connection.converter.quote res = [to_mysql(i) for i in res] res = [escape(i) for i in res] res = [quote(i) for i in res] except Exception as err: raise errors.ProgrammingError( "Failed processing format-parameters; %s" % err) else: return tuple(res) return None def _row_to_python(self, rowdata, desc=None): """Convert the row from MySQL to Python types""" res = [] to_python = self._connection.converter.to_python try: if not desc: desc = self.description for flddsc, val in zip(desc, rowdata): res.append(to_python(flddsc, val),) except Exception as err: raise errors.InterfaceError( "Failed converting row to Python types; %s" % err) else: return tuple(res) return None def _handle_noresultset(self, res): """Handles result of execute() when there is no result set """ try: self._rowcount = res['affected_rows'] self._last_insert_id = res['insert_id'] self._warning_count = res['warning_count'] except (KeyError, TypeError) as err: raise errors.ProgrammingError( "Failed handling non-resultset; {}".format(err)) if self._connection.get_warnings is True and self._warning_count: self._warnings = self._fetch_warnings() def _handle_resultset(self): """Handles result set This method handles the result set and is called after reading and storing column information in _handle_result(). For non-buffering cursors, this method is usually doing nothing. """ pass def _handle_result(self, result): """ Handle the result after a command was send. The result can be either an OK-packet or a dictionary containing column/eof information. Raises InterfaceError when result is not a dict() or result is invalid. """ if not isinstance(result, dict): raise errors.InterfaceError('Result was not a dict()') if 'columns' in result: # Weak test, must be column/eof information self._description = result['columns'] self._connection.unread_result = True self._handle_resultset() elif 'affected_rows' in result: # Weak test, must be an OK-packet self._connection.unread_result = False self._handle_noresultset(result) else: raise errors.InterfaceError('Invalid result') def _execute_iter(self, query_iter): """Generator returns MySQLCursor objects for multiple statements This method is only used when multiple statements are executed by the execute() method. It uses zip() to make an iterator from the given query_iter (result of MySQLConnection.cmd_query_iter()) and the list of statements that were executed. """ if not self._executed_list: self._executed_list = RE_SQL_SPLIT_STMTS.split(self._executed) for result, stmt in zip(query_iter, iter(self._executed_list)): self._reset_result() self._handle_result(result) self._executed = stmt yield self def execute(self, operation, params=None, multi=False): """Executes the given operation Executes the given operation substituting any markers with the given parameters. For example, getting all rows where id is 5: cursor.execute("SELECT * FROM t1 WHERE id = %s", (5,)) The multi argument should be set to True when executing multiple statements in one operation. If not set and multiple results are found, an InterfaceError will be raised. If warnings where generated, and connection.get_warnings is True, then self._warnings will be a list containing these warnings. Returns an iterator when multi is True, otherwise None. """ if not operation: return if self._connection.unread_result is True: raise errors.InternalError("Unread result found.") self._reset_result() stmt = '' try: if not isinstance(operation, bytes): stmt = operation.encode(self._connection.python_charset) else: stmt = operation except (UnicodeDecodeError, UnicodeEncodeError) as err: raise errors.ProgrammingError(str(err)) if params is not None: if isinstance(params, dict): for key, value in self._process_params_dict(params).items(): stmt = stmt.replace(key, value, 1) elif isinstance(params, (list, tuple)): psub = _ParamSubstitutor(self._process_params(params)) stmt = RE_PY_PARAM.sub(psub, stmt) if psub.remaining != 0: raise errors.ProgrammingError( "Not all parameters were used in the SQL statement") if multi: self._executed = stmt self._executed_list = [] return self._execute_iter(self._connection.cmd_query_iter(stmt)) else: self._executed = stmt try: self._handle_result(self._connection.cmd_query(stmt)) except errors.InterfaceError: if self._connection._have_next_result: # pylint: disable=W0212 raise errors.InterfaceError( "Use multi=True when executing multiple statements") raise return None def _batch_insert(self, operation, seq_params): """Implements multi row insert""" def remove_comments(match): """Remove comments from INSERT statements. This function is used while removing comments from INSERT statements. If the matched string is a comment not enclosed by quotes, it returns an empty string, else the string itself. """ if match.group(1): return "" else: return match.group(2) tmp = re.sub(RE_SQL_ON_DUPLICATE, '', re.sub(RE_SQL_COMMENT, remove_comments, operation)) matches = re.search(RE_SQL_INSERT_VALUES, tmp) if not matches: raise errors.InterfaceError( "Failed rewriting statement for multi-row INSERT. " "Check SQL syntax." ) fmt = matches.group(1).encode(self._connection.charset) values = [] try: stmt = operation.encode(self._connection.charset) for params in seq_params: tmp = fmt if isinstance(params, dict): for key, value in self._process_params_dict(params).items(): tmp = tmp.replace(key, value, 1) else: psub = _ParamSubstitutor(self._process_params(params)) tmp = RE_PY_PARAM.sub(psub, tmp) if psub.remaining != 0: raise errors.ProgrammingError("Not all parameters " "were used in the SQL statement") #for p in self._process_params(params): # tmp = tmp.replace(b'%s',p,1) values.append(tmp) if fmt in stmt: stmt = stmt.replace(fmt, b','.join(values), 1) return stmt else: return None except (UnicodeDecodeError, UnicodeEncodeError) as err: raise errors.ProgrammingError(str(err)) except errors.Error: raise except Exception as err: raise errors.InterfaceError( "Failed executing the operation; %s" % err) else: self._executed = stmt return self._rowcount def executemany(self, operation, seq_params): """Execute the given operation multiple times The executemany() method will execute the operation iterating over the list of parameters in seq_params. Example: Inserting 3 new employees and their phone number data = [ ('Jane','555-001'), ('Joe', '555-001'), ('John', '555-003') ] stmt = "INSERT INTO employees (name, phone) VALUES ('%s','%s)" cursor.executemany(stmt, data) INSERT statements are optimized by batching the data, that is using the MySQL multiple rows syntax. Results are discarded. If they are needed, consider looping over data using the execute() method. """ if not operation: return if self._connection.unread_result is True: raise errors.InternalError("Unread result found.") if not isinstance(seq_params, (list, tuple)): raise errors.ProgrammingError( "Parameters for query must be list or tuple.") # Optimize INSERTs by batching them if re.match(RE_SQL_INSERT_STMT, operation): if not seq_params: self._rowcount = 0 return stmt = self._batch_insert(operation, seq_params) if stmt is not None: return self.execute(stmt) rowcnt = 0 try: for params in seq_params: self.execute(operation, params) if self.with_rows and self._have_unread_result(): self.fetchall() rowcnt += self._rowcount except (ValueError, TypeError) as err: raise errors.InterfaceError( "Failed executing the operation; {}".format(err)) except: # Raise whatever execute() raises raise self._rowcount = rowcnt def stored_results(self): """Returns an iterator for stored results This method returns an iterator over results which are stored when callproc() is called. The iterator will provide MySQLCursorBuffered instances. Returns a iterator. """ return iter(self._stored_results) def callproc(self, procname, args=()): """Calls a stored procedure with the given arguments The arguments will be set during this session, meaning they will be called like ___arg where is an enumeration (+1) of the arguments. Coding Example: 1) Defining the Stored Routine in MySQL: CREATE PROCEDURE multiply(IN pFac1 INT, IN pFac2 INT, OUT pProd INT) BEGIN SET pProd := pFac1 * pFac2; END 2) Executing in Python: args = (5,5,0) # 0 is to hold pprod cursor.callproc('multiply', args) print(cursor.fetchone()) Does not return a value, but a result set will be available when the CALL-statement execute successfully. Raises exceptions when something is wrong. """ if not procname or not isinstance(procname, str): raise ValueError("procname must be a string") if not isinstance(args, (tuple, list)): raise ValueError("args must be a sequence") argfmt = "@_{name}_arg{index}" self._stored_results = [] results = [] try: argnames = [] if args: for idx, arg in enumerate(args): argname = argfmt.format(name=procname, index=idx + 1) argnames.append(argname) self.execute("SET {0}=%s".format(argname), (arg,)) call = "CALL {0}({1})".format(procname, ','.join(argnames)) for result in self._connection.cmd_query_iter(call): if 'columns' in result: # pylint: disable=W0212 tmp = MySQLCursorBuffered(self._connection._get_self()) tmp._handle_result(result) results.append(tmp) # pylint: enable=W0212 if argnames: select = "SELECT {0}".format(','.join(argnames)) self.execute(select) self._stored_results = results return self.fetchone() else: self._stored_results = results return () except errors.Error: raise except Exception as err: raise errors.InterfaceError( "Failed calling stored routine; {0}".format(err)) def getlastrowid(self): """Returns the value generated for an AUTO_INCREMENT column Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement. Returns a long value or None. """ return self._last_insert_id def _fetch_warnings(self): """ Fetch warnings doing a SHOW WARNINGS. Can be called after getting the result. Returns a result set or None when there were no warnings. """ res = [] try: cur = self._connection.cursor() cur.execute("SHOW WARNINGS") res = cur.fetchall() cur.close() except Exception as err: raise errors.InterfaceError( "Failed getting warnings; %s" % err) if self._connection.raise_on_warnings is True: raise errors.get_mysql_exception(res[0][1], res[0][2]) else: if len(res): return res return None def _handle_eof(self, eof): """Handle EOF packet""" self._connection.unread_result = False self._nextrow = (None, None) self._warning_count = eof['warning_count'] if self._connection.get_warnings is True and eof['warning_count']: self._warnings = self._fetch_warnings() def _fetch_row(self): """Returns the next row in the result set Returns a tuple or None. """ if not self._have_unread_result(): return None row = None if self._nextrow == (None, None): (row, eof) = self._connection.get_row( binary=self._binary, columns=self.description) else: (row, eof) = self._nextrow if row: self._nextrow = self._connection.get_row( binary=self._binary, columns=self.description) eof = self._nextrow[1] if eof is not None: self._handle_eof(eof) if self._rowcount == -1: self._rowcount = 1 else: self._rowcount += 1 if eof: self._handle_eof(eof) return row def fetchwarnings(self): """Returns Warnings.""" return self._warnings def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ row = self._fetch_row() if row: return self._row_to_python(row) return None def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0 and self._have_unread_result(): cnt -= 1 row = self.fetchone() if row: res.append(row) return res def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows() if self._nextrow[0]: rows.insert(0, self._nextrow[0]) res = [self._row_to_python(row) for row in rows] self._handle_eof(eof) rowcount = len(rows) if rowcount >= 0 and self._rowcount == -1: self._rowcount = 0 self._rowcount += rowcount return res @property def column_names(self): """Returns column names This property returns the columns names as a tuple. Returns a tuple. """ if not self.description: return () return tuple([d[0] for d in self.description]) @property def statement(self): """Returns the executed statement This property returns the executed statement. When multiple statements were executed, the current statement in the iterator will be returned. """ try: return self._executed.strip().decode('utf8') except AttributeError: return self._executed.strip() @property def with_rows(self): """Returns whether the cursor could have rows returned This property returns True when column descriptions are available and possibly also rows, which will need to be fetched. Returns True or False. """ if not self.description: return False return True def __str__(self): fmt = "MySQLCursor: %s" if self._executed: executed = bytes(self._executed).decode('utf-8') if len(executed) > 30: res = fmt % (executed[:30] + '..') else: res = fmt % (executed) else: res = fmt % '(Nothing executed yet)' return res class MySQLCursorBuffered(MySQLCursor): """Cursor which fetches rows within execute()""" def __init__(self, connection=None): MySQLCursor.__init__(self, connection) self._rows = None self._next_row = 0 def _handle_resultset(self): (self._rows, eof) = self._connection.get_rows() self._rowcount = len(self._rows) self._handle_eof(eof) self._next_row = 0 try: self._connection.unread_result = False except: pass def reset(self): self._rows = None def _fetch_row(self): row = None try: row = self._rows[self._next_row] except: return None else: self._next_row += 1 return row return None def fetchall(self): if self._rows is None: raise errors.InterfaceError("No result set to fetch from.") res = [] for row in self._rows[self._next_row:]: res.append(self._row_to_python(row)) self._next_row = len(self._rows) return res def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0: cnt -= 1 row = self.fetchone() if row: res.append(row) return res @property def with_rows(self): return self._rows is not None class MySQLCursorRaw(MySQLCursor): """ Skips conversion from MySQL datatypes to Python types when fetching rows. """ def fetchone(self): row = self._fetch_row() if row: return row return None def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows() if self._nextrow[0]: rows.insert(0, self._nextrow[0]) self._handle_eof(eof) rowcount = len(rows) if rowcount >= 0 and self._rowcount == -1: self._rowcount = 0 self._rowcount += rowcount return rows class MySQLCursorBufferedRaw(MySQLCursorBuffered): """ Cursor which skips conversion from MySQL datatypes to Python types when fetching rows and fetches rows within execute(). """ def fetchone(self): row = self._fetch_row() if row: return row return None def fetchall(self): if self._rows is None: raise errors.InterfaceError("No result set to fetch from.") return [r for r in self._rows[self._next_row:]] @property def with_rows(self): return self._rows is not None class MySQLCursorPrepared(MySQLCursor): """Cursor using MySQL Prepared Statements """ def __init__(self, connection=None): super(MySQLCursorPrepared, self).__init__(connection) self._rows = None self._next_row = 0 self._prepared = None self._binary = True self._have_result = None def callproc(self, *args, **kwargs): """Calls a stored procedue Not supported with MySQLCursorPrepared. """ raise errors.NotSupportedError() def close(self): """Close the cursor This method will try to deallocate the prepared statement and close the cursor. """ if self._prepared: try: self._connection.cmd_stmt_close(self._prepared['statement_id']) except errors.Error: # We tried to deallocate, but it's OK when we fail. pass self._prepared = None super(MySQLCursorPrepared, self).close() def _row_to_python(self, rowdata, desc=None): """Convert row data from MySQL to Python types The conversion is done while reading binary data in the protocol module. """ pass def _handle_result(self, res): """Handle result after execution""" if isinstance(res, dict): self._connection.unread_result = False self._have_result = False self._handle_noresultset(res) else: self._description = res[1] self._connection.unread_result = True self._have_result = True def execute(self, operation, params=(), multi=False): # multi is unused """Prepare and execute a MySQL Prepared Statement This method will preare the given operation and execute it using the optionally given parameters. If the cursor instance already had a prepared statement, it is first closed. """ if operation is not self._executed: if self._prepared: self._connection.cmd_stmt_close(self._prepared['statement_id']) self._executed = operation try: if not isinstance(operation, bytes): operation = operation.encode(self._connection.charset) except (UnicodeDecodeError, UnicodeEncodeError) as err: raise errors.ProgrammingError(str(err)) # need to convert %s to ? before sending it to MySQL if b'%s' in operation: operation = re.sub(RE_SQL_FIND_PARAM, b'?', operation) try: self._prepared = self._connection.cmd_stmt_prepare(operation) except errors.Error: self._executed = None raise self._connection.cmd_stmt_reset(self._prepared['statement_id']) if self._prepared['parameters'] and not params: return elif len(self._prepared['parameters']) != len(params): raise errors.ProgrammingError( errno=1210, msg="Incorrect number of arguments " "executing prepared statement") res = self._connection.cmd_stmt_execute( self._prepared['statement_id'], data=params, parameters=self._prepared['parameters']) self._handle_result(res) def executemany(self, operation, seq_params): """Prepare and execute a MySQL Prepared Statement many times This method will prepare the given operation and execute with each tuple found the list seq_params. If the cursor instance already had a prepared statement, it is first closed. executemany() simply calls execute(). """ rowcnt = 0 try: for params in seq_params: self.execute(operation, params) if self.with_rows and self._have_unread_result(): self.fetchall() rowcnt += self._rowcount except (ValueError, TypeError) as err: raise errors.InterfaceError( "Failed executing the operation; {error}".format(error=err)) except: # Raise whatever execute() raises raise self._rowcount = rowcnt def fetchone(self): """Returns next row of a query result set Returns a tuple or None. """ return self._fetch_row() or None def fetchmany(self, size=None): res = [] cnt = (size or self.arraysize) while cnt > 0 and self._have_unread_result(): cnt -= 1 row = self._fetch_row() if row: res.append(row) return res def fetchall(self): if not self._have_unread_result(): raise errors.InterfaceError("No result set to fetch from.") (rows, eof) = self._connection.get_rows( binary=self._binary, columns=self.description) self._rowcount = len(rows) self._handle_eof(eof) return rows mysql-connector-python-1.1.6/python3/mysql/connector/errors.py0000644001577100000120000002267112276514013024103 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Python exceptions """ from mysql.connector import utils from mysql.connector.locales import get_client_error # _CUSTOM_ERROR_EXCEPTIONS holds custom exceptions and is ued by the # function custom_error_exception. _ERROR_EXCEPTIONS (at bottom of module) # is similar, but hardcoded exceptions. _CUSTOM_ERROR_EXCEPTIONS = {} def custom_error_exception(error=None, exception=None): """Define custom exceptions for MySQL server errors This function defines custom exceptions for MySQL server errors and returns the current set customizations. If error is a MySQL Server error number, then you have to pass also the exception class. The error argument can also be a dictionary in which case the key is the server error number, and value the exception to be raised. If none of the arguments are given, then custom_error_exception() will simply return the current set customizations. To reset the customizations, simply supply an empty dictionary. Examples: import mysql.connector from mysql.connector import errorcode # Server error 1028 should raise a DatabaseError mysql.connector.custom_error_exception( 1028, mysql.connector.DatabaseError) # Or using a dictionary: mysql.connector.custom_error_exception({ 1028: mysql.connector.DatabaseError, 1029: mysql.connector.OperationalError, }) # Reset mysql.connector.custom_error_exception({}) Returns a dictionary. """ global _CUSTOM_ERROR_EXCEPTIONS # pylint: disable=W0603 if isinstance(error, dict) and not len(error): _CUSTOM_ERROR_EXCEPTIONS = {} return _CUSTOM_ERROR_EXCEPTIONS if not error and not exception: return _CUSTOM_ERROR_EXCEPTIONS if not isinstance(error, (int, dict)): raise ValueError( "The error argument should be either an integer or dictionary") if isinstance(error, int): error = {error: exception} for errno, exception in error.items(): if not isinstance(errno, int): raise ValueError("error number should be an integer") try: if not issubclass(exception, Exception): raise TypeError except TypeError: raise ValueError("exception should be subclass of Exception") _CUSTOM_ERROR_EXCEPTIONS[errno] = exception return _CUSTOM_ERROR_EXCEPTIONS def get_mysql_exception(errno, msg, sqlstate=None): """Get the exception matching the MySQL error This function will return an exception based on the SQLState. The given message will be passed on in the returned exception. The exception returned can be customized using the mysql.connector.custom_error_exception() function. Returns an Exception """ try: return _CUSTOM_ERROR_EXCEPTIONS[errno]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Error was not mapped to particular exception pass try: return _ERROR_EXCEPTIONS[errno]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Error was not mapped to particular exception pass if not sqlstate: return DatabaseError(msg=msg, errno=errno) try: return _SQLSTATE_CLASS_EXCEPTION[sqlstate[0:2]]( msg=msg, errno=errno, sqlstate=sqlstate) except KeyError: # Return default InterfaceError return DatabaseError(msg=msg, errno=errno, sqlstate=sqlstate) def get_exception(packet): """Returns an exception object based on the MySQL error Returns an exception object based on the MySQL error in the given packet. Returns an Error-Object. """ errno = errmsg = None if packet[4] != 255: raise ValueError("Packet is not an error packet") sqlstate = None try: packet = packet[5:] (packet, errno) = utils.read_int(packet, 2) if packet[0] != 35: # Error without SQLState errmsg = packet else: (packet, sqlstate) = utils.read_bytes(packet[1:], 5) sqlstate = sqlstate.decode('utf8') errmsg = packet.decode('utf8') except Exception as err: # pylint: disable=W0703 return InterfaceError("Failed getting Error information (%r)" % err) else: return get_mysql_exception(errno, errmsg, sqlstate) class Error(Exception): """Exception that is base class for all other error exceptions""" def __init__(self, msg=None, errno=None, values=None, sqlstate=None): super(Error, self).__init__() self.msg = msg self._full_msg = self.msg self.errno = errno or -1 self.sqlstate = sqlstate if not self.msg and (2000 <= self.errno < 3000): self.msg = get_client_error(self.errno) if values is not None: try: self.msg = self.msg % values except TypeError as err: self.msg = "{0} (Warning: {1})".format(self.msg, str(err)) elif not self.msg: self._full_msg = self.msg = 'Unknown error' if self.msg and self.errno != -1: fields = { 'errno': self.errno, 'msg': self.msg } if self.sqlstate: fmt = '{errno} ({state}): {msg}' fields['state'] = self.sqlstate else: fmt = '{errno}: {msg}' self._full_msg = fmt.format(**fields) def __str__(self): return self._full_msg class Warning(Exception): # pylint: disable=W0622 """Exception for important warnings""" pass class InterfaceError(Error): """Exception for errors related to the interface""" pass class DatabaseError(Error): """Exception for errors related to the database""" pass class InternalError(DatabaseError): """Exception for errors internal database errors""" pass class OperationalError(DatabaseError): """Exception for errors related to the database's operation""" pass class ProgrammingError(DatabaseError): """Exception for errors programming errors""" pass class IntegrityError(DatabaseError): """Exception for errors regarding relational integrity""" pass class DataError(DatabaseError): """Exception for errors reporting problems with processed data""" pass class NotSupportedError(DatabaseError): """Exception for errors when an unsupported database feature was used""" pass class PoolError(Error): """Exception raise for errors relating to connection pooling""" pass _SQLSTATE_CLASS_EXCEPTION = { '02': DataError, # no data '07': DatabaseError, # dynamic SQL error '08': OperationalError, # connection exception '0A': NotSupportedError, # feature not supported '21': DataError, # cardinality violation '22': DataError, # data exception '23': IntegrityError, # integrity constraint violation '24': ProgrammingError, # invalid cursor state '25': ProgrammingError, # invalid transaction state '26': ProgrammingError, # invalid SQL statement name '27': ProgrammingError, # triggered data change violation '28': ProgrammingError, # invalid authorization specification '2A': ProgrammingError, # direct SQL syntax error or access rule violation '2B': DatabaseError, # dependent privilege descriptors still exist '2C': ProgrammingError, # invalid character set name '2D': DatabaseError, # invalid transaction termination '2E': DatabaseError, # invalid connection name '33': DatabaseError, # invalid SQL descriptor name '34': ProgrammingError, # invalid cursor name '35': ProgrammingError, # invalid condition number '37': ProgrammingError, # dynamic SQL syntax error or access rule violation '3C': ProgrammingError, # ambiguous cursor name '3D': ProgrammingError, # invalid catalog name '3F': ProgrammingError, # invalid schema name '40': InternalError, # transaction rollback '42': ProgrammingError, # syntax error or access rule violation '44': InternalError, # with check option violation 'HZ': OperationalError, # remote database access 'XA': IntegrityError, '0K': OperationalError, 'HY': DatabaseError, # default when no SQLState provided by MySQL server } _ERROR_EXCEPTIONS = { 1243: ProgrammingError, 1210: ProgrammingError, } mysql-connector-python-1.1.6/python3/mysql/connector/network.py0000644001577100000120000003401112276514013024247 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Module implementing low-level socket communication with MySQL servers. """ import socket import struct from collections import deque import zlib try: import ssl except: # If import fails, we don't have SSL support. pass from mysql.connector import (constants, errors) def _strioerror(err): """Reformat the IOError error message This function reformats the IOError error message. """ if not err.errno: return str(err) return '{errno} {strerr}'.format(errno=err.errno, strerr=err.strerror) def _prepare_packets(buf, pktnr): """Prepare a packet for sending to the MySQL server""" pkts = [] pllen = len(buf) maxpktlen = constants.MAX_PACKET_LENGTH while pllen > maxpktlen: pkts.append(b'\xff\xff\xff' + struct.pack(' 255: self._packet_number = 0 return self._packet_number def open_connection(self): """Open the socket""" raise NotImplementedError def get_address(self): """Get the location of the socket""" raise NotImplementedError def close_connection(self): """Close the socket""" try: self.sock.close() del self._packet_queue except (socket.error, AttributeError): pass def send_plain(self, buf, packet_number=None): """Send packets to the MySQL server""" if packet_number is None: self.next_packet_number # pylint: disable=W0104 else: self._packet_number = packet_number packets = _prepare_packets(buf, self._packet_number) for packet in packets: try: self.sock.sendall(packet) except IOError as err: raise errors.OperationalError( errno=2055, values=(self.get_address(), _strioerror(err))) except AttributeError: raise errors.OperationalError(errno=2006) send = send_plain def send_compressed(self, buf, packet_number=None): """Send compressed packets to the MySQL server""" if packet_number is None: self.next_packet_number # pylint: disable=W0104 else: self._packet_number = packet_number pktnr = self._packet_number pllen = len(buf) zpkts = [] maxpktlen = constants.MAX_PACKET_LENGTH if pllen > maxpktlen: pkts = _prepare_packets(buf, pktnr) tmpbuf = b''.join(pkts) del pkts seqid = 0 zbuf = zlib.compress(tmpbuf[:16384]) zpkts.append(struct.pack(' maxpktlen: zbuf = zlib.compress(tmpbuf[:maxpktlen]) zpkts.append(struct.pack(' 50: zbuf = zlib.compress(pkt) zpkts.append(struct.pack(' 0: chunk = self.sock.recv(rest) if not chunk: raise errors.InterfaceError(errno=2013) packet += chunk rest = packet_totlen - len(packet) return packet except IOError as err: raise errors.OperationalError( errno=2055, values=(self.get_address(), _strioerror(err))) recv = recv_plain def _split_zipped_payload(self, packet_bunch): """Split compressed payload""" while packet_bunch: payload_length = struct.unpack(", like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. _GENERATED_ON = '2013-10-04' _MYSQL_VERSION = (5, 7, 2) """This module contains the MySQL Server and Client error codes""" # Start MySQL Errors ER_HASHCHK = 1000 ER_NISAMCHK = 1001 ER_NO = 1002 ER_YES = 1003 ER_CANT_CREATE_FILE = 1004 ER_CANT_CREATE_TABLE = 1005 ER_CANT_CREATE_DB = 1006 ER_DB_CREATE_EXISTS = 1007 ER_DB_DROP_EXISTS = 1008 ER_DB_DROP_DELETE = 1009 ER_DB_DROP_RMDIR = 1010 ER_CANT_DELETE_FILE = 1011 ER_CANT_FIND_SYSTEM_REC = 1012 ER_CANT_GET_STAT = 1013 ER_CANT_GET_WD = 1014 ER_CANT_LOCK = 1015 ER_CANT_OPEN_FILE = 1016 ER_FILE_NOT_FOUND = 1017 ER_CANT_READ_DIR = 1018 ER_CANT_SET_WD = 1019 ER_CHECKREAD = 1020 ER_DISK_FULL = 1021 ER_DUP_KEY = 1022 ER_ERROR_ON_CLOSE = 1023 ER_ERROR_ON_READ = 1024 ER_ERROR_ON_RENAME = 1025 ER_ERROR_ON_WRITE = 1026 ER_FILE_USED = 1027 ER_FILSORT_ABORT = 1028 ER_FORM_NOT_FOUND = 1029 ER_GET_ERRNO = 1030 ER_ILLEGAL_HA = 1031 ER_KEY_NOT_FOUND = 1032 ER_NOT_FORM_FILE = 1033 ER_NOT_KEYFILE = 1034 ER_OLD_KEYFILE = 1035 ER_OPEN_AS_READONLY = 1036 ER_OUTOFMEMORY = 1037 ER_OUT_OF_SORTMEMORY = 1038 ER_UNEXPECTED_EOF = 1039 ER_CON_COUNT_ERROR = 1040 ER_OUT_OF_RESOURCES = 1041 ER_BAD_HOST_ERROR = 1042 ER_HANDSHAKE_ERROR = 1043 ER_DBACCESS_DENIED_ERROR = 1044 ER_ACCESS_DENIED_ERROR = 1045 ER_NO_DB_ERROR = 1046 ER_UNKNOWN_COM_ERROR = 1047 ER_BAD_NULL_ERROR = 1048 ER_BAD_DB_ERROR = 1049 ER_TABLE_EXISTS_ERROR = 1050 ER_BAD_TABLE_ERROR = 1051 ER_NON_UNIQ_ERROR = 1052 ER_SERVER_SHUTDOWN = 1053 ER_BAD_FIELD_ERROR = 1054 ER_WRONG_FIELD_WITH_GROUP = 1055 ER_WRONG_GROUP_FIELD = 1056 ER_WRONG_SUM_SELECT = 1057 ER_WRONG_VALUE_COUNT = 1058 ER_TOO_LONG_IDENT = 1059 ER_DUP_FIELDNAME = 1060 ER_DUP_KEYNAME = 1061 ER_DUP_ENTRY = 1062 ER_WRONG_FIELD_SPEC = 1063 ER_PARSE_ERROR = 1064 ER_EMPTY_QUERY = 1065 ER_NONUNIQ_TABLE = 1066 ER_INVALID_DEFAULT = 1067 ER_MULTIPLE_PRI_KEY = 1068 ER_TOO_MANY_KEYS = 1069 ER_TOO_MANY_KEY_PARTS = 1070 ER_TOO_LONG_KEY = 1071 ER_KEY_COLUMN_DOES_NOT_EXITS = 1072 ER_BLOB_USED_AS_KEY = 1073 ER_TOO_BIG_FIELDLENGTH = 1074 ER_WRONG_AUTO_KEY = 1075 ER_READY = 1076 ER_NORMAL_SHUTDOWN = 1077 ER_GOT_SIGNAL = 1078 ER_SHUTDOWN_COMPLETE = 1079 ER_FORCING_CLOSE = 1080 ER_IPSOCK_ERROR = 1081 ER_NO_SUCH_INDEX = 1082 ER_WRONG_FIELD_TERMINATORS = 1083 ER_BLOBS_AND_NO_TERMINATED = 1084 ER_TEXTFILE_NOT_READABLE = 1085 ER_FILE_EXISTS_ERROR = 1086 ER_LOAD_INFO = 1087 ER_ALTER_INFO = 1088 ER_WRONG_SUB_KEY = 1089 ER_CANT_REMOVE_ALL_FIELDS = 1090 ER_CANT_DROP_FIELD_OR_KEY = 1091 ER_INSERT_INFO = 1092 ER_UPDATE_TABLE_USED = 1093 ER_NO_SUCH_THREAD = 1094 ER_KILL_DENIED_ERROR = 1095 ER_NO_TABLES_USED = 1096 ER_TOO_BIG_SET = 1097 ER_NO_UNIQUE_LOGFILE = 1098 ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099 ER_TABLE_NOT_LOCKED = 1100 ER_BLOB_CANT_HAVE_DEFAULT = 1101 ER_WRONG_DB_NAME = 1102 ER_WRONG_TABLE_NAME = 1103 ER_TOO_BIG_SELECT = 1104 ER_UNKNOWN_ERROR = 1105 ER_UNKNOWN_PROCEDURE = 1106 ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108 ER_UNKNOWN_TABLE = 1109 ER_FIELD_SPECIFIED_TWICE = 1110 ER_INVALID_GROUP_FUNC_USE = 1111 ER_UNSUPPORTED_EXTENSION = 1112 ER_TABLE_MUST_HAVE_COLUMNS = 1113 ER_RECORD_FILE_FULL = 1114 ER_UNKNOWN_CHARACTER_SET = 1115 ER_TOO_MANY_TABLES = 1116 ER_TOO_MANY_FIELDS = 1117 ER_TOO_BIG_ROWSIZE = 1118 ER_STACK_OVERRUN = 1119 ER_WRONG_OUTER_JOIN = 1120 ER_NULL_COLUMN_IN_INDEX = 1121 ER_CANT_FIND_UDF = 1122 ER_CANT_INITIALIZE_UDF = 1123 ER_UDF_NO_PATHS = 1124 ER_UDF_EXISTS = 1125 ER_CANT_OPEN_LIBRARY = 1126 ER_CANT_FIND_DL_ENTRY = 1127 ER_FUNCTION_NOT_DEFINED = 1128 ER_HOST_IS_BLOCKED = 1129 ER_HOST_NOT_PRIVILEGED = 1130 ER_PASSWORD_ANONYMOUS_USER = 1131 ER_PASSWORD_NOT_ALLOWED = 1132 ER_PASSWORD_NO_MATCH = 1133 ER_UPDATE_INFO = 1134 ER_CANT_CREATE_THREAD = 1135 ER_WRONG_VALUE_COUNT_ON_ROW = 1136 ER_CANT_REOPEN_TABLE = 1137 ER_INVALID_USE_OF_NULL = 1138 ER_REGEXP_ERROR = 1139 ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 ER_NONEXISTING_GRANT = 1141 ER_TABLEACCESS_DENIED_ERROR = 1142 ER_COLUMNACCESS_DENIED_ERROR = 1143 ER_ILLEGAL_GRANT_FOR_TABLE = 1144 ER_GRANT_WRONG_HOST_OR_USER = 1145 ER_NO_SUCH_TABLE = 1146 ER_NONEXISTING_TABLE_GRANT = 1147 ER_NOT_ALLOWED_COMMAND = 1148 ER_SYNTAX_ERROR = 1149 ER_UNUSED1 = 1150 ER_UNUSED2 = 1151 ER_ABORTING_CONNECTION = 1152 ER_NET_PACKET_TOO_LARGE = 1153 ER_NET_READ_ERROR_FROM_PIPE = 1154 ER_NET_FCNTL_ERROR = 1155 ER_NET_PACKETS_OUT_OF_ORDER = 1156 ER_NET_UNCOMPRESS_ERROR = 1157 ER_NET_READ_ERROR = 1158 ER_NET_READ_INTERRUPTED = 1159 ER_NET_ERROR_ON_WRITE = 1160 ER_NET_WRITE_INTERRUPTED = 1161 ER_TOO_LONG_STRING = 1162 ER_TABLE_CANT_HANDLE_BLOB = 1163 ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 ER_UNUSED3 = 1165 ER_WRONG_COLUMN_NAME = 1166 ER_WRONG_KEY_COLUMN = 1167 ER_WRONG_MRG_TABLE = 1168 ER_DUP_UNIQUE = 1169 ER_BLOB_KEY_WITHOUT_LENGTH = 1170 ER_PRIMARY_CANT_HAVE_NULL = 1171 ER_TOO_MANY_ROWS = 1172 ER_REQUIRES_PRIMARY_KEY = 1173 ER_NO_RAID_COMPILED = 1174 ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 ER_KEY_DOES_NOT_EXITS = 1176 ER_CHECK_NO_SUCH_TABLE = 1177 ER_CHECK_NOT_IMPLEMENTED = 1178 ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 ER_ERROR_DURING_COMMIT = 1180 ER_ERROR_DURING_ROLLBACK = 1181 ER_ERROR_DURING_FLUSH_LOGS = 1182 ER_ERROR_DURING_CHECKPOINT = 1183 ER_NEW_ABORTING_CONNECTION = 1184 ER_DUMP_NOT_IMPLEMENTED = 1185 ER_FLUSH_MASTER_BINLOG_CLOSED = 1186 ER_INDEX_REBUILD = 1187 ER_MASTER = 1188 ER_MASTER_NET_READ = 1189 ER_MASTER_NET_WRITE = 1190 ER_FT_MATCHING_KEY_NOT_FOUND = 1191 ER_LOCK_OR_ACTIVE_TRANSACTION = 1192 ER_UNKNOWN_SYSTEM_VARIABLE = 1193 ER_CRASHED_ON_USAGE = 1194 ER_CRASHED_ON_REPAIR = 1195 ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196 ER_TRANS_CACHE_FULL = 1197 ER_SLAVE_MUST_STOP = 1198 ER_SLAVE_NOT_RUNNING = 1199 ER_BAD_SLAVE = 1200 ER_MASTER_INFO = 1201 ER_SLAVE_THREAD = 1202 ER_TOO_MANY_USER_CONNECTIONS = 1203 ER_SET_CONSTANTS_ONLY = 1204 ER_LOCK_WAIT_TIMEOUT = 1205 ER_LOCK_TABLE_FULL = 1206 ER_READ_ONLY_TRANSACTION = 1207 ER_DROP_DB_WITH_READ_LOCK = 1208 ER_CREATE_DB_WITH_READ_LOCK = 1209 ER_WRONG_ARGUMENTS = 1210 ER_NO_PERMISSION_TO_CREATE_USER = 1211 ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212 ER_LOCK_DEADLOCK = 1213 ER_TABLE_CANT_HANDLE_FT = 1214 ER_CANNOT_ADD_FOREIGN = 1215 ER_NO_REFERENCED_ROW = 1216 ER_ROW_IS_REFERENCED = 1217 ER_CONNECT_TO_MASTER = 1218 ER_QUERY_ON_MASTER = 1219 ER_ERROR_WHEN_EXECUTING_COMMAND = 1220 ER_WRONG_USAGE = 1221 ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 ER_CANT_UPDATE_WITH_READLOCK = 1223 ER_MIXING_NOT_ALLOWED = 1224 ER_DUP_ARGUMENT = 1225 ER_USER_LIMIT_REACHED = 1226 ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227 ER_LOCAL_VARIABLE = 1228 ER_GLOBAL_VARIABLE = 1229 ER_NO_DEFAULT = 1230 ER_WRONG_VALUE_FOR_VAR = 1231 ER_WRONG_TYPE_FOR_VAR = 1232 ER_VAR_CANT_BE_READ = 1233 ER_CANT_USE_OPTION_HERE = 1234 ER_NOT_SUPPORTED_YET = 1235 ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236 ER_SLAVE_IGNORED_TABLE = 1237 ER_INCORRECT_GLOBAL_LOCAL_VAR = 1238 ER_WRONG_FK_DEF = 1239 ER_KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 ER_OPERAND_COLUMNS = 1241 ER_SUBQUERY_NO_1_ROW = 1242 ER_UNKNOWN_STMT_HANDLER = 1243 ER_CORRUPT_HELP_DB = 1244 ER_CYCLIC_REFERENCE = 1245 ER_AUTO_CONVERT = 1246 ER_ILLEGAL_REFERENCE = 1247 ER_DERIVED_MUST_HAVE_ALIAS = 1248 ER_SELECT_REDUCED = 1249 ER_TABLENAME_NOT_ALLOWED_HERE = 1250 ER_NOT_SUPPORTED_AUTH_MODE = 1251 ER_SPATIAL_CANT_HAVE_NULL = 1252 ER_COLLATION_CHARSET_MISMATCH = 1253 ER_SLAVE_WAS_RUNNING = 1254 ER_SLAVE_WAS_NOT_RUNNING = 1255 ER_TOO_BIG_FOR_UNCOMPRESS = 1256 ER_ZLIB_Z_MEM_ERROR = 1257 ER_ZLIB_Z_BUF_ERROR = 1258 ER_ZLIB_Z_DATA_ERROR = 1259 ER_CUT_VALUE_GROUP_CONCAT = 1260 ER_WARN_TOO_FEW_RECORDS = 1261 ER_WARN_TOO_MANY_RECORDS = 1262 ER_WARN_NULL_TO_NOTNULL = 1263 ER_WARN_DATA_OUT_OF_RANGE = 1264 WARN_DATA_TRUNCATED = 1265 ER_WARN_USING_OTHER_HANDLER = 1266 ER_CANT_AGGREGATE_2COLLATIONS = 1267 ER_DROP_USER = 1268 ER_REVOKE_GRANTS = 1269 ER_CANT_AGGREGATE_3COLLATIONS = 1270 ER_CANT_AGGREGATE_NCOLLATIONS = 1271 ER_VARIABLE_IS_NOT_STRUCT = 1272 ER_UNKNOWN_COLLATION = 1273 ER_SLAVE_IGNORED_SSL_PARAMS = 1274 ER_SERVER_IS_IN_SECURE_AUTH_MODE = 1275 ER_WARN_FIELD_RESOLVED = 1276 ER_BAD_SLAVE_UNTIL_COND = 1277 ER_MISSING_SKIP_SLAVE = 1278 ER_UNTIL_COND_IGNORED = 1279 ER_WRONG_NAME_FOR_INDEX = 1280 ER_WRONG_NAME_FOR_CATALOG = 1281 ER_WARN_QC_RESIZE = 1282 ER_BAD_FT_COLUMN = 1283 ER_UNKNOWN_KEY_CACHE = 1284 ER_WARN_HOSTNAME_WONT_WORK = 1285 ER_UNKNOWN_STORAGE_ENGINE = 1286 ER_WARN_DEPRECATED_SYNTAX = 1287 ER_NON_UPDATABLE_TABLE = 1288 ER_FEATURE_DISABLED = 1289 ER_OPTION_PREVENTS_STATEMENT = 1290 ER_DUPLICATED_VALUE_IN_TYPE = 1291 ER_TRUNCATED_WRONG_VALUE = 1292 ER_TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 ER_INVALID_ON_UPDATE = 1294 ER_UNSUPPORTED_PS = 1295 ER_GET_ERRMSG = 1296 ER_GET_TEMPORARY_ERRMSG = 1297 ER_UNKNOWN_TIME_ZONE = 1298 ER_WARN_INVALID_TIMESTAMP = 1299 ER_INVALID_CHARACTER_STRING = 1300 ER_WARN_ALLOWED_PACKET_OVERFLOWED = 1301 ER_CONFLICTING_DECLARATIONS = 1302 ER_SP_NO_RECURSIVE_CREATE = 1303 ER_SP_ALREADY_EXISTS = 1304 ER_SP_DOES_NOT_EXIST = 1305 ER_SP_DROP_FAILED = 1306 ER_SP_STORE_FAILED = 1307 ER_SP_LILABEL_MISMATCH = 1308 ER_SP_LABEL_REDEFINE = 1309 ER_SP_LABEL_MISMATCH = 1310 ER_SP_UNINIT_VAR = 1311 ER_SP_BADSELECT = 1312 ER_SP_BADRETURN = 1313 ER_SP_BADSTATEMENT = 1314 ER_UPDATE_LOG_DEPRECATED_IGNORED = 1315 ER_UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 ER_QUERY_INTERRUPTED = 1317 ER_SP_WRONG_NO_OF_ARGS = 1318 ER_SP_COND_MISMATCH = 1319 ER_SP_NORETURN = 1320 ER_SP_NORETURNEND = 1321 ER_SP_BAD_CURSOR_QUERY = 1322 ER_SP_BAD_CURSOR_SELECT = 1323 ER_SP_CURSOR_MISMATCH = 1324 ER_SP_CURSOR_ALREADY_OPEN = 1325 ER_SP_CURSOR_NOT_OPEN = 1326 ER_SP_UNDECLARED_VAR = 1327 ER_SP_WRONG_NO_OF_FETCH_ARGS = 1328 ER_SP_FETCH_NO_DATA = 1329 ER_SP_DUP_PARAM = 1330 ER_SP_DUP_VAR = 1331 ER_SP_DUP_COND = 1332 ER_SP_DUP_CURS = 1333 ER_SP_CANT_ALTER = 1334 ER_SP_SUBSELECT_NYI = 1335 ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 ER_SP_VARCOND_AFTER_CURSHNDLR = 1337 ER_SP_CURSOR_AFTER_HANDLER = 1338 ER_SP_CASE_NOT_FOUND = 1339 ER_FPARSER_TOO_BIG_FILE = 1340 ER_FPARSER_BAD_HEADER = 1341 ER_FPARSER_EOF_IN_COMMENT = 1342 ER_FPARSER_ERROR_IN_PARAMETER = 1343 ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 ER_VIEW_NO_EXPLAIN = 1345 ER_FRM_UNKNOWN_TYPE = 1346 ER_WRONG_OBJECT = 1347 ER_NONUPDATEABLE_COLUMN = 1348 ER_VIEW_SELECT_DERIVED = 1349 ER_VIEW_SELECT_CLAUSE = 1350 ER_VIEW_SELECT_VARIABLE = 1351 ER_VIEW_SELECT_TMPTABLE = 1352 ER_VIEW_WRONG_LIST = 1353 ER_WARN_VIEW_MERGE = 1354 ER_WARN_VIEW_WITHOUT_KEY = 1355 ER_VIEW_INVALID = 1356 ER_SP_NO_DROP_SP = 1357 ER_SP_GOTO_IN_HNDLR = 1358 ER_TRG_ALREADY_EXISTS = 1359 ER_TRG_DOES_NOT_EXIST = 1360 ER_TRG_ON_VIEW_OR_TEMP_TABLE = 1361 ER_TRG_CANT_CHANGE_ROW = 1362 ER_TRG_NO_SUCH_ROW_IN_TRG = 1363 ER_NO_DEFAULT_FOR_FIELD = 1364 ER_DIVISION_BY_ZERO = 1365 ER_TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 ER_ILLEGAL_VALUE_FOR_TYPE = 1367 ER_VIEW_NONUPD_CHECK = 1368 ER_VIEW_CHECK_FAILED = 1369 ER_PROCACCESS_DENIED_ERROR = 1370 ER_RELAY_LOG_FAIL = 1371 ER_PASSWD_LENGTH = 1372 ER_UNKNOWN_TARGET_BINLOG = 1373 ER_IO_ERR_LOG_INDEX_READ = 1374 ER_BINLOG_PURGE_PROHIBITED = 1375 ER_FSEEK_FAIL = 1376 ER_BINLOG_PURGE_FATAL_ERR = 1377 ER_LOG_IN_USE = 1378 ER_LOG_PURGE_UNKNOWN_ERR = 1379 ER_RELAY_LOG_INIT = 1380 ER_NO_BINARY_LOGGING = 1381 ER_RESERVED_SYNTAX = 1382 ER_WSAS_FAILED = 1383 ER_DIFF_GROUPS_PROC = 1384 ER_NO_GROUP_FOR_PROC = 1385 ER_ORDER_WITH_PROC = 1386 ER_LOGGING_PROHIBIT_CHANGING_OF = 1387 ER_NO_FILE_MAPPING = 1388 ER_WRONG_MAGIC = 1389 ER_PS_MANY_PARAM = 1390 ER_KEY_PART_0 = 1391 ER_VIEW_CHECKSUM = 1392 ER_VIEW_MULTIUPDATE = 1393 ER_VIEW_NO_INSERT_FIELD_LIST = 1394 ER_VIEW_DELETE_MERGE_VIEW = 1395 ER_CANNOT_USER = 1396 ER_XAER_NOTA = 1397 ER_XAER_INVAL = 1398 ER_XAER_RMFAIL = 1399 ER_XAER_OUTSIDE = 1400 ER_XAER_RMERR = 1401 ER_XA_RBROLLBACK = 1402 ER_NONEXISTING_PROC_GRANT = 1403 ER_PROC_AUTO_GRANT_FAIL = 1404 ER_PROC_AUTO_REVOKE_FAIL = 1405 ER_DATA_TOO_LONG = 1406 ER_SP_BAD_SQLSTATE = 1407 ER_STARTUP = 1408 ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 ER_CANT_CREATE_USER_WITH_GRANT = 1410 ER_WRONG_VALUE_FOR_TYPE = 1411 ER_TABLE_DEF_CHANGED = 1412 ER_SP_DUP_HANDLER = 1413 ER_SP_NOT_VAR_ARG = 1414 ER_SP_NO_RETSET = 1415 ER_CANT_CREATE_GEOMETRY_OBJECT = 1416 ER_FAILED_ROUTINE_BREAK_BINLOG = 1417 ER_BINLOG_UNSAFE_ROUTINE = 1418 ER_BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 ER_EXEC_STMT_WITH_OPEN_CURSOR = 1420 ER_STMT_HAS_NO_OPEN_CURSOR = 1421 ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 ER_NO_DEFAULT_FOR_VIEW_FIELD = 1423 ER_SP_NO_RECURSION = 1424 ER_TOO_BIG_SCALE = 1425 ER_TOO_BIG_PRECISION = 1426 ER_M_BIGGER_THAN_D = 1427 ER_WRONG_LOCK_OF_SYSTEM_TABLE = 1428 ER_CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 ER_QUERY_ON_FOREIGN_DATA_SOURCE = 1430 ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 ER_FOREIGN_DATA_STRING_INVALID = 1433 ER_CANT_CREATE_FEDERATED_TABLE = 1434 ER_TRG_IN_WRONG_SCHEMA = 1435 ER_STACK_OVERRUN_NEED_MORE = 1436 ER_TOO_LONG_BODY = 1437 ER_WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 ER_TOO_BIG_DISPLAYWIDTH = 1439 ER_XAER_DUPID = 1440 ER_DATETIME_FUNCTION_OVERFLOW = 1441 ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 ER_VIEW_PREVENT_UPDATE = 1443 ER_PS_NO_RECURSION = 1444 ER_SP_CANT_SET_AUTOCOMMIT = 1445 ER_MALFORMED_DEFINER = 1446 ER_VIEW_FRM_NO_USER = 1447 ER_VIEW_OTHER_USER = 1448 ER_NO_SUCH_USER = 1449 ER_FORBID_SCHEMA_CHANGE = 1450 ER_ROW_IS_REFERENCED_2 = 1451 ER_NO_REFERENCED_ROW_2 = 1452 ER_SP_BAD_VAR_SHADOW = 1453 ER_TRG_NO_DEFINER = 1454 ER_OLD_FILE_FORMAT = 1455 ER_SP_RECURSION_LIMIT = 1456 ER_SP_PROC_TABLE_CORRUPT = 1457 ER_SP_WRONG_NAME = 1458 ER_TABLE_NEEDS_UPGRADE = 1459 ER_SP_NO_AGGREGATE = 1460 ER_MAX_PREPARED_STMT_COUNT_REACHED = 1461 ER_VIEW_RECURSIVE = 1462 ER_NON_GROUPING_FIELD_USED = 1463 ER_TABLE_CANT_HANDLE_SPKEYS = 1464 ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA = 1465 ER_REMOVED_SPACES = 1466 ER_AUTOINC_READ_FAILED = 1467 ER_USERNAME = 1468 ER_HOSTNAME = 1469 ER_WRONG_STRING_LENGTH = 1470 ER_NON_INSERTABLE_TABLE = 1471 ER_ADMIN_WRONG_MRG_TABLE = 1472 ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT = 1473 ER_NAME_BECOMES_EMPTY = 1474 ER_AMBIGUOUS_FIELD_TERM = 1475 ER_FOREIGN_SERVER_EXISTS = 1476 ER_FOREIGN_SERVER_DOESNT_EXIST = 1477 ER_ILLEGAL_HA_CREATE_OPTION = 1478 ER_PARTITION_REQUIRES_VALUES_ERROR = 1479 ER_PARTITION_WRONG_VALUES_ERROR = 1480 ER_PARTITION_MAXVALUE_ERROR = 1481 ER_PARTITION_SUBPARTITION_ERROR = 1482 ER_PARTITION_SUBPART_MIX_ERROR = 1483 ER_PARTITION_WRONG_NO_PART_ERROR = 1484 ER_PARTITION_WRONG_NO_SUBPART_ERROR = 1485 ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR = 1486 ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR = 1487 ER_FIELD_NOT_FOUND_PART_ERROR = 1488 ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR = 1489 ER_INCONSISTENT_PARTITION_INFO_ERROR = 1490 ER_PARTITION_FUNC_NOT_ALLOWED_ERROR = 1491 ER_PARTITIONS_MUST_BE_DEFINED_ERROR = 1492 ER_RANGE_NOT_INCREASING_ERROR = 1493 ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR = 1494 ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR = 1495 ER_PARTITION_ENTRY_ERROR = 1496 ER_MIX_HANDLER_ERROR = 1497 ER_PARTITION_NOT_DEFINED_ERROR = 1498 ER_TOO_MANY_PARTITIONS_ERROR = 1499 ER_SUBPARTITION_ERROR = 1500 ER_CANT_CREATE_HANDLER_FILE = 1501 ER_BLOB_FIELD_IN_PART_FUNC_ERROR = 1502 ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF = 1503 ER_NO_PARTS_ERROR = 1504 ER_PARTITION_MGMT_ON_NONPARTITIONED = 1505 ER_FOREIGN_KEY_ON_PARTITIONED = 1506 ER_DROP_PARTITION_NON_EXISTENT = 1507 ER_DROP_LAST_PARTITION = 1508 ER_COALESCE_ONLY_ON_HASH_PARTITION = 1509 ER_REORG_HASH_ONLY_ON_SAME_NO = 1510 ER_REORG_NO_PARAM_ERROR = 1511 ER_ONLY_ON_RANGE_LIST_PARTITION = 1512 ER_ADD_PARTITION_SUBPART_ERROR = 1513 ER_ADD_PARTITION_NO_NEW_PARTITION = 1514 ER_COALESCE_PARTITION_NO_PARTITION = 1515 ER_REORG_PARTITION_NOT_EXIST = 1516 ER_SAME_NAME_PARTITION = 1517 ER_NO_BINLOG_ERROR = 1518 ER_CONSECUTIVE_REORG_PARTITIONS = 1519 ER_REORG_OUTSIDE_RANGE = 1520 ER_PARTITION_FUNCTION_FAILURE = 1521 ER_PART_STATE_ERROR = 1522 ER_LIMITED_PART_RANGE = 1523 ER_PLUGIN_IS_NOT_LOADED = 1524 ER_WRONG_VALUE = 1525 ER_NO_PARTITION_FOR_GIVEN_VALUE = 1526 ER_FILEGROUP_OPTION_ONLY_ONCE = 1527 ER_CREATE_FILEGROUP_FAILED = 1528 ER_DROP_FILEGROUP_FAILED = 1529 ER_TABLESPACE_AUTO_EXTEND_ERROR = 1530 ER_WRONG_SIZE_NUMBER = 1531 ER_SIZE_OVERFLOW_ERROR = 1532 ER_ALTER_FILEGROUP_FAILED = 1533 ER_BINLOG_ROW_LOGGING_FAILED = 1534 ER_BINLOG_ROW_WRONG_TABLE_DEF = 1535 ER_BINLOG_ROW_RBR_TO_SBR = 1536 ER_EVENT_ALREADY_EXISTS = 1537 ER_EVENT_STORE_FAILED = 1538 ER_EVENT_DOES_NOT_EXIST = 1539 ER_EVENT_CANT_ALTER = 1540 ER_EVENT_DROP_FAILED = 1541 ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG = 1542 ER_EVENT_ENDS_BEFORE_STARTS = 1543 ER_EVENT_EXEC_TIME_IN_THE_PAST = 1544 ER_EVENT_OPEN_TABLE_FAILED = 1545 ER_EVENT_NEITHER_M_EXPR_NOR_M_AT = 1546 ER_OBSOLETE_COL_COUNT_DOESNT_MATCH_CORRUPTED = 1547 ER_OBSOLETE_CANNOT_LOAD_FROM_TABLE = 1548 ER_EVENT_CANNOT_DELETE = 1549 ER_EVENT_COMPILE_ERROR = 1550 ER_EVENT_SAME_NAME = 1551 ER_EVENT_DATA_TOO_LONG = 1552 ER_DROP_INDEX_FK = 1553 ER_WARN_DEPRECATED_SYNTAX_WITH_VER = 1554 ER_CANT_WRITE_LOCK_LOG_TABLE = 1555 ER_CANT_LOCK_LOG_TABLE = 1556 ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED = 1557 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE = 1558 ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR = 1559 ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1560 ER_NDB_CANT_SWITCH_BINLOG_FORMAT = 1561 ER_PARTITION_NO_TEMPORARY = 1562 ER_PARTITION_CONST_DOMAIN_ERROR = 1563 ER_PARTITION_FUNCTION_IS_NOT_ALLOWED = 1564 ER_DDL_LOG_ERROR = 1565 ER_NULL_IN_VALUES_LESS_THAN = 1566 ER_WRONG_PARTITION_NAME = 1567 ER_CANT_CHANGE_TX_CHARACTERISTICS = 1568 ER_DUP_ENTRY_AUTOINCREMENT_CASE = 1569 ER_EVENT_MODIFY_QUEUE_ERROR = 1570 ER_EVENT_SET_VAR_ERROR = 1571 ER_PARTITION_MERGE_ERROR = 1572 ER_CANT_ACTIVATE_LOG = 1573 ER_RBR_NOT_AVAILABLE = 1574 ER_BASE64_DECODE_ERROR = 1575 ER_EVENT_RECURSION_FORBIDDEN = 1576 ER_EVENTS_DB_ERROR = 1577 ER_ONLY_INTEGERS_ALLOWED = 1578 ER_UNSUPORTED_LOG_ENGINE = 1579 ER_BAD_LOG_STATEMENT = 1580 ER_CANT_RENAME_LOG_TABLE = 1581 ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT = 1582 ER_WRONG_PARAMETERS_TO_NATIVE_FCT = 1583 ER_WRONG_PARAMETERS_TO_STORED_FCT = 1584 ER_NATIVE_FCT_NAME_COLLISION = 1585 ER_DUP_ENTRY_WITH_KEY_NAME = 1586 ER_BINLOG_PURGE_EMFILE = 1587 ER_EVENT_CANNOT_CREATE_IN_THE_PAST = 1588 ER_EVENT_CANNOT_ALTER_IN_THE_PAST = 1589 ER_SLAVE_INCIDENT = 1590 ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT = 1591 ER_BINLOG_UNSAFE_STATEMENT = 1592 ER_SLAVE_FATAL_ERROR = 1593 ER_SLAVE_RELAY_LOG_READ_FAILURE = 1594 ER_SLAVE_RELAY_LOG_WRITE_FAILURE = 1595 ER_SLAVE_CREATE_EVENT_FAILURE = 1596 ER_SLAVE_MASTER_COM_FAILURE = 1597 ER_BINLOG_LOGGING_IMPOSSIBLE = 1598 ER_VIEW_NO_CREATION_CTX = 1599 ER_VIEW_INVALID_CREATION_CTX = 1600 ER_SR_INVALID_CREATION_CTX = 1601 ER_TRG_CORRUPTED_FILE = 1602 ER_TRG_NO_CREATION_CTX = 1603 ER_TRG_INVALID_CREATION_CTX = 1604 ER_EVENT_INVALID_CREATION_CTX = 1605 ER_TRG_CANT_OPEN_TABLE = 1606 ER_CANT_CREATE_SROUTINE = 1607 ER_NEVER_USED = 1608 ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT = 1609 ER_SLAVE_CORRUPT_EVENT = 1610 ER_LOAD_DATA_INVALID_COLUMN = 1611 ER_LOG_PURGE_NO_FILE = 1612 ER_XA_RBTIMEOUT = 1613 ER_XA_RBDEADLOCK = 1614 ER_NEED_REPREPARE = 1615 ER_DELAYED_NOT_SUPPORTED = 1616 WARN_NO_MASTER_INFO = 1617 WARN_OPTION_IGNORED = 1618 WARN_PLUGIN_DELETE_BUILTIN = 1619 WARN_PLUGIN_BUSY = 1620 ER_VARIABLE_IS_READONLY = 1621 ER_WARN_ENGINE_TRANSACTION_ROLLBACK = 1622 ER_SLAVE_HEARTBEAT_FAILURE = 1623 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE = 1624 ER_NDB_REPLICATION_SCHEMA_ERROR = 1625 ER_CONFLICT_FN_PARSE_ERROR = 1626 ER_EXCEPTIONS_WRITE_ERROR = 1627 ER_TOO_LONG_TABLE_COMMENT = 1628 ER_TOO_LONG_FIELD_COMMENT = 1629 ER_FUNC_INEXISTENT_NAME_COLLISION = 1630 ER_DATABASE_NAME = 1631 ER_TABLE_NAME = 1632 ER_PARTITION_NAME = 1633 ER_SUBPARTITION_NAME = 1634 ER_TEMPORARY_NAME = 1635 ER_RENAMED_NAME = 1636 ER_TOO_MANY_CONCURRENT_TRXS = 1637 WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED = 1638 ER_DEBUG_SYNC_TIMEOUT = 1639 ER_DEBUG_SYNC_HIT_LIMIT = 1640 ER_DUP_SIGNAL_SET = 1641 ER_SIGNAL_WARN = 1642 ER_SIGNAL_NOT_FOUND = 1643 ER_SIGNAL_EXCEPTION = 1644 ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER = 1645 ER_SIGNAL_BAD_CONDITION_TYPE = 1646 WARN_COND_ITEM_TRUNCATED = 1647 ER_COND_ITEM_TOO_LONG = 1648 ER_UNKNOWN_LOCALE = 1649 ER_SLAVE_IGNORE_SERVER_IDS = 1650 ER_QUERY_CACHE_DISABLED = 1651 ER_SAME_NAME_PARTITION_FIELD = 1652 ER_PARTITION_COLUMN_LIST_ERROR = 1653 ER_WRONG_TYPE_COLUMN_VALUE_ERROR = 1654 ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR = 1655 ER_MAXVALUE_IN_VALUES_IN = 1656 ER_TOO_MANY_VALUES_ERROR = 1657 ER_ROW_SINGLE_PARTITION_FIELD_ERROR = 1658 ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD = 1659 ER_PARTITION_FIELDS_TOO_LONG = 1660 ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE = 1661 ER_BINLOG_ROW_MODE_AND_STMT_ENGINE = 1662 ER_BINLOG_UNSAFE_AND_STMT_ENGINE = 1663 ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE = 1664 ER_BINLOG_STMT_MODE_AND_ROW_ENGINE = 1665 ER_BINLOG_ROW_INJECTION_AND_STMT_MODE = 1666 ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1667 ER_BINLOG_UNSAFE_LIMIT = 1668 ER_UNUSED4 = 1669 ER_BINLOG_UNSAFE_SYSTEM_TABLE = 1670 ER_BINLOG_UNSAFE_AUTOINC_COLUMNS = 1671 ER_BINLOG_UNSAFE_UDF = 1672 ER_BINLOG_UNSAFE_SYSTEM_VARIABLE = 1673 ER_BINLOG_UNSAFE_SYSTEM_FUNCTION = 1674 ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS = 1675 ER_MESSAGE_AND_STATEMENT = 1676 ER_SLAVE_CONVERSION_FAILED = 1677 ER_SLAVE_CANT_CREATE_CONVERSION = 1678 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1679 ER_PATH_LENGTH = 1680 ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT = 1681 ER_WRONG_NATIVE_TABLE_STRUCTURE = 1682 ER_WRONG_PERFSCHEMA_USAGE = 1683 ER_WARN_I_S_SKIPPED_TABLE = 1684 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1685 ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1686 ER_SPATIAL_MUST_HAVE_GEOM_COL = 1687 ER_TOO_LONG_INDEX_COMMENT = 1688 ER_LOCK_ABORTED = 1689 ER_DATA_OUT_OF_RANGE = 1690 ER_WRONG_SPVAR_TYPE_IN_LIMIT = 1691 ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1692 ER_BINLOG_UNSAFE_MIXED_STATEMENT = 1693 ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1694 ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1695 ER_FAILED_READ_FROM_PAR_FILE = 1696 ER_VALUES_IS_NOT_INT_TYPE_ERROR = 1697 ER_ACCESS_DENIED_NO_PASSWORD_ERROR = 1698 ER_SET_PASSWORD_AUTH_PLUGIN = 1699 ER_GRANT_PLUGIN_USER_EXISTS = 1700 ER_TRUNCATE_ILLEGAL_FK = 1701 ER_PLUGIN_IS_PERMANENT = 1702 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN = 1703 ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX = 1704 ER_STMT_CACHE_FULL = 1705 ER_MULTI_UPDATE_KEY_CONFLICT = 1706 ER_TABLE_NEEDS_REBUILD = 1707 WARN_OPTION_BELOW_LIMIT = 1708 ER_INDEX_COLUMN_TOO_LONG = 1709 ER_ERROR_IN_TRIGGER_BODY = 1710 ER_ERROR_IN_UNKNOWN_TRIGGER_BODY = 1711 ER_INDEX_CORRUPT = 1712 ER_UNDO_RECORD_TOO_BIG = 1713 ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT = 1714 ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE = 1715 ER_BINLOG_UNSAFE_REPLACE_SELECT = 1716 ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT = 1717 ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT = 1718 ER_BINLOG_UNSAFE_UPDATE_IGNORE = 1719 ER_PLUGIN_NO_UNINSTALL = 1720 ER_PLUGIN_NO_INSTALL = 1721 ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT = 1722 ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC = 1723 ER_BINLOG_UNSAFE_INSERT_TWO_KEYS = 1724 ER_TABLE_IN_FK_CHECK = 1725 ER_UNSUPPORTED_ENGINE = 1726 ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST = 1727 ER_CANNOT_LOAD_FROM_TABLE_V2 = 1728 ER_MASTER_DELAY_VALUE_OUT_OF_RANGE = 1729 ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT = 1730 ER_PARTITION_EXCHANGE_DIFFERENT_OPTION = 1731 ER_PARTITION_EXCHANGE_PART_TABLE = 1732 ER_PARTITION_EXCHANGE_TEMP_TABLE = 1733 ER_PARTITION_INSTEAD_OF_SUBPARTITION = 1734 ER_UNKNOWN_PARTITION = 1735 ER_TABLES_DIFFERENT_METADATA = 1736 ER_ROW_DOES_NOT_MATCH_PARTITION = 1737 ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX = 1738 ER_WARN_INDEX_NOT_APPLICABLE = 1739 ER_PARTITION_EXCHANGE_FOREIGN_KEY = 1740 ER_NO_SUCH_KEY_VALUE = 1741 ER_RPL_INFO_DATA_TOO_LONG = 1742 ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE = 1743 ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE = 1744 ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX = 1745 ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT = 1746 ER_PARTITION_CLAUSE_ON_NONPARTITIONED = 1747 ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET = 1748 ER_NO_SUCH_PARTITION__UNUSED = 1749 ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE = 1750 ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE = 1751 ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE = 1752 ER_MTS_FEATURE_IS_NOT_SUPPORTED = 1753 ER_MTS_UPDATED_DBS_GREATER_MAX = 1754 ER_MTS_CANT_PARALLEL = 1755 ER_MTS_INCONSISTENT_DATA = 1756 ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING = 1757 ER_DA_INVALID_CONDITION_NUMBER = 1758 ER_INSECURE_PLAIN_TEXT = 1759 ER_INSECURE_CHANGE_MASTER = 1760 ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO = 1761 ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO = 1762 ER_SQLTHREAD_WITH_SECURE_SLAVE = 1763 ER_TABLE_HAS_NO_FT = 1764 ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER = 1765 ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION = 1766 ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST = 1767 ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL = 1768 ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION = 1769 ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL = 1770 ER_SKIPPING_LOGGED_TRANSACTION = 1771 ER_MALFORMED_GTID_SET_SPECIFICATION = 1772 ER_MALFORMED_GTID_SET_ENCODING = 1773 ER_MALFORMED_GTID_SPECIFICATION = 1774 ER_GNO_EXHAUSTED = 1775 ER_BAD_SLAVE_AUTO_POSITION = 1776 ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON = 1777 ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET = 1778 ER_GTID_MODE_2_OR_3_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON = 1779 ER_GTID_MODE_REQUIRES_BINLOG = 1780 ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF = 1781 ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON = 1782 ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF = 1783 ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF = 1784 ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE = 1785 ER_GTID_UNSAFE_CREATE_SELECT = 1786 ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION = 1787 ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME = 1788 ER_MASTER_HAS_PURGED_REQUIRED_GTIDS = 1789 ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID = 1790 ER_UNKNOWN_EXPLAIN_FORMAT = 1791 ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION = 1792 ER_TOO_LONG_TABLE_PARTITION_COMMENT = 1793 ER_SLAVE_CONFIGURATION = 1794 ER_INNODB_FT_LIMIT = 1795 ER_INNODB_NO_FT_TEMP_TABLE = 1796 ER_INNODB_FT_WRONG_DOCID_COLUMN = 1797 ER_INNODB_FT_WRONG_DOCID_INDEX = 1798 ER_INNODB_ONLINE_LOG_TOO_BIG = 1799 ER_UNKNOWN_ALTER_ALGORITHM = 1800 ER_UNKNOWN_ALTER_LOCK = 1801 ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS = 1802 ER_MTS_RECOVERY_FAILURE = 1803 ER_MTS_RESET_WORKERS = 1804 ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 = 1805 ER_SLAVE_SILENT_RETRY_TRANSACTION = 1806 ER_DISCARD_FK_CHECKS_RUNNING = 1807 ER_TABLE_SCHEMA_MISMATCH = 1808 ER_TABLE_IN_SYSTEM_TABLESPACE = 1809 ER_IO_READ_ERROR = 1810 ER_IO_WRITE_ERROR = 1811 ER_TABLESPACE_MISSING = 1812 ER_TABLESPACE_EXISTS = 1813 ER_TABLESPACE_DISCARDED = 1814 ER_INTERNAL_ERROR = 1815 ER_INNODB_IMPORT_ERROR = 1816 ER_INNODB_INDEX_CORRUPT = 1817 ER_INVALID_YEAR_COLUMN_LENGTH = 1818 ER_NOT_VALID_PASSWORD = 1819 ER_MUST_CHANGE_PASSWORD = 1820 ER_FK_NO_INDEX_CHILD = 1821 ER_FK_NO_INDEX_PARENT = 1822 ER_FK_FAIL_ADD_SYSTEM = 1823 ER_FK_CANNOT_OPEN_PARENT = 1824 ER_FK_INCORRECT_OPTION = 1825 ER_FK_DUP_NAME = 1826 ER_PASSWORD_FORMAT = 1827 ER_FK_COLUMN_CANNOT_DROP = 1828 ER_FK_COLUMN_CANNOT_DROP_CHILD = 1829 ER_FK_COLUMN_NOT_NULL = 1830 ER_DUP_INDEX = 1831 ER_FK_COLUMN_CANNOT_CHANGE = 1832 ER_FK_COLUMN_CANNOT_CHANGE_CHILD = 1833 ER_FK_CANNOT_DELETE_PARENT = 1834 ER_MALFORMED_PACKET = 1835 ER_READ_ONLY_MODE = 1836 ER_GTID_NEXT_TYPE_UNDEFINED_GROUP = 1837 ER_VARIABLE_NOT_SETTABLE_IN_SP = 1838 ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF = 1839 ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY = 1840 ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY = 1841 ER_GTID_PURGED_WAS_CHANGED = 1842 ER_GTID_EXECUTED_WAS_CHANGED = 1843 ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES = 1844 ER_ALTER_OPERATION_NOT_SUPPORTED = 1845 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON = 1846 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY = 1847 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION = 1848 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME = 1849 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE = 1850 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK = 1851 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE = 1852 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK = 1853 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC = 1854 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS = 1855 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS = 1856 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS = 1857 ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE = 1858 ER_DUP_UNKNOWN_IN_INDEX = 1859 ER_IDENT_CAUSES_TOO_LONG_PATH = 1860 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL = 1861 ER_MUST_CHANGE_PASSWORD_LOGIN = 1862 ER_ROW_IN_WRONG_PARTITION = 1863 ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX = 1864 ER_INNODB_NO_FT_USES_PARSER = 1865 ER_BINLOG_LOGICAL_CORRUPTION = 1866 ER_WARN_PURGE_LOG_IN_USE = 1867 ER_WARN_PURGE_LOG_IS_ACTIVE = 1868 ER_AUTO_INCREMENT_CONFLICT = 1869 WARN_ON_BLOCKHOLE_IN_RBR = 1870 ER_SLAVE_MI_INIT_REPOSITORY = 1871 ER_SLAVE_RLI_INIT_REPOSITORY = 1872 ER_ACCESS_DENIED_CHANGE_USER_ERROR = 1873 ER_INNODB_READ_ONLY = 1874 ER_STOP_SLAVE_SQL_THREAD_TIMEOUT = 1875 ER_STOP_SLAVE_IO_THREAD_TIMEOUT = 1876 ER_TABLE_CORRUPT = 1877 ER_FILE_CORRUPT = 1878 ER_ERROR_ON_MASTER = 1879 ER_INCONSISTENT_ERROR = 1880 ER_STORAGE_ENGINE_NOT_LOADED = 1881 ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER = 1882 ER_WARN_LEGACY_SYNTAX_CONVERTED = 1883 ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN = 1884 ER_CANNOT_DISCARD_TEMPORARY_TABLE = 1885 ER_FK_DEPTH_EXCEEDED = 1886 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 = 1887 ER_WARN_TRIGGER_DOESNT_HAVE_CREATED = 1888 ER_REFERENCED_TRG_DOES_NOT_EXIST = 1889 ER_EXPLAIN_NOT_SUPPORTED = 1890 ER_INVALID_FIELD_SIZE = 1891 ER_MISSING_HA_CREATE_OPTION = 1892 CR_UNKNOWN_ERROR = 2000 CR_SOCKET_CREATE_ERROR = 2001 CR_CONNECTION_ERROR = 2002 CR_CONN_HOST_ERROR = 2003 CR_IPSOCK_ERROR = 2004 CR_UNKNOWN_HOST = 2005 CR_SERVER_GONE_ERROR = 2006 CR_VERSION_ERROR = 2007 CR_OUT_OF_MEMORY = 2008 CR_WRONG_HOST_INFO = 2009 CR_LOCALHOST_CONNECTION = 2010 CR_TCP_CONNECTION = 2011 CR_SERVER_HANDSHAKE_ERR = 2012 CR_SERVER_LOST = 2013 CR_COMMANDS_OUT_OF_SYNC = 2014 CR_NAMEDPIPE_CONNECTION = 2015 CR_NAMEDPIPEWAIT_ERROR = 2016 CR_NAMEDPIPEOPEN_ERROR = 2017 CR_NAMEDPIPESETSTATE_ERROR = 2018 CR_CANT_READ_CHARSET = 2019 CR_NET_PACKET_TOO_LARGE = 2020 CR_EMBEDDED_CONNECTION = 2021 CR_PROBE_SLAVE_STATUS = 2022 CR_PROBE_SLAVE_HOSTS = 2023 CR_PROBE_SLAVE_CONNECT = 2024 CR_PROBE_MASTER_CONNECT = 2025 CR_SSL_CONNECTION_ERROR = 2026 CR_MALFORMED_PACKET = 2027 CR_WRONG_LICENSE = 2028 CR_NULL_POINTER = 2029 CR_NO_PREPARE_STMT = 2030 CR_PARAMS_NOT_BOUND = 2031 CR_DATA_TRUNCATED = 2032 CR_NO_PARAMETERS_EXISTS = 2033 CR_INVALID_PARAMETER_NO = 2034 CR_INVALID_BUFFER_USE = 2035 CR_UNSUPPORTED_PARAM_TYPE = 2036 CR_SHARED_MEMORY_CONNECTION = 2037 CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR = 2038 CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR = 2039 CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR = 2040 CR_SHARED_MEMORY_CONNECT_MAP_ERROR = 2041 CR_SHARED_MEMORY_FILE_MAP_ERROR = 2042 CR_SHARED_MEMORY_MAP_ERROR = 2043 CR_SHARED_MEMORY_EVENT_ERROR = 2044 CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR = 2045 CR_SHARED_MEMORY_CONNECT_SET_ERROR = 2046 CR_CONN_UNKNOW_PROTOCOL = 2047 CR_INVALID_CONN_HANDLE = 2048 CR_SECURE_AUTH = 2049 CR_FETCH_CANCELED = 2050 CR_NO_DATA = 2051 CR_NO_STMT_METADATA = 2052 CR_NO_RESULT_SET = 2053 CR_NOT_IMPLEMENTED = 2054 CR_SERVER_LOST_EXTENDED = 2055 CR_STMT_CLOSED = 2056 CR_NEW_STMT_METADATA = 2057 CR_ALREADY_CONNECTED = 2058 CR_AUTH_PLUGIN_CANNOT_LOAD = 2059 CR_DUPLICATE_CONNECTION_ATTR = 2060 CR_AUTH_PLUGIN_ERR = 2061 # End MySQL Errors mysql-connector-python-1.1.6/python3/mysql/connector/dbapi.py0000644001577100000120000000431612276514013023642 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ This module implements some constructors and singletons as required by the DB API v2.0 (PEP-249). """ # Python Db API v2 apilevel = '2.0' threadsafety = 1 paramstyle = 'pyformat' import time import datetime from mysql.connector import constants class _DBAPITypeObject: def __init__(self, *values): self.values = values def __cmp__(self, other): if other in self.values: return 0 if other < self.values: return 1 else: return -1 Date = datetime.date Time = datetime.time Timestamp = datetime.datetime def DateFromTicks(ticks): return Date(*time.localtime(ticks)[:3]) def TimeFromTicks(ticks): return Time(*time.localtime(ticks)[3:6]) def TimestampFromTicks(ticks): return Timestamp(*time.localtime(ticks)[:6]) Binary = bytes STRING = _DBAPITypeObject(constants.FieldType.get_string_types()) BINARY = _DBAPITypeObject(constants.FieldType.get_binary_types()) NUMBER = _DBAPITypeObject(constants.FieldType.get_number_types()) DATETIME = _DBAPITypeObject(constants.FieldType.get_timestamp_types()) ROWID = _DBAPITypeObject() mysql-connector-python-1.1.6/python3/mysql/connector/locales/0000755001577100000120000000000012276514327023637 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/connector/locales/eng/0000755001577100000120000000000012276514327024410 5ustar pb2userwheelmysql-connector-python-1.1.6/python3/mysql/connector/locales/eng/client_error.py0000644001577100000120000001346712276514013027454 0ustar pb2userwheel# -*- coding: utf-8 -*- # MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This file was auto-generated. _GENERATED_ON = '2013-10-04' _MYSQL_VERSION = (5, 7, 2) # Start MySQL Error messages CR_UNKNOWN_ERROR = "Unknown MySQL error" CR_SOCKET_CREATE_ERROR = "Can't create UNIX socket (%s)" CR_CONNECTION_ERROR = "Can't connect to local MySQL server through socket '%-.100s' (%s)" CR_CONN_HOST_ERROR = "Can't connect to MySQL server on '%-.100s' (%s)" CR_IPSOCK_ERROR = "Can't create TCP/IP socket (%s)" CR_UNKNOWN_HOST = "Unknown MySQL server host '%-.100s' (%s)" CR_SERVER_GONE_ERROR = "MySQL server has gone away" CR_VERSION_ERROR = "Protocol mismatch; server version = %s, client version = %s" CR_OUT_OF_MEMORY = "MySQL client ran out of memory" CR_WRONG_HOST_INFO = "Wrong host info" CR_LOCALHOST_CONNECTION = "Localhost via UNIX socket" CR_TCP_CONNECTION = "%-.100s via TCP/IP" CR_SERVER_HANDSHAKE_ERR = "Error in server handshake" CR_SERVER_LOST = "Lost connection to MySQL server during query" CR_COMMANDS_OUT_OF_SYNC = "Commands out of sync; you can't run this command now" CR_NAMEDPIPE_CONNECTION = "Named pipe: %-.32s" CR_NAMEDPIPEWAIT_ERROR = "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%s)" CR_NAMEDPIPEOPEN_ERROR = "Can't open named pipe to host: %-.64s pipe: %-.32s (%s)" CR_NAMEDPIPESETSTATE_ERROR = "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%s)" CR_CANT_READ_CHARSET = "Can't initialize character set %-.32s (path: %-.100s)" CR_NET_PACKET_TOO_LARGE = "Got packet bigger than 'max_allowed_packet' bytes" CR_EMBEDDED_CONNECTION = "Embedded server" CR_PROBE_SLAVE_STATUS = "Error on SHOW SLAVE STATUS:" CR_PROBE_SLAVE_HOSTS = "Error on SHOW SLAVE HOSTS:" CR_PROBE_SLAVE_CONNECT = "Error connecting to slave:" CR_PROBE_MASTER_CONNECT = "Error connecting to master:" CR_SSL_CONNECTION_ERROR = "SSL connection error: %-.100s" CR_MALFORMED_PACKET = "Malformed packet" CR_WRONG_LICENSE = "This client library is licensed only for use with MySQL servers having '%s' license" CR_NULL_POINTER = "Invalid use of null pointer" CR_NO_PREPARE_STMT = "Statement not prepared" CR_PARAMS_NOT_BOUND = "No data supplied for parameters in prepared statement" CR_DATA_TRUNCATED = "Data truncated" CR_NO_PARAMETERS_EXISTS = "No parameters exist in the statement" CR_INVALID_PARAMETER_NO = "Invalid parameter number" CR_INVALID_BUFFER_USE = "Can't send long data for non-string/non-binary data types (parameter: %s)" CR_UNSUPPORTED_PARAM_TYPE = "Using unsupported buffer type: %s (parameter: %s)" CR_SHARED_MEMORY_CONNECTION = "Shared memory: %-.100s" CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR = "Can't open shared memory; client could not create request event (%s)" CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR = "Can't open shared memory; no answer event received from server (%s)" CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR = "Can't open shared memory; server could not allocate file mapping (%s)" CR_SHARED_MEMORY_CONNECT_MAP_ERROR = "Can't open shared memory; server could not get pointer to file mapping (%s)" CR_SHARED_MEMORY_FILE_MAP_ERROR = "Can't open shared memory; client could not allocate file mapping (%s)" CR_SHARED_MEMORY_MAP_ERROR = "Can't open shared memory; client could not get pointer to file mapping (%s)" CR_SHARED_MEMORY_EVENT_ERROR = "Can't open shared memory; client could not create %s event (%s)" CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR = "Can't open shared memory; no answer from server (%s)" CR_SHARED_MEMORY_CONNECT_SET_ERROR = "Can't open shared memory; cannot send request event to server (%s)" CR_CONN_UNKNOW_PROTOCOL = "Wrong or unknown protocol" CR_INVALID_CONN_HANDLE = "Invalid connection handle" CR_SECURE_AUTH = "Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)" CR_FETCH_CANCELED = "Row retrieval was canceled by mysql_stmt_close() call" CR_NO_DATA = "Attempt to read column without prior row fetch" CR_NO_STMT_METADATA = "Prepared statement contains no metadata" CR_NO_RESULT_SET = "Attempt to read a row while there is no result set associated with the statement" CR_NOT_IMPLEMENTED = "This feature is not implemented yet" CR_SERVER_LOST_EXTENDED = "Lost connection to MySQL server at '%s', system error: %s" CR_STMT_CLOSED = "Statement closed indirectly because of a preceeding %s() call" CR_NEW_STMT_METADATA = "The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again" CR_ALREADY_CONNECTED = "This handle is already connected. Use a separate handle for each connection." CR_AUTH_PLUGIN_CANNOT_LOAD = "Authentication plugin '%s' cannot be loaded: %s" CR_DUPLICATE_CONNECTION_ATTR = "There is an attribute with the same name already" CR_AUTH_PLUGIN_ERR = "Authentication plugin '%s' reported error: %s" # End MySQL Error messages mysql-connector-python-1.1.6/python3/mysql/connector/locales/eng/__init__.py0000644001577100000120000000220112276514013026504 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """English Content """ mysql-connector-python-1.1.6/python3/mysql/connector/locales/__init__.py0000644001577100000120000000461612276514013025747 0ustar pb2userwheel# MySQL Connector/Python - MySQL driver written in Python. # Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # MySQL Connector/Python is licensed under the terms of the GPLv2 # , like most # MySQL Connectors. There are special exceptions to the terms and # conditions of the GPLv2 as it is applied to this software, see the # FOSS License Exception # . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Translations """ __all__ = [ 'get_client_error' ] from .. import errorcode def get_client_error(error, language='eng'): """Lookup client error This function will lookup the client error message based on the given error and return the error message. If the error was not found, None will be returned. Error can be either an integer or a string. For example: error: 2000 error: CR_UNKNOWN_ERROR The language attribute can be used to retrieve a localized message, when available. Returns a string or None. """ try: tmp = __import__('mysql.connector.locales.{}'.format(language), globals(), locals(), ['client_error']) except ImportError: raise ImportError("No localization support for language '{}'".format( language)) client_error = tmp.client_error if isinstance(error, int): errno = error for key, value in errorcode.__dict__.items(): if value == errno: error = key break if isinstance(error, (str)): try: return getattr(client_error, error) except AttributeError: return None raise ValueError("error argument needs to be either an integer or string")