From 87e27693ad57c728e870147cace473a69caca005 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 5 Mar 2024 16:28:51 -0500 Subject: [PATCH] proposal: remove _execute_compiled() this isn't used internally and only allows execute(stmt.compile()) to work, which is not something I want to support. Since people are definitely using this [1] we might want to think about either deprectation or having a recipe for people who really want to still do this [1] https://github.com/sqlalchemy/sqlalchemy/discussions/11108?converting=1 Change-Id: I5f0fe800e31aac052926cebe9206763eef9a804c --- .../unreleased_21/remove_compiled.rst | 7 ++ lib/sqlalchemy/engine/base.py | 50 -------------- lib/sqlalchemy/sql/compiler.py | 10 --- test/engine/test_execute.py | 39 ----------- test/sql/test_query.py | 68 ------------------- test/sql/test_types.py | 2 +- 6 files changed, 8 insertions(+), 168 deletions(-) create mode 100644 doc/build/changelog/unreleased_21/remove_compiled.rst diff --git a/doc/build/changelog/unreleased_21/remove_compiled.rst b/doc/build/changelog/unreleased_21/remove_compiled.rst new file mode 100644 index 0000000000..033478c29f --- /dev/null +++ b/doc/build/changelog/unreleased_21/remove_compiled.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: engine, change + + The private method ``Connection._execute_compiled`` is removed. This method may + have been used for some special purposes however the :class:`.SQLCompiler` + object has lots of special state that should be set up for an execute call, + which we don't support. diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index c7439b57be..0d8bf6f08b 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1672,56 +1672,6 @@ class Connection(ConnectionEventsTarget, inspection.Inspectable["Inspector"]): ) return ret - def _execute_compiled( - self, - compiled: Compiled, - distilled_parameters: _CoreMultiExecuteParams, - execution_options: CoreExecuteOptionsParameter = _EMPTY_EXECUTION_OPTS, - ) -> CursorResult[Unpack[TupleAny]]: - """Execute a sql.Compiled object. - - TODO: why do we have this? likely deprecate or remove - - """ - - exec_opts = compiled.execution_options.merge_with( - self._execution_options, execution_options - ) - - if self._has_events or self.engine._has_events: - ( - compiled, - distilled_parameters, - event_multiparams, - event_params, - ) = self._invoke_before_exec_event( - compiled, distilled_parameters, exec_opts - ) - - dialect = self.dialect - - ret = self._execute_context( - dialect, - dialect.execution_ctx_cls._init_compiled, - compiled, - distilled_parameters, - exec_opts, - compiled, - distilled_parameters, - None, - None, - ) - if self._has_events or self.engine._has_events: - self.dispatch.after_execute( - self, - compiled, - event_multiparams, - event_params, - exec_opts, - ret, - ) - return ret - def exec_driver_sql( self, statement: str, diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index e95eaa5918..38290980bf 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -928,16 +928,6 @@ class Compiled: def _init_compiler_cls(cls): pass - def _execute_on_connection( - self, connection, distilled_params, execution_options - ): - if self.can_execute: - return connection._execute_compiled( - self, distilled_params, execution_options - ) - else: - raise exc.ObjectNotExecutableError(self.statement) - def visit_unsupported_compilation(self, element, err, **kw): raise exc.UnsupportedCompilationError(self, type(element)) from err diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 01bb1fe94b..17a51ad76f 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -32,7 +32,6 @@ from sqlalchemy import util from sqlalchemy import VARCHAR from sqlalchemy.connectors.asyncio import AsyncAdapt_dbapi_module from sqlalchemy.engine import BindTyping -from sqlalchemy.engine import default from sqlalchemy.engine.base import Connection from sqlalchemy.engine.base import Engine from sqlalchemy.pool import AsyncAdaptedQueuePool @@ -703,39 +702,6 @@ class ExecuteTest(fixtures.TablesTest): "insert into users (user_id, user_name) values (?, ?)", [] ) - @testing.only_on("sqlite") - def test_execute_compiled_favors_compiled_paramstyle(self): - users = self.tables.users - - with patch.object(testing.db.dialect, "do_execute") as do_exec: - stmt = users.update().values(user_id=1, user_name="foo") - - d1 = default.DefaultDialect(paramstyle="format") - d2 = default.DefaultDialect(paramstyle="pyformat") - - with testing.db.begin() as conn: - conn.execute(stmt.compile(dialect=d1)) - conn.execute(stmt.compile(dialect=d2)) - - eq_( - do_exec.mock_calls, - [ - call( - mock.ANY, - "UPDATE users SET user_id=%s, user_name=%s", - (1, "foo"), - mock.ANY, - ), - call( - mock.ANY, - "UPDATE users SET user_id=%(user_id)s, " - "user_name=%(user_name)s", - {"user_name": "foo", "user_id": 1}, - mock.ANY, - ), - ], - ) - @testing.requires.ad_hoc_engines def test_engine_level_options(self): eng = engines.testing_engine( @@ -2266,11 +2232,6 @@ class EngineEventsTest(fixtures.TestBase): with e1.connect() as conn: conn.execute(select(1)) conn.execute(select(1).compile(dialect=e1.dialect).statement) - conn.execute(select(1).compile(dialect=e1.dialect)) - - conn._execute_compiled( - select(1).compile(dialect=e1.dialect), (), {} - ) @testing.emits_warning("The garbage collector is trying to clean up") def test_execute_events(self): diff --git a/test/sql/test_query.py b/test/sql/test_query.py index 5d7788fcf1..72b6bff738 100644 --- a/test/sql/test_query.py +++ b/test/sql/test_query.py @@ -12,7 +12,6 @@ from sqlalchemy import Integer from sqlalchemy import intersect from sqlalchemy import literal from sqlalchemy import literal_column -from sqlalchemy import MetaData from sqlalchemy import not_ from sqlalchemy import or_ from sqlalchemy import select @@ -271,29 +270,6 @@ class QueryTest(fixtures.TablesTest): [], ) - def test_compiled_execute(self, connection): - users = self.tables.users - connection.execute(users.insert(), dict(user_id=7, user_name="jack")) - s = ( - select(users) - .where(users.c.user_id == bindparam("id")) - .compile(connection) - ) - eq_(connection.execute(s, dict(id=7)).first()._mapping["user_id"], 7) - - def test_compiled_insert_execute(self, connection): - users = self.tables.users - connection.execute( - users.insert().compile(connection), - dict(user_id=7, user_name="jack"), - ) - s = ( - select(users) - .where(users.c.user_id == bindparam("id")) - .compile(connection) - ) - eq_(connection.execute(s, dict(id=7)).first()._mapping["user_id"], 7) - def test_repeated_bindparams(self, connection): """Tests that a BindParam can be used more than once. @@ -778,50 +754,6 @@ class QueryTest(fixtures.TablesTest): [(7, "jack"), (8, "fred")], ) - def test_expanding_in_dont_alter_compiled(self, connection): - """test for issue #5048""" - - class NameWithProcess(TypeDecorator): - impl = String - cache_ok = True - - def process_bind_param(self, value, dialect): - return value[3:] - - users = Table( - "users", - MetaData(), - Column("user_id", Integer, primary_key=True), - Column("user_name", NameWithProcess()), - ) - - connection.execute( - users.insert(), - [ - dict(user_id=7, user_name="AB jack"), - dict(user_id=8, user_name="BE fred"), - dict(user_id=9, user_name="GP ed"), - ], - ) - - stmt = ( - select(users) - .where(users.c.user_name.in_(bindparam("uname", expanding=True))) - .order_by(users.c.user_id) - ) - - compiled = stmt.compile(testing.db) - eq_(len(compiled._bind_processors), 1) - - eq_( - connection.execute( - compiled, {"uname": ["HJ jack", "RR fred"]} - ).fetchall(), - [(7, "jack"), (8, "fred")], - ) - - eq_(len(compiled._bind_processors), 1) - @testing.skip_if(["mssql"]) def test_bind_in(self, connection): """test calling IN against a bind parameter. diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 486d4199ac..4d73eb9931 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -3115,7 +3115,7 @@ class BinaryTest(fixtures.TablesTest, AssertsExecutionResults): compiled = select(cast(literal(util.b("foo")), LargeBinary)).compile( dialect=testing.db.dialect, compile_kwargs={"literal_binds": True} ) - result = connection.execute(compiled) + result = connection.execute(compiled.statement) eq_(result.scalar(), util.b("foo")) def test_bind_processor_no_dbapi(self): -- 2.47.3