From 26efe4f6434ebd56851ed4e156f0d0d234b28729 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 12 Aug 2006 19:50:07 +0000 Subject: [PATCH] fixes to types so that database-specific types more easily used; fixes to mysql text types to work with this methodology [ticket:269] --- CHANGES | 3 +++ lib/sqlalchemy/databases/mysql.py | 16 ++++------------ lib/sqlalchemy/types.py | 9 ++++++++- test/engine/reflection.py | 26 +++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 9a0a415d08..43778d4d78 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,9 @@ flexibly correspond to class inheritance [ticket:271] - SelectResults will use a subselect, when calling an aggregate (i.e. max, min, etc.) on a SelectResults that has an ORDER BY clause [ticket:252] +- fixes to types so that database-specific types more easily used; +fixes to mysql text types to work with this methodology +[ticket:269] 0.2.6 - big overhaul to schema to allow truly composite primary and foreign diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index 56f2125ac0..14e26438f2 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -115,28 +115,19 @@ class MSText(sqltypes.TEXT): super(MSText, self).__init__() def get_col_spec(self): return "TEXT" -class MSTinyText(sqltypes.TEXT): - def __init__(self, **kw): - self.binary = 'binary' in kw - super(MSTinyText, self).__init__() +class MSTinyText(MSText): def get_col_spec(self): if self.binary: return "TEXT BINARY" else: return "TEXT" -class MSMediumText(sqltypes.TEXT): - def __init__(self, **kw): - self.binary = 'binary' in kw - super(MSMediumText, self).__init__() +class MSMediumText(MSText): def get_col_spec(self): if self.binary: return "MEDIUMTEXT BINARY" else: return "MEDIUMTEXT" -class MSLongText(sqltypes.TEXT): - def __init__(self, **kw): - self.binary = 'binary' in kw - super(MSLongText, self).__init__() +class MSLongText(MSText): def get_col_spec(self): if self.binary: return "LONGTEXT BINARY" @@ -431,6 +422,7 @@ class MySQLCompiler(ansisql.ANSICompiler): class MySQLSchemaGenerator(ansisql.ANSISchemaGenerator): def get_column_specification(self, column, override_pk=False, first_pk=False): + t = column.type.engine_impl(self.engine) colspec = self.preparer.format_column(column) + " " + column.type.engine_impl(self.engine).get_col_spec() default = self.get_column_default_string(column) if default is not None: diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 5fc75678d2..709c77e5c6 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -37,7 +37,7 @@ class TypeEngine(AbstractType): def dialect_impl(self, dialect): try: return self.impl_dict[dialect] - except: + except KeyError: return self.impl_dict.setdefault(dialect, dialect.type_descriptor(self)) def _get_impl(self): if hasattr(self, '_impl'): @@ -96,6 +96,7 @@ def to_instance(typeobj): def adapt_type(typeobj, colspecs): if isinstance(typeobj, type): typeobj = typeobj() + for t in typeobj.__class__.__mro__[0:-1]: try: impltype = colspecs[t] @@ -105,6 +106,12 @@ def adapt_type(typeobj, colspecs): else: # couldnt adapt...raise exception ? return typeobj + # if we adapted the given generic type to a database-specific type, + # but it turns out the originally given "generic" type + # is actually a subclass of our resulting type, then we were already + # were given a more specific type than that required; so use that. + if (issubclass(typeobj.__class__, impltype)): + return typeobj return typeobj.adapt(impltype) class NullTypeEngine(TypeEngine): diff --git a/test/engine/reflection.py b/test/engine/reflection.py index 52fc2987d6..411e594b5c 100644 --- a/test/engine/reflection.py +++ b/test/engine/reflection.py @@ -5,6 +5,7 @@ import sqlalchemy.ansisql as ansisql from sqlalchemy import * from sqlalchemy.exceptions import NoSuchTableError +import sqlalchemy.databases.mysql as mysql import unittest, re, StringIO @@ -93,7 +94,30 @@ class ReflectionTest(PersistTest): finally: addresses.drop() users.drop() - + + @testbase.supported('mysql') + def testmysqltypes(self): + meta1 = BoundMetaData(testbase.db) + table = Table( + 'mysql_types', meta1, + Column('id', Integer, primary_key=True), + Column('num1', mysql.MSInteger(unsigned=True)), + Column('text1', mysql.MSLongText), + Column('text2', mysql.MSLongText()) + ) + try: + table.create(checkfirst=True) + meta2 = BoundMetaData(testbase.db) + t2 = Table('mysql_types', meta2, autoload=True) + assert isinstance(t2.c.num1.type, mysql.MSInteger) + assert t2.c.num1.type.unsigned + assert isinstance(t2.c.text1.type, mysql.MSLongText) + assert isinstance(t2.c.text2.type, mysql.MSLongText) + t2.drop() + t2.create() + finally: + table.drop(checkfirst=True) + def testmultipk(self): table = Table( 'engine_multi', testbase.db, -- 2.47.2