From 8056006f067f98cffcbdc274a1c7921f00a67ab9 Mon Sep 17 00:00:00 2001 From: Michael Trier Date: Thu, 25 Feb 2010 10:07:59 +0000 Subject: [PATCH] Support for the mysql+oursql dialect. Thank you Taavi Burns. --- lib/sqlalchemy/dialects/mysql/base.py | 9 ++++-- lib/sqlalchemy/dialects/mysql/oursql.py | 42 ++++++++++++++++++++++--- test/engine/test_reflection.py | 1 - test/orm/test_query.py | 2 +- test/sql/test_types.py | 3 ++ 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index e3d06972fd..1a9e57ee77 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -281,13 +281,18 @@ class _StringType(sqltypes.String): """Base for MySQL string types.""" def __init__(self, charset=None, collation=None, - ascii=False, unicode=False, binary=False, + ascii=False, binary=False, national=False, **kw): self.charset = charset # allow collate= or collation= self.collation = kw.pop('collate', collation) self.ascii = ascii - self.unicode = unicode + # We have to munge the 'unicode' param strictly as a dict + # otherwise 2to3 will turn it into str. + self.__dict__['unicode'] = kw.get('unicode', False) + # sqltypes.String does not accept the 'unicode' arg at all. + if 'unicode' in kw: + del kw['unicode'] self.binary = binary self.national = national super(_StringType, self).__init__(**kw) diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py index 1fca6850a1..87a5094935 100644 --- a/lib/sqlalchemy/dialects/mysql/oursql.py +++ b/lib/sqlalchemy/dialects/mysql/oursql.py @@ -55,6 +55,8 @@ class MySQL_oursqlExecutionContext(MySQLExecutionContext): class MySQL_oursql(MySQLDialect): driver = 'oursql' +# Py3K +# description_encoding = None supports_unicode_statements = True supports_unicode_binds = True supports_sane_rowcount = True @@ -77,6 +79,19 @@ class MySQL_oursql(MySQLDialect): def do_execute(self, cursor, statement, parameters, context=None): """Provide an implementation of *cursor.execute(statement, parameters)*.""" +# Py3K +# if context is not None: +# charset = self._detect_charset(context.connection) +# if charset is not None: +# statement = statement.encode(charset) +# encoded_parameters = [] +# for p in parameters: +# if isinstance(p, str): +# encoded_parameters.append(p.encode(charset)) +# else: +# encoded_parameters.append(p) +# parameters = encoded_parameters + if context and context.plain_query: cursor.execute(statement, plain_query=True) else: @@ -86,7 +101,13 @@ class MySQL_oursql(MySQLDialect): connection.cursor().execute('BEGIN', plain_query=True) def _xa_query(self, connection, query, xid): - connection.execution_options(_oursql_plain_query=True).execute(query % connection.connection._escape_string(xid)) +# Py2K + arg = connection.connection._escape_string(xid) +# end Py2K +# Py3K +# charset = connection.connection.charset +# arg = connection.connection._escape_string(xid.encode(charset)).decode(charset) + connection.execution_options(_oursql_plain_query=True).execute(query % arg) # Because mysql is bad, these methods have to be reimplemented to use _PlainQuery. Basically, some queries # refuse to return any data if they're run through the parameterized query API, or refuse to be parameterized @@ -115,13 +136,18 @@ class MySQL_oursql(MySQLDialect): def _show_create_table(self, connection, table, charset=None, full_name=None): - return MySQLDialect._show_create_table(self, + sql = MySQLDialect._show_create_table(self, connection.contextual_connect(close_with_result=True).execution_options(_oursql_plain_query=True), table, charset, full_name) +# Py3K +# charset = self._detect_charset(connection) +# if charset is not None: +# sql = sql.decode(charset) + return sql def is_disconnect(self, e): if isinstance(e, self.dbapi.ProgrammingError): # if underlying connection is closed, this is the error you get - return e.errno is None and e[1].endswith('closed') + return e.errno is None and e.args[1].endswith('closed') else: return e.errno in (2006, 2013, 2014, 2045, 2055) @@ -139,6 +165,7 @@ class MySQL_oursql(MySQLDialect): opts['charset'] = None else: util.coerce_kw_type(opts, 'charset', str) + opts['use_unicode'] = opts.get('use_unicode', True) util.coerce_kw_type(opts, 'use_unicode', bool) # FOUND_ROWS must be set in CLIENT_FLAGS to enable @@ -166,7 +193,14 @@ class MySQL_oursql(MySQLDialect): def _detect_charset(self, connection): """Sniff out the character set in use for connection results.""" - return connection.connection.charset + if hasattr(connection, 'connection'): + if hasattr(connection.connection, 'use_unicode') and connection.connection.use_unicode: + return None + else: + return connection.connection.charset + else: + return None + def _compat_fetchall(self, rp, charset=None): """oursql isn't super-broken like MySQLdb, yaaay.""" diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index 1582c86e4a..5d3f0ca86c 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -1203,7 +1203,6 @@ class ComponentReflectionTest(TestBase): # so there may be more indexes than expected. insp = Inspector(meta.bind) indexes = insp.get_indexes('users', schema=schema) - indexes.sort() expected_indexes = [ {'unique': False, 'column_names': ['test1', 'test2'], diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 51db26925e..1bc24a2eed 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -167,7 +167,7 @@ class GetTest(QueryTest): try: metadata.create_all() # Py3K - #ustring = 'petit voix m\xe2\x80\x99a' + #ustring = b'petit voix m\xe2\x80\x99a'.decode('utf-8') # Py2K ustring = 'petit voix m\xe2\x80\x99a'.decode('utf-8') # end Py2K diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 2a17c72186..27ee8709f8 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -467,6 +467,9 @@ class UnicodeTest(TestBase, AssertsExecutionResults): # the row that we put in was stored as hexlified ascii row = engine.execute(utf8_table.select()).first() x = row['plain_varchar_no_coding_error'] + connect_opts = engine.dialect.create_connect_args(testing.db.url)[1] + if connect_opts.get('use_unicode', False): + x = x.encode('utf-8') a = hexlify(x) b = hexlify(asciidata) eq_(a, b) -- 2.47.3