This commit is contained in:
2025-05-22 20:25:38 +02:00
parent 09f6750c2b
commit ce03fbf12f
529 changed files with 3353 additions and 3312 deletions

View File

@@ -205,6 +205,7 @@ from .base import PGExecutionContext
from .base import PGIdentifierPreparer
from .base import REGCLASS
from .base import REGCONFIG
from .types import BIT
from .types import BYTEA
from .types import CITEXT
from ... import exc
@@ -237,6 +238,10 @@ class AsyncpgTime(sqltypes.Time):
render_bind_cast = True
class AsyncpgBit(BIT):
render_bind_cast = True
class AsyncpgByteA(BYTEA):
render_bind_cast = True
@@ -566,6 +571,7 @@ class AsyncAdapt_asyncpg_cursor:
async def _executemany(self, operation, seq_of_parameters):
adapt_connection = self._adapt_connection
self.description = None
async with adapt_connection._execute_mutex:
await adapt_connection._check_type_cache_invalidation(
self._invalidate_schema_cache_asof
@@ -818,10 +824,23 @@ class AsyncAdapt_asyncpg_connection(AdaptedConnection):
def ping(self):
try:
_ = self.await_(self._connection.fetchrow(";"))
_ = self.await_(self._async_ping())
except Exception as error:
self._handle_exception(error)
async def _async_ping(self):
if self._transaction is None and self.isolation_level != "autocommit":
# create a tranasction explicitly to support pgbouncer
# transaction mode. See #10226
tr = self._connection.transaction()
await tr.start()
try:
await self._connection.fetchrow(";")
finally:
await tr.rollback()
else:
await self._connection.fetchrow(";")
def set_isolation_level(self, level):
if self._started:
self.rollback()
@@ -1002,6 +1021,7 @@ class PGDialect_asyncpg(PGDialect):
{
sqltypes.String: AsyncpgString,
sqltypes.ARRAY: AsyncpgARRAY,
BIT: AsyncpgBit,
CITEXT: CITEXT,
REGCONFIG: AsyncpgREGCONFIG,
sqltypes.Time: AsyncpgTime,

View File

@@ -303,7 +303,7 @@ Setting Alternate Search Paths on Connect
------------------------------------------
The PostgreSQL ``search_path`` variable refers to the list of schema names
that will be implicitly referred towards when a particular table or other
that will be implicitly referenced when a particular table or other
object is referenced in a SQL statement. As detailed in the next section
:ref:`postgresql_schema_reflection`, SQLAlchemy is generally organized around
the concept of keeping this variable at its default value of ``public``,
@@ -1376,8 +1376,8 @@ Built-in support for rendering a ``ROW`` may be approximated using
Table Types passed to Functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PostgreSQL supports passing a table as an argument to a function, which it
refers towards as a "record" type. SQLAlchemy :class:`_sql.FromClause` objects
PostgreSQL supports passing a table as an argument to a function, which is
known as a "record" type. SQLAlchemy :class:`_sql.FromClause` objects
such as :class:`_schema.Table` support this special form using the
:meth:`_sql.FromClause.table_valued` method, which is comparable to the
:meth:`_functions.FunctionElement.table_valued` method except that the collection
@@ -1868,6 +1868,9 @@ class PGCompiler(compiler.SQLCompiler):
value = value.replace("\\", "\\\\")
return value
def visit_aggregate_strings_func(self, fn, **kw):
return "string_agg%s" % self.function_argspec(fn)
def visit_sequence(self, seq, **kw):
return "nextval('%s')" % self.preparer.format_sequence(seq)
@@ -4114,9 +4117,13 @@ class PGDialect(default.DefaultDialect):
@util.memoized_property
def _fk_regex_pattern(self):
# optionally quoted token
qtoken = '(?:"[^"]+"|[A-Za-z0-9_]+?)'
# https://www.postgresql.org/docs/current/static/sql-createtable.html
return re.compile(
r"FOREIGN KEY \((.*?)\) REFERENCES (?:(.*?)\.)?(.*?)\((.*?)\)"
r"FOREIGN KEY \((.*?)\) "
rf"REFERENCES (?:({qtoken})\.)?({qtoken})\(((?:{qtoken}(?: *, *)?)+)\)" # noqa: E501
r"[\s]?(MATCH (FULL|PARTIAL|SIMPLE)+)?"
r"[\s]?(ON UPDATE "
r"(CASCADE|RESTRICT|NO ACTION|SET NULL|SET DEFAULT)+)?"

View File

@@ -254,7 +254,7 @@ equivalent to psycopg2's ``execute_values()`` handler; an overview of this
feature and its configuration are at :ref:`engine_insertmanyvalues`.
.. versionadded:: 2.0 Replaced psycopg2's ``execute_values()`` fast execution
helper with a native SQLAlchemy mechanism referred towards as
helper with a native SQLAlchemy mechanism known as
:ref:`insertmanyvalues <engine_insertmanyvalues>`.
The psycopg2 dialect retains the ability to use the psycopg2-specific

View File

@@ -293,7 +293,7 @@ class Range(Generic[_T]):
else:
return 0
def __eq__(self, other: Any) -> bool: # type: ignore[override] # noqa: E501
def __eq__(self, other: Any) -> bool:
"""Compare this range to the `other` taking into account
bounds inclusivity, returning ``True`` if they are equal.
"""

View File

@@ -18,7 +18,9 @@ from ...sql import type_api
from ...util.typing import Literal
if TYPE_CHECKING:
from ...engine.interfaces import Dialect
from ...sql.operators import OperatorType
from ...sql.type_api import _LiteralProcessorType
from ...sql.type_api import TypeEngine
_DECIMAL_TYPES = (1231, 1700)
@@ -247,6 +249,14 @@ class INTERVAL(type_api.NativeForEmulated, sqltypes._AbstractInterval):
def python_type(self) -> Type[dt.timedelta]:
return dt.timedelta
def literal_processor(
self, dialect: Dialect
) -> Optional[_LiteralProcessorType[dt.timedelta]]:
def process(value: dt.timedelta) -> str:
return f"make_interval(secs=>{value.total_seconds()})"
return process
PGInterval = INTERVAL