]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Restore coercion to unicode with cx_Oracle.
authorChristoph Zwerschke <cito@online.de>
Thu, 27 Feb 2014 20:15:21 +0000 (21:15 +0100)
committerChristoph Zwerschke <cito@online.de>
Thu, 27 Feb 2014 20:15:21 +0000 (21:15 +0100)
This feature is now turned off by default.

lib/sqlalchemy/dialects/oracle/cx_oracle.py
test/dialect/test_oracle.py

index 9a632cb0a6c3459feeadf4bc01f397df46d787b6..0e9d7175e7ffdeda7ce08d4a58b09e009baf54d1 100644 (file)
@@ -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
index 8d0ff97762bc633131bd6f4ce17060638b90b50b..660a2a5e9a72835c3552228a5c917f0f81558893 100644 (file)
@@ -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',