summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-03-07 12:36:35 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-03-07 12:36:35 -0500
commita98bb5f0cd5d7ef51dbf0f04cc2ba1971768691f (patch)
treeb6a1dea1efe8f521500fe6c2e86c1099bcb8166e
parent029b79052cae9a74c9b4dceea92d8ec00595f175 (diff)
parent50cc82b7966f70aeb8c21d881be4ca2b3327f7bf (diff)
downloadsqlalchemy-a98bb5f0cd5d7ef51dbf0f04cc2ba1971768691f.tar.gz
Merged in nakagami/sqlalchemy/cymysql (pull request #42)
cymysql support
-rw-r--r--lib/sqlalchemy/dialects/mysql/__init__.py2
-rw-r--r--lib/sqlalchemy/dialects/mysql/cymysql.py72
-rw-r--r--lib/sqlalchemy/testing/engines.py2
-rw-r--r--test/dialect/test_mysql.py1
-rw-r--r--test/engine/test_execute.py4
-rw-r--r--test/engine/test_reconnect.py3
-rw-r--r--test/engine/test_transaction.py1
-rw-r--r--test/requirements.py4
-rw-r--r--test/sql/test_types.py10
9 files changed, 94 insertions, 5 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/__init__.py b/lib/sqlalchemy/dialects/mysql/__init__.py
index 1f7046410..2bb636ff3 100644
--- a/lib/sqlalchemy/dialects/mysql/__init__.py
+++ b/lib/sqlalchemy/dialects/mysql/__init__.py
@@ -6,7 +6,7 @@
from . import base, mysqldb, oursql, \
pyodbc, zxjdbc, mysqlconnector, pymysql,\
- gaerdbms
+ gaerdbms, cymysql
# default dialect
base.dialect = mysqldb.dialect
diff --git a/lib/sqlalchemy/dialects/mysql/cymysql.py b/lib/sqlalchemy/dialects/mysql/cymysql.py
new file mode 100644
index 000000000..d9b43869c
--- /dev/null
+++ b/lib/sqlalchemy/dialects/mysql/cymysql.py
@@ -0,0 +1,72 @@
+# mysql/cymysql.py
+# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
+#
+# This module is part of SQLAlchemy and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+
+"""
+
+.. dialect:: mysql+cymysql
+ :name: CyMySQL
+ :dbapi: cymysql
+ :connectstring: mysql+cymysql://<username>:<password>@<host>/<dbname>[?<options>]
+ :url: https://github.com/nakagami/CyMySQL
+
+"""
+
+from .mysqldb import MySQLDialect_mysqldb
+from .base import (BIT, MySQLDialect)
+from ... import util
+
+class _cymysqlBIT(BIT):
+ def result_processor(self, dialect, coltype):
+ """Convert a MySQL's 64 bit, variable length binary string to a long.
+ """
+
+ def process(value):
+ if value is not None:
+ # Py2K
+ v = 0L
+ for i in map(ord, value):
+ v = v << 8 | i
+ # end Py2K
+ # Py3K
+ #v = 0
+ #for i in value:
+ # v = v << 8 | i
+ return v
+ return value
+ return process
+
+
+class MySQLDialect_cymysql(MySQLDialect_mysqldb):
+ driver = 'cymysql'
+
+ description_encoding = None
+
+ colspecs = util.update_copy(
+ MySQLDialect.colspecs,
+ {
+ BIT: _cymysqlBIT,
+ }
+ )
+
+ @classmethod
+ def dbapi(cls):
+ return __import__('cymysql')
+
+ def _extract_error_code(self, exception):
+ return exception.errno
+
+ def is_disconnect(self, e, connection, cursor):
+ if isinstance(e, self.dbapi.OperationalError):
+ return self._extract_error_code(e) in \
+ (2006, 2013, 2014, 2045, 2055)
+ elif isinstance(e, self.dbapi.InterfaceError):
+ # if underlying connection is closed,
+ # this is the error you get
+ return True
+ else:
+ return False
+
+dialect = MySQLDialect_cymysql
diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py
index 20bcf0317..26f561016 100644
--- a/lib/sqlalchemy/testing/engines.py
+++ b/lib/sqlalchemy/testing/engines.py
@@ -229,7 +229,7 @@ def utf8_engine(url=None, options=None):
from sqlalchemy.engine import url as engine_url
if config.db.dialect.name == 'mysql' and \
- config.db.driver in ['mysqldb', 'pymysql']:
+ config.db.driver in ['mysqldb', 'pymysql', 'cymysql']:
# note 1.2.1.gamma.6 or greater of MySQLdb
# needed here
url = url or config.db_url
diff --git a/test/dialect/test_mysql.py b/test/dialect/test_mysql.py
index d5ce6e923..f89b0b229 100644
--- a/test/dialect/test_mysql.py
+++ b/test/dialect/test_mysql.py
@@ -1500,6 +1500,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL):
@testing.fails_on('mysql+mysqldb', 'uses format')
@testing.fails_on('mysql+pymysql', 'uses format')
+ @testing.fails_on('mysql+cymysql', 'uses format')
@testing.fails_on('mysql+oursql', 'uses format')
@testing.fails_on('mysql+pyodbc', 'uses format')
@testing.fails_on('mysql+zxjdbc', 'uses format')
diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py
index 447324d6e..203d7bd71 100644
--- a/test/engine/test_execute.py
+++ b/test/engine/test_execute.py
@@ -110,7 +110,7 @@ class ExecuteTest(fixtures.TestBase):
# some psycopg2 versions bomb this.
@testing.fails_on_everything_except('mysql+mysqldb', 'mysql+pymysql',
- 'mysql+mysqlconnector', 'postgresql')
+ 'mysql+cymysql', 'mysql+mysqlconnector', 'postgresql')
@testing.fails_on('postgresql+zxjdbc', 'sprintf not supported')
def test_raw_sprintf(self):
def go(conn):
@@ -157,7 +157,7 @@ class ExecuteTest(fixtures.TestBase):
'db-api flaky')
@testing.fails_on_everything_except('postgresql+psycopg2',
'postgresql+pypostgresql', 'mysql+mysqlconnector',
- 'mysql+pymysql')
+ 'mysql+pymysql', 'mysql+cymysql')
def test_raw_python(self):
def go(conn):
conn.execute('insert into users (user_id, user_name) '
diff --git a/test/engine/test_reconnect.py b/test/engine/test_reconnect.py
index 6416ce149..6b283654b 100644
--- a/test/engine/test_reconnect.py
+++ b/test/engine/test_reconnect.py
@@ -487,6 +487,9 @@ class InvalidateDuringResultTest(fixtures.TestBase):
meta.drop_all()
engine.dispose()
+ @testing.fails_on('+cymysql',
+ "Buffers the result set and doesn't check for "
+ "connection close")
@testing.fails_on('+pymysql',
"Buffers the result set and doesn't check for "
"connection close")
diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py
index ad6813f87..5558ff778 100644
--- a/test/engine/test_transaction.py
+++ b/test/engine/test_transaction.py
@@ -29,6 +29,7 @@ class TransactionTest(fixtures.TestBase):
testing.db.execute(users.delete()).close()
@classmethod
+ @testing.crashes('mysql+cymysql', 'deadlock')
def teardown_class(cls):
users.drop(testing.db)
diff --git a/test/requirements.py b/test/requirements.py
index 738429158..c20bcbd0a 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -378,6 +378,7 @@ class DefaultRequirements(SuiteRequirements):
"""
return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql',
'sqlite+pysqlite', 'mysql+pymysql',
+ 'mysql+cymysql',
'sybase', 'mssql+pyodbc', 'mssql+mxodbc')
@property
@@ -393,7 +394,8 @@ class DefaultRequirements(SuiteRequirements):
"""
return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql',
- 'sqlite+pysqlite', 'mysql+pymysql')
+ 'sqlite+pysqlite', 'mysql+pymysql',
+ 'mysql+cymysql')
@property
def sane_multi_rowcount(self):
diff --git a/test/sql/test_types.py b/test/sql/test_types.py
index 0e6f1b5f0..3c981e539 100644
--- a/test/sql/test_types.py
+++ b/test/sql/test_types.py
@@ -690,6 +690,16 @@ class UnicodeTest(fixtures.TestBase):
('charset' in testing.db.url.query)
)
+ elif testing.against('mysql+cymysql'):
+ eq_(
+ testing.db.dialect.returns_unicode_strings,
+ # Py3K
+ #True
+ # Py2K
+ False
+ # end Py2K
+ )
+
else:
expected = (testing.db.name, testing.db.driver) in \
(