Skip to content

Commit 76fa5bc

Browse files
zzzeekRamazan Elsunkaev
authored and
Ramazan Elsunkaev
committed
doc fixes
* clarify merge behavior for non-present attributes, references sqlalchemy#7687 * fix AsyncSession in async_scoped_session documentation, name the scoped session AsyncScopedSession, fixes: sqlalchemy#7671 * Use non-deprecated execute() style in sqltypes JSON examples, fixes: sqlalchemy#7633 * Add note regarding mitigation for MagicStack/asyncpg#727, fixes sqlalchemy#7245 Fixes: sqlalchemy#7671 Fixes: sqlalchemy#7633 Fixes: sqlalchemy#7245 Change-Id: Ic40b4378ca321367a912864f4eddfdd9714fe217
1 parent b2980cb commit 76fa5bc

File tree

4 files changed

+49
-23
lines changed

4 files changed

+49
-23
lines changed

doc/build/orm/extensions/asyncio.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -712,10 +712,10 @@ constructor::
712712
from sqlalchemy.ext.asyncio import async_scoped_session
713713
from sqlalchemy.ext.asyncio import AsyncSession
714714

715-
async_session_factory = sessionmaker(some_async_engine, class_=_AsyncSession)
716-
AsyncSession = async_scoped_session(async_session_factory, scopefunc=current_task)
715+
async_session_factory = sessionmaker(some_async_engine, class_=AsyncSession)
716+
AsyncScopedSession = async_scoped_session(async_session_factory, scopefunc=current_task)
717717

718-
some_async_session = AsyncSession()
718+
some_async_session = AsyncScopedSession()
719719

720720
:class:`_asyncio.async_scoped_session` also includes **proxy
721721
behavior** similar to that of :class:`.scoped_session`, which means it can be
@@ -728,10 +728,10 @@ the usual ``await`` keywords are necessary, including for the
728728
some_async_session.add(some_object)
729729

730730
# use the AsyncSession via the context-local proxy
731-
await AsyncSession.commit()
731+
await AsyncScopedSession.commit()
732732

733733
# "remove" the current proxied AsyncSession for the local context
734-
await AsyncSession.remove()
734+
await AsyncScopedSession.remove()
735735

736736
.. versionadded:: 1.4.19
737737

doc/build/orm/session_state_management.rst

+8-5
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,14 @@ When given an instance, it follows these steps:
204204
key if not located locally.
205205
* If the given instance has no primary key, or if no instance can be found
206206
with the primary key given, a new instance is created.
207-
* The state of the given instance is then copied onto the located/newly
208-
created instance. For attributes which are present on the source
209-
instance, the value is transferred to the target instance. For mapped
210-
attributes which aren't present on the source, the attribute is
211-
expired on the target instance, discarding its existing value.
207+
* The state of the given instance is then copied onto the located/newly created
208+
instance. For attribute values which are present on the source instance, the
209+
value is transferred to the target instance. For attribute values that aren't
210+
present on the source instance, the corresponding attribute on the target
211+
instance is :term:`expired` from memory, which discards any locally
212+
present value from the target instance for that attribute, but no
213+
direct modification is made to the database-persisted value for that
214+
attribute.
212215

213216
If the ``load=True`` flag is left at its default,
214217
this copy process emits events and will load the target object's

lib/sqlalchemy/dialects/postgresql/asyncpg.py

