From: Mike Bayer Date: Wed, 13 Jun 2018 21:48:51 +0000 (-0400) Subject: Add use_nchar_for_unicode flag; don't use nchar types for generic unicode X-Git-Tag: rel_1_3_0b1~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb991a4474fa0d4df69af10a808fe234016c6a52;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add use_nchar_for_unicode flag; don't use nchar types for generic unicode The Oracle dialect will no longer use the NCHAR/NCLOB datatypes to represent generic unicode strings or clob fields in conjunction with :class:`.Unicode` and :class:`.UnicodeText` unless the flag ``use_nchar_for_unicode=True`` is passed to :func:`.create_engine`. Additionally, string types under Oracle now coerce to unicode under Python 2 in all cases, however unlike in previous iterations, we use SQLAlchemy's native unicode handlers which are very performant (when C extensions are enabled; when they are not, we use cx_Oracle's handlers). Change-Id: I3939012e9396520875bc52e69bf81f27393836ee Fixes: #4242 --- diff --git a/doc/build/changelog/migration_13.rst b/doc/build/changelog/migration_13.rst index 423b69579e..f742eb6672 100644 --- a/doc/build/changelog/migration_13.rst +++ b/doc/build/changelog/migration_13.rst @@ -413,6 +413,45 @@ JSON is being used for its familiarity. Dialect Improvements and Changes - Oracle ============================================= +.. _change_4242: + +National char datatypes de-emphasized for generic unicode, re-enabled with option +--------------------------------------------------------------------------------- + +The :class:`.Unicode` and :class:`.UnicodeText` datatypes by default now +correspond to the ``VARCHAR2`` and ``CLOB`` datatypes on Oracle, rather than +``NVARCHAR2`` and ``NCLOB`` (otherwise known as "national" character set +types). This will be seen in behaviors such as that of how they render in +``CREATE TABLE`` statements, as well as that no type object will be passed to +``setinputsizes()`` when bound parameters using :class:`.Unicode` or +:class:`.UnicodeText` are used; cx_Oracle handles the string value natively. +This change is based on advice from cx_Oracle's maintainer that the "national" +datatypes in Oracle are largely obsolete and are not performant. They also +interfere in some situations such as when applied to the format specifier for +functions like ``trunc()``. + +The one case where ``NVARCHAR2`` and related types may be needed is for a +database that is not using a Unicode-compliant character set. In this case, +the flag ``use_nchar_for_unicode`` can be passed to :func:`.create_engine` to +re-enable the old behavior. + +As always, using the :class:`.oracle.NVARCHAR2` and :class:`.oracle.NCLOB` +datatypes explicitly will continue to make use of ``NVARCHAR2`` and ``NCLOB``, +including within DDL as well as when handling bound parameters with cx_Oracle's +``setinputsizes()``. + +On the read side, automatic Unicode conversion under Python 2 has been added to +CHAR/VARCHAR/CLOB result rows, to match the behavior of cx_Oracle under Python +3. In order to mitigate the performance hit that the cx_Oracle dialect had +previously with this behavior under Python 2, SQLAlchemy's very performant +(when C extensions are built) native Unicode handlers are used under Python 2. +The automatic unicode coercion can be disabled by setting the +``coerce_to_unicode`` flag to False. This flag now defaults to True and applies +to all string data returned in a result set that isn't explicitly under +:class:`.Unicode` or Oracle's NVARCHAR2/NCHAR/NCLOB datatypes. + +:ticket:`4242` + Dialect Improvements and Changes - SQL Server ============================================= diff --git a/doc/build/changelog/unreleased_13/4242.rst b/doc/build/changelog/unreleased_13/4242.rst new file mode 100644 index 0000000000..b1385135aa --- /dev/null +++ b/doc/build/changelog/unreleased_13/4242.rst @@ -0,0 +1,18 @@ +.. change:: + :tags: bug, oracle + :tickets: 4242 + + The Oracle dialect will no longer use the NCHAR/NCLOB datatypes + represent generic unicode strings or clob fields in conjunction with + :class:`.Unicode` and :class:`.UnicodeText` unless the flag + ``use_nchar_for_unicode=True`` is passed to :func:`.create_engine` - + this includes CREATE TABLE behavior as well as ``setinputsizes()`` for + bound parameters. On the read side, automatic Unicode conversion under + Python 2 has been added to CHAR/VARCHAR/CLOB result rows, to match the + behavior of cx_Oracle under Python 3. In order to mitigate the performance + hit under Python 2, SQLAlchemy's very performant (when C extensions + are built) native Unicode handlers are used under Python 2. + + .. seealso:: + + :ref:`change_4242` diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 76ae1ced6c..b5aea4386b 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -533,7 +533,7 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): return self.visit_FLOAT(type_, **kw) def visit_unicode(self, type_, **kw): - if self.dialect._supports_nchar: + if self.dialect._use_nchar_for_unicode: return self.visit_NVARCHAR2(type_, **kw) else: return self.visit_VARCHAR2(type_, **kw) @@ -620,7 +620,7 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): return self.visit_CLOB(type_, **kw) def visit_unicode_text(self, type_, **kw): - if self.dialect._supports_nchar: + if self.dialect._use_nchar_for_unicode: return self.visit_NCLOB(type_, **kw) else: return self.visit_CLOB(type_, **kw) @@ -1056,6 +1056,8 @@ class OracleDialect(default.DefaultDialect): reflection_options = ('oracle_resolve_synonyms', ) + _use_nchar_for_unicode = False + construct_arguments = [ (sa_schema.Table, { "resolve_synonyms": False, @@ -1072,9 +1074,11 @@ class OracleDialect(default.DefaultDialect): use_ansi=True, optimize_limits=False, use_binds_for_limits=True, + use_nchar_for_unicode=False, exclude_tablespaces=('SYSTEM', 'SYSAUX', ), **kwargs): default.DefaultDialect.__init__(self, **kwargs) + self._use_nchar_for_unicode = use_nchar_for_unicode self.use_ansi = use_ansi self.optimize_limits = optimize_limits self.use_binds_for_limits = use_binds_for_limits @@ -1111,14 +1115,20 @@ class OracleDialect(default.DefaultDialect): def _supports_char_length(self): return not self._is_oracle_8 - @property - def _supports_nchar(self): - return not self._is_oracle_8 - def do_release_savepoint(self, connection, name): # Oracle does not support RELEASE SAVEPOINT pass + def _check_unicode_returns(self, connection): + additional_tests = [ + expression.cast( + expression.literal_column("'test nvarchar2 returns'"), + sqltypes.NVARCHAR(60) + ), + ] + return super(OracleDialect, self)._check_unicode_returns( + connection, additional_tests) + def has_table(self, connection, table_name, schema=None): if not schema: schema = self.default_schema_name diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index eb75f750ac..620b5384ba 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -56,76 +56,46 @@ on the URL, or as keyword arguments to :func:`.create_engine()` are: Unicode ------- -The cx_Oracle DBAPI as of version 5 fully supports unicode, and has the -ability to return string results as Python unicode objects natively. +The cx_Oracle DBAPI as of version 5 fully supports Unicode, and has the +ability to return string results as Python Unicode objects natively. + +Explicit Unicode support is available by using the :class:`.Unicode` datatype +with SQLAlchemy Core expression language, as well as the :class:`.UnicodeText` +datatype. These types correspond to the VARCHAR2 and CLOB Oracle datatypes by +default. When using these datatypes with Unicode data, it is expected that +the Oracle database is configured with a Unicode-aware character set, as well +as that the ``NLS_LANG`` environment variable is set appropriately, so that +the VARCHAR2 and CLOB datatypes can accommodate the data. + +In the case that the Oracle database is not configured with a Unicode character +set, the two options are to use the :class:`.oracle.NCHAR` and +:class:`.oracle.NCLOB` datatypes explicitly, or to pass the flag +``use_nchar_for_unicode=True`` to :func:`.create_engine`, which will cause the +SQLAlchemy dialect to use NCHAR/NCLOB for the :class:`.Unicode` / +:class:`.UnicodeText` datatypes instead of VARCHAR/CLOB. + +.. versionchanged:: 1.3 The :class:`.Unicode` and :class:`.UnicodeText` + datatypes now correspond to the ``VARCHAR2`` and ``CLOB`` Oracle datatypes + unless the ``use_nchar_for_unicode=True`` is passed to the dialect + when :func:`.create_engine` is called. + +When result sets are fetched that include strings, under Python 3 the cx_Oracle +DBAPI returns all strings as Python Unicode objects, since Python 3 only has a +Unicode string type. This occurs for data fetched from datatypes such as +VARCHAR2, CHAR, CLOB, NCHAR, NCLOB, etc. In order to provide cross- +compatibility under Python 2, the SQLAlchemy cx_Oracle dialect will add +Unicode-conversion to string data under Python 2 as well. Historically, this +made use of converters that were supplied by cx_Oracle but were found to be +non-performant; SQLAlchemy's own converters are used for the string to Unicode +conversion under Python 2. To disable the Python 2 Unicode conversion for +VARCHAR2, CHAR, and CLOB, the flag ``coerce_to_unicode=False`` can be passed to +:func:`.create_engine`. + +.. versionchanged:: 1.3 Unicode conversion is applied to all string values + by default under python 2. The ``coerce_to_unicode`` now defaults to True + and can be set to False to disable the Unicode coersion of strings that are + delivered as VARCHAR2/CHAR/CLOB data. -When used in Python 3, cx_Oracle returns all strings as Python unicode objects -(that is, plain ``str`` in Python 3). In Python 2, it will return as Python -unicode those column values that are of type ``NVARCHAR`` or ``NCLOB``. For -column values that are of type ``VARCHAR`` or other non-unicode string types, -it will return values as Python strings (e.g. bytestrings). - -The cx_Oracle SQLAlchemy dialect presents several different options for the use -case of receiving ``VARCHAR`` column values as Python unicode objects under -Python 2: - -* When using Core expression objects as well as the ORM, SQLAlchemy's - unicode-decoding services are available, which are established by - using either the :class:`.Unicode` datatype or by using the - :class:`.String` datatype with :paramref:`.String.convert_unicode` set - to True. - -* When using raw SQL strings, typing behavior can be added for unicode - conversion using the :func:`.text` construct:: - - from sqlalchemy import text, Unicode - result = conn.execute( - text("select username from user").columns(username=Unicode)) - -* Otherwise, when using raw SQL strings sent directly to an ``.execute()`` - method without any Core typing behavior added, the flag - ``coerce_to_unicode=True`` flag can be passed to :func:`.create_engine` - which will add an unconditional unicode processor to cx_Oracle for all - string values:: - - engine = create_engine("oracle+cx_oracle://dsn", coerce_to_unicode=True) - - The above approach will add significant latency to result-set fetches - of plain string values. - -Sending String Values as Unicode or Non-Unicode -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -As of SQLAlchemy 1.2.2, the cx_Oracle dialect unconditionally calls -``setinputsizes()`` for bound values that are passed as Python unicode objects. -In Python 3, all string values are Unicode; for cx_Oracle, this corresponds to -``cx_Oracle.NCHAR`` being passed to ``setinputsizes()`` for that parameter. -In some edge cases, such as passing format specifiers for -the ``trunc()`` function, Oracle does not accept these as NCHAR:: - - from sqlalchemy import func - - conn.execute( - func.trunc(func.sysdate(), 'dd') - ) - -In these cases, an error as follows may be raised:: - - ORA-01899: bad precision specifier - -When this error is encountered, it may be necessary to pass the string value -with an explicit non-unicode type:: - - from sqlalchemy import func - from sqlalchemy import literal - from sqlalchemy import String - - conn.execute( - func.trunc(func.sysdate(), literal('dd', String)) - ) - -For full control over this ``setinputsizes()`` behavior, see the section -:ref:`cx_oracle_setinputsizes` .. _cx_oracle_setinputsizes: @@ -193,7 +163,6 @@ series. This setting can be modified as follows:: if dbapitype is CLOB: del inputsizes[bindparam] - .. _cx_oracle_returning: RETURNING Support @@ -285,11 +254,11 @@ from .base import OracleCompiler, OracleDialect, OracleExecutionContext from . import base as oracle from ...engine import result as _result from sqlalchemy import types as sqltypes, util, exc, processors +from ...util import compat import random import collections import decimal import re -import time class _OracleInteger(sqltypes.Integer): @@ -430,11 +399,26 @@ class _OracleChar(sqltypes.CHAR): return dbapi.FIXED_CHAR -class _OracleNVarChar(sqltypes.NVARCHAR): +class _OracleUnicodeStringNCHAR(oracle.NVARCHAR2): def get_dbapi_type(self, dbapi): return dbapi.NCHAR +class _OracleUnicodeStringCHAR(sqltypes.Unicode): + def get_dbapi_type(self, dbapi): + return None + + +class _OracleUnicodeTextNCLOB(oracle.NCLOB): + def get_dbapi_type(self, dbapi): + return dbapi.NCLOB + + +class _OracleUnicodeTextCLOB(sqltypes.UnicodeText): + def get_dbapi_type(self, dbapi): + return dbapi.CLOB + + class _OracleText(sqltypes.Text): def get_dbapi_type(self, dbapi): return dbapi.CLOB @@ -459,11 +443,6 @@ class _OracleEnum(sqltypes.Enum): return process -class _OracleUnicodeText(sqltypes.UnicodeText): - def get_dbapi_type(self, dbapi): - return dbapi.NCLOB - - class _OracleBinary(sqltypes.LargeBinary): def get_dbapi_type(self, dbapi): return dbapi.BLOB @@ -698,14 +677,16 @@ class OracleDialect_cx_oracle(OracleDialect): oracle.INTERVAL: _OracleInterval, sqltypes.Text: _OracleText, sqltypes.String: _OracleString, - sqltypes.UnicodeText: _OracleUnicodeText, + sqltypes.UnicodeText: _OracleUnicodeTextCLOB, sqltypes.CHAR: _OracleChar, sqltypes.Enum: _OracleEnum, oracle.LONG: _OracleLong, oracle.RAW: _OracleRaw, - sqltypes.Unicode: _OracleNVarChar, - sqltypes.NVARCHAR: _OracleNVarChar, + sqltypes.Unicode: _OracleUnicodeStringCHAR, + sqltypes.NVARCHAR: _OracleUnicodeStringNCHAR, + sqltypes.NCHAR: _OracleUnicodeStringNCHAR, + oracle.NCLOB: _OracleUnicodeTextNCLOB, oracle.ROWID: _OracleRowid, } @@ -714,7 +695,7 @@ class OracleDialect_cx_oracle(OracleDialect): def __init__(self, auto_convert_lobs=True, threaded=True, - coerce_to_unicode=False, + coerce_to_unicode=True, coerce_to_decimal=True, arraysize=50, **kwargs): @@ -727,6 +708,10 @@ class OracleDialect_cx_oracle(OracleDialect): self.auto_convert_lobs = auto_convert_lobs self.coerce_to_unicode = coerce_to_unicode self.coerce_to_decimal = coerce_to_decimal + if self._use_nchar_for_unicode: + self.colspecs = self.colspecs.copy() + self.colspecs[sqltypes.Unicode] = _OracleUnicodeStringNCHAR + self.colspecs[sqltypes.UnicodeText] = _OracleUnicodeTextNCLOB cx_Oracle = self.dbapi @@ -872,11 +857,36 @@ class OracleDialect_cx_oracle(OracleDialect): # allow all strings to come back natively as Unicode elif dialect.coerce_to_unicode and \ default_type in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR): - return cursor.var( - util.text_type, size, cursor.arraysize - ) + if compat.py2k: + outconverter = processors.to_unicode_processor_factory( + dialect.encoding, None) + return cursor.var( + cx_Oracle.STRING, size, cursor.arraysize, + outconverter=outconverter + ) + else: + return cursor.var( + util.text_type, size, cursor.arraysize + ) + + elif dialect.auto_convert_lobs and default_type in ( + cx_Oracle.CLOB, cx_Oracle.NCLOB + ): + if compat.py2k: + outconverter = processors.to_unicode_processor_factory( + dialect.encoding, None) + return cursor.var( + default_type, size, cursor.arraysize, + outconverter=lambda value: outconverter(value.read()) + ) + else: + return cursor.var( + default_type, size, cursor.arraysize, + outconverter=lambda value: value.read() + ) + elif dialect.auto_convert_lobs and default_type in ( - cx_Oracle.CLOB, cx_Oracle.NCLOB, cx_Oracle.BLOB + cx_Oracle.BLOB, ): return cursor.var( default_type, size, cursor.arraysize, diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index aa524cd511..f48217a4e9 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -1135,6 +1135,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): dialect_impl = bindparam.type._unwrapped_dialect_impl(self.dialect) dialect_impl_cls = type(dialect_impl) dbtype = dialect_impl.get_dbapi_type(self.dialect.dbapi) + if dbtype is not None and ( not exclude_types or dbtype not in exclude_types and dialect_impl_cls not in exclude_types diff --git a/test/dialect/oracle/test_dialect.py b/test/dialect/oracle/test_dialect.py index fc6eba89a7..23725e4836 100644 --- a/test/dialect/oracle/test_dialect.py +++ b/test/dialect/oracle/test_dialect.py @@ -179,13 +179,12 @@ class CompatFlagsTest(fixtures.TestBase, AssertsCompiledSQL): # before connect, assume modern DB assert dialect._supports_char_length - assert dialect._supports_nchar assert dialect.use_ansi + assert not dialect._use_nchar_for_unicode dialect.initialize(Mock()) assert not dialect.implicit_returning assert not dialect._supports_char_length - assert not dialect._supports_nchar assert not dialect.use_ansi self.assert_compile(String(50), "VARCHAR2(50)", dialect=dialect) self.assert_compile(Unicode(50), "VARCHAR2(50)", dialect=dialect) @@ -201,19 +200,29 @@ class CompatFlagsTest(fixtures.TestBase, AssertsCompiledSQL): dialect = self._dialect(None) assert dialect._supports_char_length - assert dialect._supports_nchar + assert not dialect._use_nchar_for_unicode assert dialect.use_ansi self.assert_compile(String(50), "VARCHAR2(50 CHAR)", dialect=dialect) - self.assert_compile(Unicode(50), "NVARCHAR2(50)", dialect=dialect) - self.assert_compile(UnicodeText(), "NCLOB", dialect=dialect) + self.assert_compile(Unicode(50), "VARCHAR2(50 CHAR)", dialect=dialect) + self.assert_compile(UnicodeText(), "CLOB", dialect=dialect) def test_ora10_flags(self): dialect = self._dialect((10, 2, 5)) dialect.initialize(Mock()) assert dialect._supports_char_length - assert dialect._supports_nchar + assert not dialect._use_nchar_for_unicode assert dialect.use_ansi + self.assert_compile(String(50), "VARCHAR2(50 CHAR)", dialect=dialect) + self.assert_compile(Unicode(50), "VARCHAR2(50 CHAR)", dialect=dialect) + self.assert_compile(UnicodeText(), "CLOB", dialect=dialect) + + def test_use_nchar(self): + dialect = self._dialect((10, 2, 5), use_nchar_for_unicode=True) + + dialect.initialize(Mock()) + assert dialect._use_nchar_for_unicode + self.assert_compile(String(50), "VARCHAR2(50 CHAR)", dialect=dialect) self.assert_compile(Unicode(50), "NVARCHAR2(50)", dialect=dialect) self.assert_compile(UnicodeText(), "NCLOB", dialect=dialect) diff --git a/test/dialect/oracle/test_types.py b/test/dialect/oracle/test_types.py index f8e8d41f88..9fbea61303 100644 --- a/test/dialect/oracle/test_types.py +++ b/test/dialect/oracle/test_types.py @@ -75,14 +75,33 @@ class DialectTypesTest(fixtures.TestBase, AssertsCompiledSQL): (DATE(), cx_oracle._OracleDate), (oracle.DATE(), oracle.DATE), (String(50), cx_oracle._OracleString), - (Unicode(), cx_oracle._OracleNVarChar), + (Unicode(), cx_oracle._OracleUnicodeStringCHAR), (Text(), cx_oracle._OracleText), - (UnicodeText(), cx_oracle._OracleUnicodeText), - (NCHAR(), cx_oracle._OracleNVarChar), + (UnicodeText(), cx_oracle._OracleUnicodeTextCLOB), + (NCHAR(), cx_oracle._OracleUnicodeStringNCHAR), + (NVARCHAR(), cx_oracle._OracleUnicodeStringNCHAR), (oracle.RAW(50), cx_oracle._OracleRaw), ]: - assert isinstance(start.dialect_impl(dialect), test), \ - "wanted %r got %r" % (test, start.dialect_impl(dialect)) + assert isinstance( + start.dialect_impl(dialect), test), \ + "wanted %r got %r" % (test, start.dialect_impl(dialect)) + + def test_type_adapt_nchar(self): + dialect = cx_oracle.dialect(use_nchar_for_unicode=True) + + for start, test in [ + (String(), String), + (VARCHAR(), cx_oracle._OracleString), + (String(50), cx_oracle._OracleString), + (Unicode(), cx_oracle._OracleUnicodeStringNCHAR), + (Text(), cx_oracle._OracleText), + (UnicodeText(), cx_oracle._OracleUnicodeTextNCLOB), + (NCHAR(), cx_oracle._OracleUnicodeStringNCHAR), + (NVARCHAR(), cx_oracle._OracleUnicodeStringNCHAR), + ]: + assert isinstance( + start.dialect_impl(dialect), test), \ + "wanted %r got %r" % (test, start.dialect_impl(dialect)) def test_raw_compile(self): self.assert_compile(oracle.RAW(), "RAW") @@ -100,6 +119,24 @@ class DialectTypesTest(fixtures.TestBase, AssertsCompiledSQL): def test_varchar_types(self): dialect = oracle.dialect() + for typ, exp in [ + (String(50), "VARCHAR2(50 CHAR)"), + (Unicode(50), "VARCHAR2(50 CHAR)"), + (NVARCHAR(50), "NVARCHAR2(50)"), + (VARCHAR(50), "VARCHAR(50 CHAR)"), + (oracle.NVARCHAR2(50), "NVARCHAR2(50)"), + (oracle.VARCHAR2(50), "VARCHAR2(50 CHAR)"), + (String(), "VARCHAR2"), + (Unicode(), "VARCHAR2"), + (NVARCHAR(), "NVARCHAR2"), + (VARCHAR(), "VARCHAR"), + (oracle.NVARCHAR2(), "NVARCHAR2"), + (oracle.VARCHAR2(), "VARCHAR2"), + ]: + self.assert_compile(typ, exp, dialect=dialect) + + def test_varchar_use_nchar_types(self): + dialect = oracle.dialect(use_nchar_for_unicode=True) for typ, exp in [ (String(50), "VARCHAR2(50 CHAR)"), (Unicode(50), "NVARCHAR2(50)"), @@ -587,12 +624,12 @@ class TypesTest(fixtures.TestBase): testing.requires.python3, "cx_oracle always returns unicode on py3k") def test_coerce_to_unicode(self): - engine = testing_engine(options=dict(coerce_to_unicode=True)) + engine = testing_engine(options=dict(coerce_to_unicode=False)) value = engine.scalar("SELECT 'hello' FROM DUAL") - assert isinstance(value, util.text_type) + assert isinstance(value, util.binary_type) value = testing.db.scalar("SELECT 'hello' FROM DUAL") - assert isinstance(value, util.binary_type) + assert isinstance(value, util.text_type) @testing.provide_metadata def test_reflect_dates(self): @@ -651,11 +688,29 @@ class TypesTest(fixtures.TestBase): assert isinstance(t2.c.data.type, sqltypes.NVARCHAR) if testing.against('oracle+cx_oracle'): - # nvarchar returns unicode natively. cx_oracle - # _OracleNVarChar type should be at play here. assert isinstance( t2.c.data.type.dialect_impl(testing.db.dialect), - cx_oracle._OracleNVarChar) + cx_oracle._OracleUnicodeStringNCHAR) + + data = u('m’a réveillé.') + t2.insert().execute(data=data) + res = t2.select().execute().first()['data'] + eq_(res, data) + assert isinstance(res, util.text_type) + + @testing.provide_metadata + def test_reflect_unicode_no_nvarchar(self): + metadata = self.metadata + Table('tnv', metadata, Column('data', sqltypes.Unicode(255))) + metadata.create_all() + m2 = MetaData(testing.db) + t2 = Table('tnv', m2, autoload=True) + assert isinstance(t2.c.data.type, sqltypes.VARCHAR) + + if testing.against('oracle+cx_oracle'): + assert isinstance( + t2.c.data.type.dialect_impl(testing.db.dialect), + cx_oracle._OracleString) data = u('m’a réveillé.') t2.insert().execute(data=data) @@ -901,7 +956,8 @@ class SetInputSizesTest(fixtures.TestBase): __backend__ = True @testing.provide_metadata - def _test_setinputsizes(self, datatype, value, sis_value): + def _test_setinputsizes( + self, datatype, value, sis_value, set_nchar_flag=False): class TestTypeDec(TypeDecorator): impl = NullType() @@ -944,7 +1000,12 @@ class SetInputSizesTest(fixtures.TestBase): def __getattr__(self, key): return getattr(self.cursor, key) - with testing.db.connect() as conn: + if set_nchar_flag: + engine = testing_engine(options={"use_nchar_for_unicode": True}) + else: + engine = testing.db + + with engine.connect() as conn: connection_fairy = conn.connection for tab in [t1, t2, t3]: with mock.patch.object( @@ -995,9 +1056,23 @@ class SetInputSizesTest(fixtures.TestBase): oracle.DOUBLE_PRECISION, 25.34534, None) + def test_unicode_nchar_mode(self): + self._test_setinputsizes( + Unicode(30), u("test"), testing.db.dialect.dbapi.NCHAR, + set_nchar_flag=True) + + def test_unicodetext_nchar_mode(self): + self._test_setinputsizes( + UnicodeText(), u("test"), testing.db.dialect.dbapi.NCLOB, + set_nchar_flag=True) + def test_unicode(self): self._test_setinputsizes( - Unicode(30), u("test"), testing.db.dialect.dbapi.NCHAR) + Unicode(30), u("test"), None) + + def test_unicodetext(self): + self._test_setinputsizes( + UnicodeText(), u("test"), testing.db.dialect.dbapi.CLOB) def test_string(self): self._test_setinputsizes(String(30), "test", None) diff --git a/test/profiles.txt b/test/profiles.txt index a70901208e..ae7b5746ab 100644 --- a/test/profiles.txt +++ b/test/profiles.txt @@ -1,15 +1,15 @@ # /home/classic/dev/sqlalchemy/test/profiles.txt # This file is written out on a per-environment basis. -# For each test in aaa_profiling, the corresponding function and +# For each test in aaa_profiling, the corresponding function and # environment is located within this file. If it doesn't exist, # the test is skipped. -# If a callcount does exist, it is compared to what we received. +# If a callcount does exist, it is compared to what we received. # assertions are raised if the counts do not match. -# -# To add a new callcount test, apply the function_call_count -# decorator and re-run the tests using the --write-profiles +# +# To add a new callcount test, apply the function_call_count +# decorator and re-run the tests using the --write-profiles # option - this file will be rewritten including the new count. -# +# # TEST: test.aaa_profiling.test_compiler.CompileTest.test_insert @@ -27,14 +27,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dba test.aaa_profiling.test_compiler.CompileTest.test_insert 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 70,70 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mssql_pyodbc_dbapiunicode_cextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mssql_pyodbc_dbapiunicode_nocextensions 73,73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_mysqldb_dbapiunicode_cextensions 73,73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_mysqldb_dbapiunicode_nocextensions 73,73 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_mysqldb_dbapiunicode_cextensions 73,73,73,73 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_mysqldb_dbapiunicode_nocextensions 73,73,73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_pymysql_dbapiunicode_cextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_mysql_pymysql_dbapiunicode_nocextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_oracle_cx_oracle_dbapiunicode_cextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 73,73 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_postgresql_psycopg2_dbapiunicode_cextensions 73,73,78 -test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 73,73,78 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_postgresql_psycopg2_dbapiunicode_cextensions 73,73,73 +test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 73,73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_sqlite_pysqlite_dbapiunicode_cextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.6_sqlite_pysqlite_dbapiunicode_nocextensions 73,73 test.aaa_profiling.test_compiler.CompileTest.test_insert 3.7_mysql_mysqldb_dbapiunicode_cextensions 73,73,73,73 @@ -138,14 +138,14 @@ test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dba test.aaa_profiling.test_compiler.CompileTest.test_update 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 82,80 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mssql_pyodbc_dbapiunicode_cextensions 83,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mssql_pyodbc_dbapiunicode_nocextensions 83,81 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_mysqldb_dbapiunicode_cextensions 83,81 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_mysqldb_dbapiunicode_nocextensions 83,81 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_mysqldb_dbapiunicode_cextensions 83,81,81,81 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_mysqldb_dbapiunicode_nocextensions 83,81,81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_pymysql_dbapiunicode_cextensions 81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_mysql_pymysql_dbapiunicode_nocextensions 81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_oracle_cx_oracle_dbapiunicode_cextensions 83,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 83,81 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_postgresql_psycopg2_dbapiunicode_cextensions 83,81,77 -test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 83,81,77 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_postgresql_psycopg2_dbapiunicode_cextensions 83,81,81 +test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 83,81,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_sqlite_pysqlite_dbapiunicode_cextensions 83,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.6_sqlite_pysqlite_dbapiunicode_nocextensions 83,81 test.aaa_profiling.test_compiler.CompileTest.test_update 3.7_mysql_mysqldb_dbapiunicode_cextensions 83,81,81,81 @@ -388,8 +388,8 @@ test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mssql_pyodbc_dbap test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mssql_pyodbc_dbapiunicode_nocextensions 26212 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mysql_mysqldb_dbapiunicode_cextensions 41220 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_mysql_mysqldb_dbapiunicode_nocextensions 50225 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_cextensions 17287 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 26292 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_cextensions 17299 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 44316 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_cextensions 17199 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 26204 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 2.7_sqlite_pysqlite_dbapiunicode_cextensions 17164 @@ -398,8 +398,8 @@ test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_mssql_pyodbc_dbap test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_mssql_pyodbc_dbapiunicode_nocextensions 27228 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_mysql_mysqldb_dbapiunicode_cextensions 30235 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_mysql_mysqldb_dbapiunicode_nocextensions 39242 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_oracle_cx_oracle_dbapiunicode_cextensions 18301 -test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 27308 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_oracle_cx_oracle_dbapiunicode_cextensions 18307 +test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 27314 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_postgresql_psycopg2_dbapiunicode_cextensions 18228 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 27235 test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline 3.6_sqlite_pysqlite_dbapiunicode_cextensions 18186 @@ -475,6 +475,7 @@ test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_postgresql_ test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_cextensions 455708 test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_build_query 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 455708 + # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results 2.7_mssql_pyodbc_dbapiunicode_cextensions 466544 @@ -667,20 +668,20 @@ test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mssql_pyodbc_dbapiunic test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mssql_pyodbc_dbapiunicode_nocextensions 6780 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mysql_mysqldb_dbapiunicode_cextensions 8020 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_mysql_mysqldb_dbapiunicode_nocextensions 8570 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_cextensions 6280 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 6830 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_cextensions 6360 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 8190 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_cextensions 6150 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 6700 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_cextensions 6004 test.aaa_profiling.test_orm.QueryTest.test_query_cols 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6554 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_mssql_pyodbc_dbapiunicode_cextensions 6404 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_mssql_pyodbc_dbapiunicode_nocextensions 6974 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_mysql_mysqldb_dbapiunicode_cextensions 7404 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_mysql_mysqldb_dbapiunicode_cextensions 7494 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_mysql_mysqldb_dbapiunicode_nocextensions 7974 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_oracle_cx_oracle_dbapiunicode_cextensions 6454 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 7024 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_oracle_cx_oracle_dbapiunicode_cextensions 6494 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 7154 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_postgresql_psycopg2_dbapiunicode_cextensions 6414 -test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 6984 +test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 7074 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_sqlite_pysqlite_dbapiunicode_cextensions 6186 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.6_sqlite_pysqlite_dbapiunicode_nocextensions 6756 test.aaa_profiling.test_orm.QueryTest.test_query_cols 3.7_mysql_mysqldb_dbapiunicode_cextensions 7433 @@ -863,8 +864,8 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 51 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mssql_pyodbc_dbapiunicode_cextensions 51 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mssql_pyodbc_dbapiunicode_nocextensions 55 -test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_mysqldb_dbapiunicode_cextensions 51,51 -test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_mysqldb_dbapiunicode_nocextensions 55,55 +test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_mysqldb_dbapiunicode_cextensions 51,51,51,51 +test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_mysqldb_dbapiunicode_nocextensions 55,55,55,55 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_pymysql_dbapiunicode_cextensions 51,51 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_mysql_pymysql_dbapiunicode_nocextensions 55,55 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_connection_execute 3.6_oracle_cx_oracle_dbapiunicode_cextensions 51 @@ -900,8 +901,8 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 90 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mssql_pyodbc_dbapiunicode_cextensions 90 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mssql_pyodbc_dbapiunicode_nocextensions 94 -test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_mysqldb_dbapiunicode_cextensions 90,90 -test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_mysqldb_dbapiunicode_nocextensions 94,94 +test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_mysqldb_dbapiunicode_cextensions 90,90,90,90 +test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_mysqldb_dbapiunicode_nocextensions 94,94,94,94 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_pymysql_dbapiunicode_cextensions 90,90 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_mysql_pymysql_dbapiunicode_nocextensions 94,94 test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.6_oracle_cx_oracle_dbapiunicode_cextensions 90 @@ -937,8 +938,8 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mssql_pyodbc_dbapiunicode_cextensions 16 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mssql_pyodbc_dbapiunicode_nocextensions 16 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_mysqldb_dbapiunicode_cextensions 16,16 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_mysqldb_dbapiunicode_nocextensions 16,16 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_mysqldb_dbapiunicode_cextensions 16,16,16,16 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_mysqldb_dbapiunicode_nocextensions 16,16,16,16 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_pymysql_dbapiunicode_cextensions 16,16 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_mysql_pymysql_dbapiunicode_nocextensions 16,16 test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.6_oracle_cx_oracle_dbapiunicode_cextensions 16 @@ -965,21 +966,21 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mssql_pyodbc test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 40304,40306,40306,40306 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 55326,55328,55328,55328 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122257,122262 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 137269,137269 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 355 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 15377 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 137259,137264 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 375 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 45417 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 290,292,292 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15312,15314,15314 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 246 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15268 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mssql_pyodbc_dbapiunicode_cextensions 245 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mssql_pyodbc_dbapiunicode_nocextensions 14249 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_mysqldb_dbapiunicode_cextensions 20285,20287 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34289,34291 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_pymysql_dbapiunicode_cextensions 88036,88066 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_pymysql_dbapiunicode_nocextensions 102040,102065 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_oracle_cx_oracle_dbapiunicode_cextensions 324 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14328 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_mysqldb_dbapiunicode_cextensions 20285,20287,20287,20287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34289,34291,34291,34291 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_pymysql_dbapiunicode_cextensions 88041,88046 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_mysql_pymysql_dbapiunicode_nocextensions 102045,102055 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_oracle_cx_oracle_dbapiunicode_cextensions 334 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14338 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_postgresql_psycopg2_dbapiunicode_cextensions 290,292,292 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14294,14296,14296 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string 3.6_sqlite_pysqlite_dbapiunicode_cextensions 242 @@ -1001,22 +1002,22 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodb test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 15258 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 40304,40306,40306,40306 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 55326,55328,55328,55328 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122257,122257 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 137264,137264 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 20355 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 35377 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122257,122262 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 137274,137264 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 375 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 45417 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 290,292,292 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15312,15314,15314 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 246 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15268 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mssql_pyodbc_dbapiunicode_cextensions 245 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mssql_pyodbc_dbapiunicode_nocextensions 14249 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_mysqldb_dbapiunicode_cextensions 20285,20287 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34289,34291 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_pymysql_dbapiunicode_cextensions 88036,88056 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_pymysql_dbapiunicode_nocextensions 102040,102055 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_oracle_cx_oracle_dbapiunicode_cextensions 324 -test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14328 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_mysqldb_dbapiunicode_cextensions 20285,20287,20287,20287 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34289,34291,34291,34291 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_pymysql_dbapiunicode_cextensions 88041,88036 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_mysql_pymysql_dbapiunicode_nocextensions 102050,102050 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_oracle_cx_oracle_dbapiunicode_cextensions 334 +test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14338 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_postgresql_psycopg2_dbapiunicode_cextensions 290,292,292 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14294,14296,14296 test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode 3.6_sqlite_pysqlite_dbapiunicode_cextensions 242 @@ -1038,24 +1039,24 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dba test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mssql_pyodbc_dbapiunicode_nocextensions 15528 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_cextensions 40533,40535,40535,40535 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_mysqldb_dbapiunicode_nocextensions 55535,55537,55537,55537 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122506,122501 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 137498,137513 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 535 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 15537 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_cextensions 122506,122496 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_mysql_pymysql_dbapiunicode_nocextensions 137518,137508 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_cextensions 555 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 45577 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_cextensions 518,520,520 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15520,15522,15522 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_cextensions 460 test.aaa_profiling.test_resultset.ResultSetTest.test_string 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15462 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mssql_pyodbc_dbapiunicode_cextensions 530 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mssql_pyodbc_dbapiunicode_nocextensions 14534 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_mysqldb_dbapiunicode_cextensions 20538,20520 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34542,34524 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_pymysql_dbapiunicode_cextensions 88290,88275 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_pymysql_dbapiunicode_nocextensions 102294,102299 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_oracle_cx_oracle_dbapiunicode_cextensions 539 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14543 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_postgresql_psycopg2_dbapiunicode_cextensions 543,525,525 -test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14547,14529,14529 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_mysqldb_dbapiunicode_cextensions 20538,20540,20540,20540 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34542,34544,34544,34544 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_pymysql_dbapiunicode_cextensions 88295,88300 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_mysql_pymysql_dbapiunicode_nocextensions 102299,102304 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_oracle_cx_oracle_dbapiunicode_cextensions 549 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14553 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_postgresql_psycopg2_dbapiunicode_cextensions 543,545,545 +test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14547,14549,14549 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_sqlite_pysqlite_dbapiunicode_cextensions 480 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.6_sqlite_pysqlite_dbapiunicode_nocextensions 14484 test.aaa_profiling.test_resultset.ResultSetTest.test_string 3.7_mysql_mysqldb_dbapiunicode_cextensions 20537,20539,20539,20539 @@ -1075,24 +1076,24 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_db test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mssql_pyodbc_dbapiunicode_nocextensions 15528 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_cextensions 40533,40535,40535,40535 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_mysqldb_dbapiunicode_nocextensions 55535,55537,55537,55537 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122501,122506 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_cextensions 122501,122496 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_mysql_pymysql_dbapiunicode_nocextensions 137503,137503 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 20535 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 55537 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_cextensions 555 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_oracle_cx_oracle_dbapiunicode_nocextensions 45577 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_cextensions 518,520,520 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_postgresql_psycopg2_dbapiunicode_nocextensions 15520,15522,15522 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_cextensions 460 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 15462 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mssql_pyodbc_dbapiunicode_cextensions 530 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mssql_pyodbc_dbapiunicode_nocextensions 14534 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_mysqldb_dbapiunicode_cextensions 20538,20520 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34542,34524 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_pymysql_dbapiunicode_cextensions 88290,88275 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_pymysql_dbapiunicode_nocextensions 102294,102274 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_oracle_cx_oracle_dbapiunicode_cextensions 539 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14543 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_postgresql_psycopg2_dbapiunicode_cextensions 543,525,525 -test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14547,14529,14529 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_mysqldb_dbapiunicode_cextensions 20538,20540,20540,20540 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_mysqldb_dbapiunicode_nocextensions 34542,34544,34544,34544 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_pymysql_dbapiunicode_cextensions 88290,88295 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_mysql_pymysql_dbapiunicode_nocextensions 102299,102329 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_oracle_cx_oracle_dbapiunicode_cextensions 549 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_oracle_cx_oracle_dbapiunicode_nocextensions 14553 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_postgresql_psycopg2_dbapiunicode_cextensions 543,545,545 +test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_postgresql_psycopg2_dbapiunicode_nocextensions 14547,14549,14549 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_sqlite_pysqlite_dbapiunicode_cextensions 480 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.6_sqlite_pysqlite_dbapiunicode_nocextensions 14484 test.aaa_profiling.test_resultset.ResultSetTest.test_unicode 3.7_mysql_mysqldb_dbapiunicode_cextensions 20537,20539,20539,20539