From: Christoph Zwerschke Date: Thu, 27 Feb 2014 20:15:21 +0000 (+0100) Subject: Restore coercion to unicode with cx_Oracle. X-Git-Tag: rel_0_9_4~78^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4dede6e7c1420aacc54c9c326bf3a834dff45c7;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Restore coercion to unicode with cx_Oracle. This feature is now turned off by default. --- diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 9a632cb0a6..0e9d7175e7 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -70,7 +70,12 @@ unicode by using outputtypehandlers, SQLAlchemy has observed that usage of a unicode-converting outputtypehandler in Python 2 (not Python 3) incurs significant performance overhead for all statements that deliver string results, whether or not values contain non-ASCII characters. For this reason, -SQLAlchemy as of 0.9.2 does not use cx_Oracle's outputtypehandlers for unicode conversion. +SQLAlchemy as of 0.9.2 does not use cx_Oracle's outputtypehandlers for unicode +conversion by default. If you want to use this feature anyway, you can enable +it by passing the flag ``coerce_to_unicode=True`` to :func:`.create_engine`:: + + engine = create_engine("oracle+cx_oracle://dsn", + coerce_to_unicode=True) Keeping in mind that any NVARCHAR or NCLOB type is returned as Python unicode unconditionally, in order for VARCHAR values to be returned as Python unicode @@ -90,6 +95,9 @@ SQL statement, use :func:`.text`:: performance bottleneck. SQLAlchemy's own unicode facilities are used instead. +.. versionadded:: 0.9.4 + Add the ``coerce_to_unicode`` flag. + .. _cx_oracle_returning: RETURNING Support @@ -602,6 +610,7 @@ class OracleDialect_cx_oracle(OracleDialect): threaded=True, allow_twophase=True, coerce_to_decimal=True, + coerce_to_unicode=False, arraysize=50, **kwargs): OracleDialect.__init__(self, **kwargs) self.threaded = threaded @@ -630,6 +639,11 @@ class OracleDialect_cx_oracle(OracleDialect): self._cx_oracle_binary_types = types("BFILE", "CLOB", "NCLOB", "BLOB") self.supports_unicode_binds = self.cx_oracle_ver >= (5, 0) + self.coerce_to_unicode = ( + self.cx_oracle_ver >= (5, 0) and + coerce_to_unicode + ) + self.supports_native_decimal = ( self.cx_oracle_ver >= (5, 0) and coerce_to_decimal @@ -773,6 +787,10 @@ class OracleDialect_cx_oracle(OracleDialect): 255, outconverter=self._detect_decimal, arraysize=cursor.arraysize) + # allow all strings to come back natively as Unicode + elif self.coerce_to_unicode and \ + defaultType in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR): + return cursor.var(util.text_type, size, cursor.arraysize) def on_connect(conn): conn.outputtypehandler = output_type_handler diff --git a/test/dialect/test_oracle.py b/test/dialect/test_oracle.py index 8d0ff97762..660a2a5e9a 100644 --- a/test/dialect/test_oracle.py +++ b/test/dialect/test_oracle.py @@ -1218,8 +1218,6 @@ class TypesTest(fixtures.TestBase): assert isinstance(row[i], type_), '%r is not %r' \ % (row[i], type_) - - def test_numeric_no_decimal_mode(self): engine = testing_engine(options=dict(coerce_to_decimal=False)) value = engine.scalar("SELECT 5.66 FROM DUAL") @@ -1228,6 +1226,14 @@ class TypesTest(fixtures.TestBase): value = testing.db.scalar("SELECT 5.66 FROM DUAL") assert isinstance(value, decimal.Decimal) + def test_coerce_to_unicode(self): + engine = testing_engine(options=dict(coerce_to_unicode=True)) + value = engine.scalar("SELECT 'hello' FROM DUAL") + assert isinstance(value, util.text_type) + + value = testing.db.scalar("SELECT 'hello' FROM DUAL") + assert isinstance(value, util.binary_type) + @testing.provide_metadata def test_numerics_broken_inspection(self): """Numeric scenarios where Oracle type info is 'broken',