+19
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,25 @@
9696
stale, nor can it retry the statement as the PostgreSQL transaction is
9797
invalidated when these errors occur.
9898
99+
Disabling the PostgreSQL JIT to improve ENUM datatype handling
100+
---------------------------------------------------------------
101+
102+
Asyncpg has an `issue <https://github.com/MagicStack/asyncpg/issues/727>`_ when
103+
using PostgreSQL ENUM datatypes, where upon the creation of new database
104+
connections, an expensive query may be emitted in order to retrieve metadata
105+
regarding custom types which has been shown to negatively affect performance.
106+
To mitigate this issue, the PostgreSQL "jit" setting may be disabled from the
107+
client using this setting passed to :func:`_asyncio.create_async_engine`::
108+
109+
engine = create_async_engine(
110+
"postgresql+asyncpg://user:password@localhost/tmp",
111+
connect_args={"server_settings": {"jit": "off"}},
112+
)
113+
114+
.. seealso::
115+
116+
https://github.com/MagicStack/asyncpg/issues/727
117+
99118
""" # noqa
100119

101120
import collections

lib/sqlalchemy/sql/sqltypes.py

+17-13
Original file line numberDiff line numberDiff line change
@@ -1904,7 +1904,7 @@ class JSON(Indexable, TypeEngine[Any]):
19041904
with engine.connect() as conn:
19051905
conn.execute(
19061906
data_table.insert(),
1907-
data = {"key1": "value1", "key2": "value2"}
1907+
{"data": {"key1": "value1", "key2": "value2"}}
19081908
)
19091909
19101910
**JSON-Specific Expression Operators**
@@ -2000,20 +2000,22 @@ class JSON(Indexable, TypeEngine[Any]):
20002000
20012001
**Support for JSON null vs. SQL NULL**
20022002
2003-
When working with NULL values, the :class:`_types.JSON`
2004-
type recommends the
2003+
When working with NULL values, the :class:`_types.JSON` type recommends the
20052004
use of two specific constants in order to differentiate between a column
2006-
that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string
2007-
of ``"null"``. To insert or select against a value that is SQL NULL,
2008-
use the constant :func:`.null`::
2005+
that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string of
2006+
``"null"``. To insert or select against a value that is SQL NULL, use the
2007+
constant :func:`.null`. This symbol may be passed as a parameter value
2008+
specifically when using the :class:`_types.JSON` datatype, which contains
2009+
special logic that interprets this symbol to mean that the column value
2010+
should be SQL NULL as opposed to JSON ``"null"``::
20092011
20102012
from sqlalchemy import null
2011-
conn.execute(table.insert(), json_value=null())
2013+
conn.execute(table.insert(), {"json_value": null()})
20122014
20132015
To insert or select against a value that is JSON ``"null"``, use the
20142016
constant :attr:`_types.JSON.NULL`::
20152017
2016-
conn.execute(table.insert(), json_value=JSON.NULL)
2018+
conn.execute(table.insert(), {"json_value": JSON.NULL})
20172019
20182020
The :class:`_types.JSON` type supports a flag
20192021
:paramref:`_types.JSON.none_as_null` which when set to True will result
@@ -2114,12 +2116,14 @@ def __init__(self, none_as_null=False):
21142116
"""Construct a :class:`_types.JSON` type.
21152117
21162118
:param none_as_null=False: if True, persist the value ``None`` as a
2117-
SQL NULL value, not the JSON encoding of ``null``. Note that
2118-
when this flag is False, the :func:`.null` construct can still
2119-
be used to persist a NULL value::
2119+
SQL NULL value, not the JSON encoding of ``null``. Note that when this
2120+
flag is False, the :func:`.null` construct can still be used to
2121+
persist a NULL value, which may be passed directly as a parameter
2122+
value that is specially interpreted by the :class:`_types.JSON` type
2123+
as SQL NULL::
21202124
21212125
from sqlalchemy import null
2122-
conn.execute(table.insert(), data=null())
2126+
conn.execute(table.insert(), {"data": null()})
21232127
21242128
.. note::
21252129
@@ -2461,7 +2465,7 @@ class ARRAY(
24612465
24622466
connection.execute(
24632467
mytable.insert(),
2464-
data=[1,2,3]
2468+
{"data": [1,2,3]}
24652469
)
24662470
24672471
The :class:`_types.ARRAY` type can be constructed given a fixed number

0 commit comments

Comments
 (0)