from sqlalchemy.ext.asyncio import async_scoped_session
from sqlalchemy.ext.asyncio import AsyncSession
- async_session_factory = sessionmaker(some_async_engine, class_=_AsyncSession)
- AsyncSession = async_scoped_session(async_session_factory, scopefunc=current_task)
+ async_session_factory = sessionmaker(some_async_engine, class_=AsyncSession)
+ AsyncScopedSession = async_scoped_session(async_session_factory, scopefunc=current_task)
- some_async_session = AsyncSession()
+ some_async_session = AsyncScopedSession()
:class:`_asyncio.async_scoped_session` also includes **proxy
behavior** similar to that of :class:`.scoped_session`, which means it can be
some_async_session.add(some_object)
# use the AsyncSession via the context-local proxy
- await AsyncSession.commit()
+ await AsyncScopedSession.commit()
# "remove" the current proxied AsyncSession for the local context
- await AsyncSession.remove()
+ await AsyncScopedSession.remove()
.. versionadded:: 1.4.19
key if not located locally.
* If the given instance has no primary key, or if no instance can be found
with the primary key given, a new instance is created.
-* The state of the given instance is then copied onto the located/newly
- created instance. For attributes which are present on the source
- instance, the value is transferred to the target instance. For mapped
- attributes which aren't present on the source, the attribute is
- expired on the target instance, discarding its existing value.
+* The state of the given instance is then copied onto the located/newly created
+ instance. For attribute values which are present on the source instance, the
+ value is transferred to the target instance. For attribute values that aren't
+ present on the source instance, the corresponding attribute on the target
+ instance is :term:`expired` from memory, which discards any locally
+ present value from the target instance for that attribute, but no
+ direct modification is made to the database-persisted value for that
+ attribute.
If the ``load=True`` flag is left at its default,
this copy process emits events and will load the target object's
stale, nor can it retry the statement as the PostgreSQL transaction is
invalidated when these errors occur.
+Disabling the PostgreSQL JIT to improve ENUM datatype handling
+---------------------------------------------------------------
+
+Asyncpg has an `issue <https://github.com/MagicStack/asyncpg/issues/727>`_ when
+using PostgreSQL ENUM datatypes, where upon the creation of new database
+connections, an expensive query may be emitted in order to retrieve metadata
+regarding custom types which has been shown to negatively affect performance.
+To mitigate this issue, the PostgreSQL "jit" setting may be disabled from the
+client using this setting passed to :func:`_asyncio.create_async_engine`::
+
+ engine = create_async_engine(
+ "postgresql+asyncpg://user:password@localhost/tmp",
+ connect_args={"server_settings": {"jit": "off"}},
+ )
+
+.. seealso::
+
+ https://github.com/MagicStack/asyncpg/issues/727
+
""" # noqa
import collections
with engine.connect() as conn:
conn.execute(
data_table.insert(),
- data = {"key1": "value1", "key2": "value2"}
+ {"data": {"key1": "value1", "key2": "value2"}}
)
**JSON-Specific Expression Operators**
**Support for JSON null vs. SQL NULL**
- When working with NULL values, the :class:`_types.JSON`
- type recommends the
+ When working with NULL values, the :class:`_types.JSON` type recommends the
use of two specific constants in order to differentiate between a column
- that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string
- of ``"null"``. To insert or select against a value that is SQL NULL,
- use the constant :func:`.null`::
+ that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string of
+ ``"null"``. To insert or select against a value that is SQL NULL, use the
+ constant :func:`.null`. This symbol may be passed as a parameter value
+ specifically when using the :class:`_types.JSON` datatype, which contains
+ special logic that interprets this symbol to mean that the column value
+ should be SQL NULL as opposed to JSON ``"null"``::
from sqlalchemy import null
- conn.execute(table.insert(), json_value=null())
+ conn.execute(table.insert(), {"json_value": null()})
To insert or select against a value that is JSON ``"null"``, use the
constant :attr:`_types.JSON.NULL`::
- conn.execute(table.insert(), json_value=JSON.NULL)
+ conn.execute(table.insert(), {"json_value": JSON.NULL})
The :class:`_types.JSON` type supports a flag
:paramref:`_types.JSON.none_as_null` which when set to True will result
"""Construct a :class:`_types.JSON` type.
:param none_as_null=False: if True, persist the value ``None`` as a
- SQL NULL value, not the JSON encoding of ``null``. Note that
- when this flag is False, the :func:`.null` construct can still
- be used to persist a NULL value::
+ SQL NULL value, not the JSON encoding of ``null``. Note that when this
+ flag is False, the :func:`.null` construct can still be used to
+ persist a NULL value, which may be passed directly as a parameter
+ value that is specially interpreted by the :class:`_types.JSON` type
+ as SQL NULL::
from sqlalchemy import null
- conn.execute(table.insert(), data=null())
+ conn.execute(table.insert(), {"data": null()})
.. note::
connection.execute(
mytable.insert(),
- data=[1,2,3]
+ {"data": [1,2,3]}
)
The :class:`_types.ARRAY` type can be constructed given a fixed number