[Sqlalchemy-commits] sqlalchemy: - introduce an optimizing type _NativeUnicodeMixin t...
Brought to you by:
zzzeek
From: <co...@sq...> - 2010-03-12 18:32:32
|
details: http://hg.sqlalchemy.org/sqlalchemy/rev/27e2d25a0e78 changeset: 6203:27e2d25a0e78 user: zzzeek date: Fri Mar 12 18:30:38 2010 +0000 description: - introduce an optimizing type _NativeUnicodeMixin to oracle plus supporting changes to Enum/SchemaType to re-support adaptation of string types. This approach can be adapted by "conditional" unicode returning dialects (i.e. pyodbc and possibly mxodbc) to remove the overhead of isinstance(value, unicode) calls when the dialect returned type is of dbapi.UNICODE, dbapi.NVARCHAR, etc. diffstat: lib/sqlalchemy/dialects/oracle/cx_oracle.py | 26 ++++++++++++++++++-------- lib/sqlalchemy/types.py | 20 ++++++++++++-------- test/dialect/test_oracle.py | 6 +++--- test/sql/test_query.py | 3 +-- test/sql/test_types.py | 4 +++- 5 files changed, 37 insertions(+), 22 deletions(-) diffs (177 lines): diff -r dd0d7264778b -r 27e2d25a0e78 lib/sqlalchemy/dialects/oracle/cx_oracle.py --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py Thu Mar 11 22:38:15 2010 -0500 +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py Fri Mar 12 18:30:38 2010 +0000 @@ -115,24 +115,33 @@ return value return process -class _OracleChar(sqltypes.CHAR): +class _NativeUnicodeMixin(object): + def result_processor(self, dialect, coltype): + # if we know cx_Oracle will return unicode, + # don't process results + if self.convert_unicode != 'force' and \ + dialect._cx_oracle_native_nvarchar and \ + coltype == dialect.dbapi.UNICODE: + return None + else: + return super(_NativeUnicodeMixin, self).result_processor(dialect, coltype) + +class _OracleChar(_NativeUnicodeMixin, sqltypes.CHAR): def get_dbapi_type(self, dbapi): return dbapi.FIXED_CHAR -class _OracleNVarChar(sqltypes.NVARCHAR): +class _OracleNVarChar(_NativeUnicodeMixin, sqltypes.NVARCHAR): def get_dbapi_type(self, dbapi): return dbapi.UNICODE - def result_processor(self, dialect, coltype): - if dialect._cx_oracle_native_nvarchar: - return None - else: - return sqltypes.NVARCHAR.result_processor(self, dialect, coltype) class _OracleText(_LOBMixin, sqltypes.Text): def get_dbapi_type(self, dbapi): return dbapi.CLOB -class _OracleUnicodeText(sqltypes.UnicodeText): +class _OracleString(_NativeUnicodeMixin, sqltypes.String): + pass + +class _OracleUnicodeText(_NativeUnicodeMixin, sqltypes.UnicodeText): def get_dbapi_type(self, dbapi): return dbapi.NCLOB @@ -184,6 +193,7 @@ sqltypes.Interval : _OracleInterval, oracle.INTERVAL : _OracleInterval, sqltypes.Text : _OracleText, + sqltypes.String : _OracleString, sqltypes.UnicodeText : _OracleUnicodeText, sqltypes.CHAR : _OracleChar, sqltypes.Integer : _OracleInteger, # this is only needed for OUT parameters. diff -r dd0d7264778b -r 27e2d25a0e78 lib/sqlalchemy/types.py --- a/lib/sqlalchemy/types.py Thu Mar 11 22:38:15 2010 -0500 +++ b/lib/sqlalchemy/types.py Fri Mar 12 18:30:38 2010 +0000 @@ -653,6 +653,7 @@ return impltype( length=self.length, convert_unicode=self.convert_unicode, + unicode_error=self.unicode_error, _warn_on_bytestring=True, ) @@ -690,7 +691,7 @@ needs_convert = wants_unicode and \ (dialect.returns_unicode_strings is not True or self.convert_unicode == 'force') - + if needs_convert: to_unicode = processors.to_unicode_processor_factory( dialect.encoding, self.unicode_error) @@ -1216,7 +1217,7 @@ if bind is None: bind = _bind_or_error(self) t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t.create(bind=bind, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=False): @@ -1226,27 +1227,27 @@ if bind is None: bind = _bind_or_error(self) t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t.drop(bind=bind, checkfirst=checkfirst) def _on_table_create(self, event, target, bind, **kw): t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t._on_table_create(event, target, bind, **kw) def _on_table_drop(self, event, target, bind, **kw): t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t._on_table_drop(event, target, bind, **kw) def _on_metadata_create(self, event, target, bind, **kw): t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t._on_metadata_create(event, target, bind, **kw) def _on_metadata_drop(self, event, target, bind, **kw): t = self.dialect_impl(bind.dialect) - if t is not self: + if t is not self and isinstance(t, SchemaType): t._on_metadata_drop(event, target, bind, **kw) class Enum(String, SchemaType): @@ -1341,13 +1342,16 @@ table.append_constraint(e) def adapt(self, impltype): - return impltype(name=self.name, + if issubclass(impltype, Enum): + return impltype(name=self.name, quote=self.quote, schema=self.schema, metadata=self.metadata, convert_unicode=self.convert_unicode, *self.enums ) + else: + return super(Enum, self).adapt(impltype) class PickleType(MutableType, TypeDecorator): """Holds Python objects. diff -r dd0d7264778b -r 27e2d25a0e78 test/dialect/test_oracle.py --- a/test/dialect/test_oracle.py Thu Mar 11 22:38:15 2010 -0500 +++ b/test/dialect/test_oracle.py Fri Mar 12 18:30:38 2010 +0000 @@ -459,10 +459,10 @@ (Date(), cx_oracle._OracleDate), (oracle.OracleRaw(), cx_oracle._OracleRaw), (String(), String), - (VARCHAR(), VARCHAR), + (VARCHAR(), cx_oracle._OracleString), (DATE(), DATE), - (String(50), String), - (Unicode(), Unicode), + (String(50), cx_oracle._OracleString), + (Unicode(), cx_oracle._OracleNVarChar), (Text(), cx_oracle._OracleText), (UnicodeText(), cx_oracle._OracleUnicodeText), (NCHAR(), cx_oracle._OracleNVarChar), diff -r dd0d7264778b -r 27e2d25a0e78 test/sql/test_query.py --- a/test/sql/test_query.py Thu Mar 11 22:38:15 2010 -0500 +++ b/test/sql/test_query.py Fri Mar 12 18:30:38 2010 +0000 @@ -770,8 +770,7 @@ @testing.emits_warning('.*empty sequence.*') @testing.fails_on('firebird', "kinterbasdb doesn't send full type information") @testing.fails_if(lambda: - (testing.db.name, testing.db.driver) == ('mssql', 'pyodbc') - and not testing.db.dialect.freetds, + testing.against('mssql+pyodbc') and not testing.db.dialect.freetds, "not supported by Windows ODBC driver") def test_bind_in(self): users.insert().execute(user_id = 7, user_name = 'jack') diff -r dd0d7264778b -r 27e2d25a0e78 test/sql/test_types.py --- a/test/sql/test_types.py Thu Mar 11 22:38:15 2010 -0500 +++ b/test/sql/test_types.py Fri Mar 12 18:30:38 2010 +0000 @@ -312,7 +312,9 @@ def test_native_unicode(self): """assert expected values for 'native unicode' mode""" - if testing.against('mssql+pyodbc') and not testing.db.dialect.freetds: + if \ + (testing.against('mssql+pyodbc') and not testing.db.dialect.freetds) or \ + testing.against('oracle+cx_oracle'): assert testing.db.dialect.returns_unicode_strings == 'conditional' return |