summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-10-03 15:25:47 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2011-10-03 15:25:47 -0400
commit88f345aa0ab05ac4d35ecf6048e7badc52ff80f7 (patch)
tree20f1f71f0af3c6ae12fad404d12516403499fcf2
parent290064ab235b4ce30b84394db5219f74b69736ea (diff)
downloadsqlalchemy-88f345aa0ab05ac4d35ecf6048e7badc52ff80f7.tar.gz
- a CREATE TABLE will put the COLLATE option
after CHARSET, which appears to be part of MySQL's arbitrary rules regarding if it will actually work or not. [ticket:2225]
-rw-r--r--CHANGES5
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py50
-rw-r--r--test/dialect/test_mysql.py15
3 files changed, 50 insertions, 20 deletions
diff --git a/CHANGES b/CHANGES
index 6d27cc2e8..e7f399261 100644
--- a/CHANGES
+++ b/CHANGES
@@ -89,6 +89,11 @@ CHANGES
quote symbol "'" for XA commands instead
of '"'. [ticket:2186].
+ - a CREATE TABLE will put the COLLATE option
+ after CHARSET, which appears to be part of
+ MySQL's arbitrary rules regarding if it will actually
+ work or not. [ticket:2225]
+
- oracle
- Added ORA-00028 to disconnect codes, use
cx_oracle _Error.code to get at the code,
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 740b4937d..b2d025bdd 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -174,7 +174,7 @@ from array import array as _array
from sqlalchemy.engine import reflection
from sqlalchemy.engine import base as engine_base, default
from sqlalchemy import types as sqltypes
-
+from sqlalchemy import topological
from sqlalchemy.types import DATE, DATETIME, BOOLEAN, TIME, \
BLOB, BINARY, VARBINARY
@@ -1310,25 +1310,35 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
"""Build table-level CREATE options like ENGINE and COLLATE."""
table_opts = []
- for k in table.kwargs:
- if k.startswith('mysql_'):
- opt = k[6:].upper()
-
- arg = table.kwargs[k]
- if opt in _options_of_type_string:
- arg = "'%s'" % arg.replace("\\", "\\\\").replace("'", "''")
-
- if opt in ('DATA_DIRECTORY', 'INDEX_DIRECTORY',
- 'DEFAULT_CHARACTER_SET', 'CHARACTER_SET', 'DEFAULT_CHARSET',
- 'DEFAULT_COLLATE'):
- opt = opt.replace('_', ' ')
-
- joiner = '='
- if opt in ('TABLESPACE', 'DEFAULT CHARACTER SET',
- 'CHARACTER SET', 'COLLATE'):
- joiner = ' '
-
- table_opts.append(joiner.join((opt, arg)))
+ opts = dict(
+ (
+ k[len(self.dialect.name)+1:].upper(),
+ v
+ )
+ for k, v in table.kwargs.items()
+ if k.startswith('%s_' % self.dialect.name)
+ )
+
+ for opt in topological.sort([
+ ('DEFAULT_CHARSET', 'COLLATE'),
+ ('DEFAULT_CHARACTER_SET', 'COLLATE')
+ ], opts):
+ arg = opts[opt]
+ if opt in _options_of_type_string:
+ arg = "'%s'" % arg.replace("\\", "\\\\").replace("'", "''")
+
+ if opt in ('DATA_DIRECTORY', 'INDEX_DIRECTORY',
+ 'DEFAULT_CHARACTER_SET', 'CHARACTER_SET',
+ 'DEFAULT_CHARSET',
+ 'DEFAULT_COLLATE'):
+ opt = opt.replace('_', ' ')
+
+ joiner = '='
+ if opt in ('TABLESPACE', 'DEFAULT CHARACTER SET',
+ 'CHARACTER SET', 'COLLATE'):
+ joiner = ' '
+
+ table_opts.append(joiner.join((opt, arg)))
return ' '.join(table_opts)
def visit_drop_index(self, drop):
diff --git a/test/dialect/test_mysql.py b/test/dialect/test_mysql.py
index f1601bbc1..1e4d19d9c 100644
--- a/test/dialect/test_mysql.py
+++ b/test/dialect/test_mysql.py
@@ -334,6 +334,21 @@ class TypesTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL):
charset_table.drop()
@testing.exclude('mysql', '<', (5, 0, 5), 'a 5.0+ feature')
+ @testing.provide_metadata
+ def test_charset_collate_table(self):
+ t = Table('foo', metadata,
+ Column('id', Integer),
+ mysql_default_charset='utf8',
+ mysql_collate='utf8_unicode_ci'
+ )
+ t.create()
+ m2 = MetaData(testing.db)
+ t2 = Table('foo', m2, autoload=True)
+ eq_(t2.kwargs['mysql_collate'], 'utf8_unicode_ci')
+ # note we changed this to have an _ in 0.7.3
+ eq_(t2.kwargs['mysql_default charset'], 'utf8')
+
+ @testing.exclude('mysql', '<', (5, 0, 5), 'a 5.0+ feature')
@testing.fails_on('mysql+oursql', 'some round trips fail, oursql bug ?')
def test_bit_50(self):
"""Exercise BIT types on 5.0+ (not valid for all engine types)"""