mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-14 20:57:19 -04:00
document thread safety workaround for lambda statements
Change-Id: Idb7840ff64487ef985087a28bb6e96088e6a392e References: #8098
This commit is contained in:
Vendored
+35
-14
@@ -1258,11 +1258,13 @@ SELECTs with LIMIT/OFFSET are correctly rendered and cached.
|
||||
Using Lambdas to add significant speed gains to statement production
|
||||
--------------------------------------------------------------------
|
||||
|
||||
.. deepalchemy:: This technique is generally non-essential except in very performance
|
||||
intensive scenarios, and intended for experienced Python programmers.
|
||||
While fairly straightforward, it involves metaprogramming concepts that are
|
||||
not appropriate for novice Python developers. The lambda approach can be
|
||||
applied to at a later time to existing code with a minimal amount of effort.
|
||||
.. deprecated:: 1.4 The lambda statement feature is being considered
|
||||
for deprecation in SQLAlchemy and removal from documentation for 2.0. The
|
||||
internal workings have been shown to be not thread safe during construction
|
||||
for multi-lambda statements, and the overall complexity of the feature has
|
||||
proven to be mostly impractical outside of a particular narrow use case
|
||||
in the ORM.
|
||||
|
||||
|
||||
Python functions, typically expressed as lambdas, may be used to generate
|
||||
SQL expressions which are cacheable based on the Python code location of
|
||||
@@ -1296,11 +1298,15 @@ to also having closure variables, which are significant to the whole
|
||||
approach::
|
||||
|
||||
from sqlalchemy import lambda_stmt
|
||||
import threading
|
||||
|
||||
mutex = threading.Lock()
|
||||
|
||||
def run_my_statement(connection, parameter):
|
||||
stmt = lambda_stmt(lambda: select(table))
|
||||
stmt += lambda s: s.where(table.c.col == parameter)
|
||||
stmt += lambda s: s.order_by(table.c.id)
|
||||
with mutex:
|
||||
stmt = lambda_stmt(lambda: select(table))
|
||||
stmt += lambda s: s.where(table.c.col == parameter)
|
||||
stmt += lambda s: s.order_by(table.c.id)
|
||||
|
||||
return connection.execute(stmt)
|
||||
|
||||
@@ -1331,15 +1337,26 @@ objects will run and analyze the given lambda in order to calculate how
|
||||
it should be cached on each run, trying to detect any potential problems.
|
||||
Basic guidelines include:
|
||||
|
||||
* **For multi-threaded applications, a mutex is required when building up
|
||||
statements among multiple lambdas** -
|
||||
this is a discovered limitation in the implementation; while SQLAlchemy
|
||||
developers hope to repair it, code examples are illustrating this
|
||||
usage for now until it can be fixed.
|
||||
|
||||
* **Any kind of statement is supported** - while it's expected that
|
||||
:func:`_sql.select` constructs are the prime use case for :func:`_sql.lambda_stmt`,
|
||||
DML statements such as :func:`_sql.insert` and :func:`_sql.update` are
|
||||
equally usable::
|
||||
|
||||
import threading
|
||||
|
||||
mutex = threading.Lock()
|
||||
|
||||
def upd(id_, newname):
|
||||
stmt = lambda_stmt(lambda: users.update())
|
||||
stmt += lambda s: s.values(name=newname)
|
||||
stmt += lambda s: s.where(users.c.id==id_)
|
||||
with mutex:
|
||||
stmt = lambda_stmt(lambda: users.update())
|
||||
stmt += lambda s: s.values(name=newname)
|
||||
stmt += lambda s: s.where(users.c.id==id_)
|
||||
return stmt
|
||||
|
||||
with engine.begin() as conn:
|
||||
@@ -1351,15 +1368,19 @@ Basic guidelines include:
|
||||
can accommodate ORM functionality completely and used directly with
|
||||
:meth:`_orm.Session.execute`::
|
||||
|
||||
import threading
|
||||
|
||||
mutex = threading.Lock()
|
||||
|
||||
def select_user(session, name):
|
||||
stmt = lambda_stmt(lambda: select(User))
|
||||
stmt += lambda s: s.where(User.name == name)
|
||||
with mutex:
|
||||
stmt = lambda_stmt(lambda: select(User))
|
||||
stmt += lambda s: s.where(User.name == name)
|
||||
|
||||
row = session.execute(stmt).first()
|
||||
return row
|
||||
|
||||
..
|
||||
|
||||
* **Bound parameters are automatically accommodated** - in contrast to SQLAlchemy's
|
||||
previous "baked query" system, the lambda SQL system accommodates for
|
||||
Python literal values which become SQL bound parameters automatically.
|
||||
|
||||
Reference in New Issue
Block a user