diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-08-12 15:09:37 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-10-21 14:20:24 -0400 |
| commit | d76cb7213557c24609a1a75d8c391aea0179562a (patch) | |
| tree | 83ff13ecbcb17b779e839671fcc0567b4a85e028 /lib | |
| parent | bb9a55b6416fdd654e85f65b1cef4d86a416b43e (diff) | |
| download | sqlalchemy-d76cb7213557c24609a1a75d8c391aea0179562a.tar.gz | |
Implment encoding_errors for cx_oracle
Added dialect-level flag ``encoding_errors`` to the cx_Oracle dialect,
which can be specified as part of :func:`.create_engine`. This is passed
to SQLAlchemy's unicode decoding converter under Python 2, and to
cx_Oracle's ``cursor.var()`` object as the ``encodingErrors`` parameter
under Python 3, for the very unusual case that broken encodings are present
in the target database which cannot be fetched unless error handling is
relaxed. The value is ultimately one of the Python "encoding errors"
parameters passed to ``decode()``.
Closes: #4801
Fixes: #4799
Change-Id: I1d542ba367bcd187347c54db1fee815f7890e71c
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/dialects/oracle/cx_oracle.py | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 2572a79b3..d7cd6dcfc 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -78,6 +78,8 @@ The parameters accepted by the cx_oracle dialect are as follows: * ``coerce_to_decimal`` - see :ref:`cx_oracle_numeric` for detail. +* ``encoding_errors`` - see :ref:`cx_oracle_unicode_encoding_errors` for detail. + .. _cx_oracle_unicode: Unicode @@ -124,6 +126,23 @@ VARCHAR2, CHAR, and CLOB, the flag ``coerce_to_unicode=False`` can be passed to delivered as VARCHAR2/CHAR/CLOB data. +.. _cx_oracle_unicode_encoding_errors: + +Encoding Errors +^^^^^^^^^^^^^^^ + +For the unusual case that data in the Oracle database is present with a broken +encoding, the dialect accepts a parameter ``encoding_errors`` which will be +passed to Unicode decoding functions in order to affect how decoding errors are +handled. The value is ultimately consumed by the Python `decode +<https://docs.python.org/3/library/stdtypes.html#bytes.decode>`_ function, and +is passed both via cx_Oracle's ``encodingErrors`` parameter consumed by +``Cursor.var()``, as well as SQLAlchemy's own decoding function, as the +cx_Oracle dialect makes use of both under different circumstances. + +.. versionadded:: 1.3.11 + + .. _cx_oracle_setinputsizes: Fine grained control over cx_Oracle data binding performance with setinputsizes @@ -760,12 +779,14 @@ class OracleDialect_cx_oracle(OracleDialect): coerce_to_unicode=True, coerce_to_decimal=True, arraysize=50, + encoding_errors=None, threaded=None, **kwargs ): OracleDialect.__init__(self, **kwargs) self.arraysize = arraysize + self.encoding_errors = encoding_errors if threaded is not None: self._cx_oracle_threaded = threaded self.auto_convert_lobs = auto_convert_lobs @@ -823,6 +844,19 @@ class OracleDialect_cx_oracle(OracleDialect): self._is_cx_oracle_6 = self.cx_oracle_ver >= (6,) + @property + def _cursor_var_unicode_kwargs(self): + if self.encoding_errors: + if self.cx_oracle_ver >= (6, 4): + return {"encodingErrors": self.encoding_errors} + else: + util.warn( + "cx_oracle version %r does not support encodingErrors" + % (self.cx_oracle_ver,) + ) + + return {} + def _parse_cx_oracle_ver(self, version): m = re.match(r"(\d+)\.(\d+)(?:\.(\d+))?", version) if m: @@ -920,7 +954,7 @@ class OracleDialect_cx_oracle(OracleDialect): ): if compat.py2k: outconverter = processors.to_unicode_processor_factory( - dialect.encoding, None + dialect.encoding, errors=dialect.encoding_errors ) return cursor.var( cx_Oracle.STRING, @@ -929,7 +963,12 @@ class OracleDialect_cx_oracle(OracleDialect): outconverter=outconverter, ) else: - return cursor.var(util.text_type, size, cursor.arraysize) + return cursor.var( + util.text_type, + size, + cursor.arraysize, + **dialect._cursor_var_unicode_kwargs + ) elif dialect.auto_convert_lobs and default_type in ( cx_Oracle.CLOB, @@ -937,7 +976,7 @@ class OracleDialect_cx_oracle(OracleDialect): ): if compat.py2k: outconverter = processors.to_unicode_processor_factory( - dialect.encoding, None + dialect.encoding, errors=dialect.encoding_errors ) return cursor.var( default_type, @@ -951,6 +990,7 @@ class OracleDialect_cx_oracle(OracleDialect): size, cursor.arraysize, outconverter=lambda value: value.read(), + **dialect._cursor_var_unicode_kwargs ) elif dialect.auto_convert_lobs and default_type in ( |
