From: Mike Bayer Date: Fri, 18 Dec 2020 15:46:20 +0000 (-0500) Subject: test fixes for oracle 18c, for rel_1_3 X-Git-Tag: rel_1_3_23~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=94ac28e2b975e6be82cc961dde1ccecee547a159;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git test fixes for oracle 18c, for rel_1_3 Change-Id: I4968aa3bde3c4d11d7fe84f18b4a846ba357d16a --- diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 3028704a4f..c60a85c7cf 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -974,7 +974,11 @@ class OracleCompiler(compiler.SQLCompiler): for i, column in enumerate( expression._select_iterables(returning_cols) ): - if self.isupdate and isinstance(column.server_default, Computed): + if ( + self.isupdate + and isinstance(column.server_default, Computed) + and not self.dialect._supports_update_returning_computed_cols + ): util.warn( "Computed columns don't work with Oracle UPDATE " "statements that use RETURNING; the value of the column " @@ -1388,6 +1392,12 @@ class OracleDialect(default.DefaultDialect): def _supports_char_length(self): return not self._is_oracle_8 + @property + def _supports_update_returning_computed_cols(self): + # on version 18 this error is no longet present while it happens on 11 + # it may work also on versions before the 18 + return self.server_version_info and self.server_version_info >= (18,) + def do_release_savepoint(self, connection, name): # Oracle does not support RELEASE SAVEPOINT pass diff --git a/lib/sqlalchemy/dialects/oracle/provision.py b/lib/sqlalchemy/dialects/oracle/provision.py index 7901eb4e81..bf6116b07a 100644 --- a/lib/sqlalchemy/dialects/oracle/provision.py +++ b/lib/sqlalchemy/dialects/oracle/provision.py @@ -7,6 +7,7 @@ from ...testing.provision import drop_db from ...testing.provision import follower_url_from_main from ...testing.provision import log from ...testing.provision import run_reap_dbs +from ...testing.provision import stop_test_class from ...testing.provision import temp_table_keyword_args from ...testing.provision import update_db_opts @@ -60,6 +61,18 @@ def _oracle_update_db_opts(db_url, db_opts): pass +@stop_test_class.for_db("oracle") +def stop_test_class(config, db, cls): + """run magic command to get rid of identity sequences + + # https://floo.bar/2019/11/29/drop-the-underlying-sequence-of-an-identity-column/ + + """ + + with db.begin() as conn: + conn.execute("purge recyclebin") + + @run_reap_dbs.for_db("oracle") def _reap_oracle_dbs(url, idents): log.info("db reaper connecting to %r", url) diff --git a/lib/sqlalchemy/testing/plugin/plugin_base.py b/lib/sqlalchemy/testing/plugin/plugin_base.py index 2b062cee4a..f1314d96c9 100644 --- a/lib/sqlalchemy/testing/plugin/plugin_base.py +++ b/lib/sqlalchemy/testing/plugin/plugin_base.py @@ -41,6 +41,7 @@ engines = None exclusions = None warnings = None profiling = None +provision = None assertions = None requirements = None config = None @@ -246,12 +247,12 @@ def post_begin(): fn(options, file_config) # late imports, has to happen after config. - global util, fixtures, engines, exclusions, assertions + global util, fixtures, engines, exclusions, assertions, provision global warnings, profiling, config, testing from sqlalchemy import testing # noqa from sqlalchemy.testing import fixtures, engines, exclusions # noqa from sqlalchemy.testing import assertions, warnings, profiling # noqa - from sqlalchemy.testing import config # noqa + from sqlalchemy.testing import config, provision # noqa from sqlalchemy import util # noqa warnings.setup_filters() @@ -554,6 +555,8 @@ def start_test_class(cls): def stop_test_class(cls): # from sqlalchemy import inspect # assert not inspect(testing.db).get_table_names() + + provision.stop_test_class(config, config.db, cls) engines.testing_reaper._stop_test_ctx() try: if not options.low_connections: diff --git a/lib/sqlalchemy/testing/provision.py b/lib/sqlalchemy/testing/provision.py index 7669cdc32e..2445b7745e 100644 --- a/lib/sqlalchemy/testing/provision.py +++ b/lib/sqlalchemy/testing/provision.py @@ -192,3 +192,8 @@ def temp_table_keyword_args(cfg, eng): raise NotImplementedError( "no temp table keyword args routine for cfg: %s" % eng.url ) + + +@register.init +def stop_test_class(config, db, testcls): + pass diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index 6bb89a3cf8..1034b94d89 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -25,8 +25,7 @@ def setup_filters(): warnings.filterwarnings( "ignore", category=sa_exc.SAWarning, - message=r"Oracle compatibility version .* is known to have a " - "maximum identifier", + message=r"Oracle version .* is known to have a " "maximum identifier", ) # some selected deprecations... diff --git a/test/dialect/oracle/test_dialect.py b/test/dialect/oracle/test_dialect.py index c28218a3d3..d01e1be2e7 100644 --- a/test/dialect/oracle/test_dialect.py +++ b/test/dialect/oracle/test_dialect.py @@ -350,11 +350,17 @@ class ComputedReturningTest(fixtures.TablesTest): eq_(conn.scalar(select([test.c.bar])), 47) - def test_computed_update_warning(self): + def test_computed_update_warning(self, connection): test = self.tables.test - with testing.db.connect() as conn: - conn.execute(test.insert(), {"id": 1, "foo": 5}) + conn = connection + conn.execute(test.insert(), {"id": 1, "foo": 5}) + if testing.db.dialect._supports_update_returning_computed_cols: + result = conn.execute( + test.update().values(foo=10).return_defaults() + ) + eq_(result.returned_defaults, (52,)) + else: with testing.expect_warnings( "Computed columns don't work with Oracle UPDATE" ): @@ -365,7 +371,7 @@ class ComputedReturningTest(fixtures.TablesTest): # returns the *old* value eq_(result.returned_defaults, (47,)) - eq_(conn.scalar(select([test.c.bar])), 52) + eq_(conn.scalar(select([test.c.bar])), 52) def test_computed_update_no_warning(self): test = self.tables.test_no_returning @@ -429,7 +435,7 @@ class QuotedBindRoundTripTest(fixtures.TestBase): @testing.provide_metadata def test_table_round_trip(self): - oracle.RESERVED_WORDS.remove("UNION") + oracle.RESERVED_WORDS.discard("UNION") metadata = self.metadata table = Table( diff --git a/test/dialect/oracle/test_reflection.py b/test/dialect/oracle/test_reflection.py index 4ce60db4c3..160b58939d 100644 --- a/test/dialect/oracle/test_reflection.py +++ b/test/dialect/oracle/test_reflection.py @@ -456,27 +456,24 @@ class UnsupportedIndexReflectTest(fixtures.TestBase): def all_tables_compression_missing(): - try: - testing.db.execute("SELECT compression FROM all_tables") - if "Enterprise Edition" not in testing.db.scalar( - "select * from v$version" - ): + with testing.db.connect() as conn: + if ( + "Enterprise Edition" + not in conn.execute("select * from v$version").scalar() + # this works in Oracle Database 18c Express Edition Release + ) and testing.db.dialect.server_version_info < (18,): return True return False - except Exception: - return True def all_tables_compress_for_missing(): - try: - testing.db.execute("SELECT compress_for FROM all_tables") - if "Enterprise Edition" not in testing.db.scalar( - "select * from v$version" + with testing.db.connect() as conn: + if ( + "Enterprise Edition" + not in conn.execute("select * from v$version").scalar() ): return True return False - except Exception: - return True class TableReflectionTest(fixtures.TestBase):