]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/log
thirdparty/sqlalchemy/sqlalchemy.git
38 hours agoCredit Sam Debruyn for the TEXT / NTEXT reflection fix rel_2_0
Mike Bayer [Thu, 13 Aug 2026 13:26:05 +0000 (09:26 -0400)] 
Credit Sam Debruyn for the TEXT / NTEXT reflection fix

Added the contributor credit line to the changelog entry for the
SQL Server TEXT / NTEXT reflection fix.  An equivalent fix had
already been proposed by the reporter in
https://github.com/sqlalchemy/sqlalchemy/pull/13452, which was not
noticed at the time the change was written.

References: #13451
Change-Id: I4f31b71a3a72da7979df5fdf6747dd39e0c5a3eb
(cherry picked from commit 4695cf855a8da83cfefcc4b1f86682c7160a2037)

2 days agoDon't apply a length to reflected TEXT / NTEXT
Mike Bayer [Wed, 12 Aug 2026 19:30:42 +0000 (15:30 -0400)] 
Don't apply a length to reflected TEXT / NTEXT

Fixed issue in SQL Server reflection where ``TEXT`` and ``NTEXT``
columns would be reflected with a spurious length of 16 and 8,
respectively.  These are unlengthed LOB datatypes; the value
originates from the ``sys.columns.max_length`` column, which reports
the size of the in-row LOB pointer rather than a character length for
these types.  The reflected ``TEXT`` and ``NTEXT`` types now have a
``length`` of ``None``, so that a reflected table emits valid DDL when
re-created, which previously failed with "Cannot specify a column
width on data type text".

Fixes: #13451
Change-Id: I8456688fc8d21fe25f326c6bf0f7b13aa1fc838c
(cherry picked from commit 325f71701a8a994c982c781f59bf34f42add88e7)

3 days agoVersion 2.0.53 placeholder
Mike Bayer [Tue, 11 Aug 2026 19:07:26 +0000 (15:07 -0400)] 
Version 2.0.53 placeholder

3 days ago- 2.0.52 rel_2_0_52
Mike Bayer [Tue, 11 Aug 2026 19:03:02 +0000 (15:03 -0400)] 
- 2.0.52

3 days agoMerge "Establish the fixed set of loader path tokens up front" into rel_2_0
Michael Bayer [Tue, 11 Aug 2026 18:44:59 +0000 (18:44 +0000)] 
Merge "Establish the fixed set of loader path tokens up front" into rel_2_0

3 days agoEstablish the fixed set of loader path tokens up front
Mike Bayer [Mon, 10 Aug 2026 13:08:00 +0000 (09:08 -0400)] 
Establish the fixed set of loader path tokens up front

Fixed issue where unpickling an ORM object that were loaded using
loader options making use of wildcard tokens, such as
:func:`_orm.load_only` or :func:`_orm.raiseload` with ``"*"``, would
fail with ``KeyError`` or ``IndexError`` if the process doing the
unpickling had not yet constructed a loader path making use of that
same token.  This would typically be observed when the object were
unpickled in a separate process, such as with the ``spawn`` or
``forkserver`` multiprocessing start methods, the latter of which
became the default on POSIX platforms as of Python 3.14.  The internal
collection of these tokens is now established up front, so that it is
identical in every process.

Fixed issue where a string ending in ``"*"`` passed to a
:class:`_orm.Load` strategy method, such as
``Load(A).joinedload("bs.*")``, would bypass the check which rejects
string attribute names in loader options, silently producing a loader
path that matched nothing.  Such a string now raises
:class:`.ArgumentError` with the same message given for any other
string attribute name.  The bare wildcard ``"*"``, as in
``Load(A).lazyload("*")``, continues to be accepted.

Fixes: #13493
Change-Id: I0e8ddf4168bbea132392dd2dfda9a1ef0daf6436
(cherry picked from commit 73832c396cc2ec41ef3fc0a0e79917424bebab84)

3 days agoReset Session._flushing when a bulk_* call can't begin its transaction
Hamody We [Tue, 11 Aug 2026 14:10:30 +0000 (10:10 -0400)] 
Reset Session._flushing when a bulk_* call can't begin its transaction

Fixed bug where a failed ``Session.bulk_insert_mappings()``,
``Session.bulk_update_mappings()`` or ``Session.bulk_save_objects()`` call
could leave the :class:`_orm.Session` permanently in a "flushing" state.

``Session._bulk_save_mappings()`` set ``self._flushing = True`` and called
``self._autobegin_t()._begin()`` before its ``try`` block, so an exception
raised by ``_begin()`` -- such as ``PendingRollbackError`` when the
transaction still needs a rollback from a prior failed flush -- left
``_flushing`` stuck at ``True``.  As neither ``Session.rollback()`` nor
``Session.close()`` reset the flag, a reused Session then raised
"Session is already flushing" for every subsequent flush.

The flag-set and transaction-begin are moved inside a ``try``/``finally``
that wraps the whole method, matching the shape used by ``Session.flush()``,
so that the flag is always cleared regardless of where the failure occurs.

Fixes: #13485
Closes: #13487
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13487
Pull-request-sha: 4b3283906123068744943fa724722ee63b74e007

Change-Id: I5be8b59db500aacf2a76fe31f9c0c854a8324f70

4 days agoMerge "Copy column defaults in Table.to_metadata" into rel_2_0
Michael Bayer [Tue, 11 Aug 2026 01:47:11 +0000 (01:47 +0000)] 
Merge "Copy column defaults in Table.to_metadata" into rel_2_0

4 days agoGeneralize SQLite paren counting to fix PG CHECK constraint parsing
LeSingh1 [Mon, 20 Jul 2026 17:14:38 +0000 (13:14 -0400)] 
Generalize SQLite paren counting to fix PG CHECK constraint parsing

Fixed reflection of PostgreSQL CHECK constraints where an expression made
up of multiple parenthesized sub-expressions, such as ``(x IS NULL OR y IS
NULL) AND (x IS NULL OR y IS NULL)``, would have its leading and trailing
parentheses incorrectly stripped, producing an unbalanced and
syntactically invalid reflected expression.  Pull request courtesy
Shaurya Singh.

Fixes #13157
Closes: #13303
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13303
Pull-request-sha: 79bb5f3855ab434d9110864bc467bda66de08a2c

Change-Id: I8312a82527b39aeade731fa358cf7d1959e32427
(cherry picked from commit ebb7993232721731c37e472c8ec42f9f40f19a6f)

4 days agoCopy column defaults in Table.to_metadata
goutamadwant [Mon, 10 Aug 2026 13:27:21 +0000 (09:27 -0400)] 
Copy column defaults in Table.to_metadata

``Table.to_metadata()`` reused the original column's ``default``,
``onupdate``, ``server_default``, and ``server_onupdate`` objects.
Attaching those objects to the copied column changed their ``column``
reference, leaving the original column's defaults associated with the
copy.

This change copies each default generator before constructing the new
column.  Sequence defaults are copied into the target metadata
collection so both the original and copied metadata retain their own
sequence objects.

Regression tests verify ownership for client-side defaults, server-side
defaults, on-update values, and sequence defaults.  Existing merge-copy
expectations now assert that each copied default remains associated with
its own column.

Fixes: #13481
Closes: #13482
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13482
Pull-request-sha: 3dfbe0d91c99cd33bb059937478b9ecb398d3613

Change-Id: Ifceb7802028ff8560937b265c2f55ed93e657fc5
(cherry picked from commit 17758bc8f6e8024e58177159941509eaa66bd074)

8 days agopin asyncmy to 0.2.12 or greater
Mike Bayer [Thu, 6 Aug 2026 14:40:33 +0000 (10:40 -0400)] 
pin asyncmy to 0.2.12 or greater

they seem to have fixed a BIT issue

Change-Id: I393fa4423356b94859cca3c282f6bfcfae3a7656
(cherry picked from commit 3ea271cc9653ef9fe12d26f1911aa8d13386cbab)

10 days agoExclude broken argcomplete 3.7.1 from CI nox install
Mike Bayer [Tue, 4 Aug 2026 20:47:04 +0000 (16:47 -0400)] 
Exclude broken argcomplete 3.7.1 from CI nox install

argcomplete 3.7.1, released 2026-08-04, declares requires-python >=3.8
but its completers module uses PEP 585 and PEP 604 syntax in class body
annotations without ``from __future__ import annotations``.  As
argcomplete is an unconditional dependency of nox, this makes ``import
nox`` fail outright on Python 3.8 and 3.9, so every job on those
interpreters errors before the noxfile is even loaded.

Pinning nox itself does not help, as all versions in range depend on
``argcomplete<4,>=1.9.4``, which resolves to 3.7.1 regardless; the
constraint has to be on argcomplete.  The exclusion is version exact so
that an upstream fix is picked up automatically, and is a no-op on
Python 3.10 and above.

Reported upstream at https://github.com/kislyuk/argcomplete/issues/559

Change-Id: I02d92ae9dcdf7cf5ed2b836a717ec04b2cc1a3bf

10 days agoallow prereleases so py315 works
Mike Bayer [Tue, 4 Aug 2026 20:41:00 +0000 (16:41 -0400)] 
allow prereleases so py315 works

Change-Id: I912c02286cb2fa916c7acecb7eb2ea9ca6defef4
(cherry picked from commit 8c4c51907c2e71906d482169510cf5632c1df88b)

10 days agoadd py315 for pullreq/run tests actions. not yet for create wheels
Mike Bayer [Tue, 4 Aug 2026 18:40:33 +0000 (14:40 -0400)] 
add py315 for pullreq/run tests actions.   not yet for create wheels

Change-Id: I574c3a8e2bb2d6beb0b7097665d8600a99e149d7
(cherry picked from commit 37e08f8dda5556c4a60496a1df0986ed773ed116)

10 days agoMerge "add Python 3.15 support" into rel_2_0
Michael Bayer [Tue, 4 Aug 2026 18:39:05 +0000 (18:39 +0000)] 
Merge "add Python 3.15 support" into rel_2_0

10 days agoadd Python 3.15 support
Mike Bayer [Mon, 3 Aug 2026 17:58:31 +0000 (13:58 -0400)] 
add Python 3.15 support

Backport to 2.0 of the 3.15 support added for 2.1, as the issue is
milestoned to 2.0.x.

Add 3.15 to the noxfile Python matrix, and add both the 3.14 and the
3.15 trove classifiers; 3.14 has been in the noxfile matrix here for
some time but was never added to the classifier list.

Repair the auto-generated docstring for MappedAsDataclass subclasses
under 3.15.  Python 3.15 changed dataclasses so that the class
docstring is no longer rendered when the dataclass is created, and is
instead produced by a descriptor the first time __doc__ is read.  The
dataclass setup swaps a constructed __annotations__ onto the class for
the duration of the dataclass call and restores the original in a
finally block, so by the time that deferred render runs the
annotations are gone and the docstring omits them entirely.  Read
__doc__ while the swapped annotations are still in place, so that the
same docstring is produced on every supported Python.

Also port the docstring assertion from the 2.1 test suite; there was
no equivalent coverage here, so this defect would otherwise go
unnoticed on this branch.  As Python 3.8 and earlier still define
typing.Generic.__new__, and declarative classes are Generic subclasses,
the inspect.signature() call dataclasses uses to render this docstring
reports that __new__ rather than the generated __init__ on those
versions; assert the version-appropriate form in each case.

py315: yes

Fixes: #13477
Change-Id: I452a8bb1392a4417194594bd2e1e37b9e56fee26

11 days agoMerge "Improve postgresql inherits docs" into rel_2_0
Michael Bayer [Tue, 4 Aug 2026 02:24:23 +0000 (02:24 +0000)] 
Merge "Improve postgresql inherits docs" into rel_2_0

11 days agoImprove postgresql inherits docs
Federico Caselli [Tue, 28 Jul 2026 18:18:40 +0000 (20:18 +0200)] 
Improve postgresql inherits docs

Clarify that inherited table columns are not copied by default
and provide an example of a function that will copy them.

Change-Id: I17811c1d3500fbb22a015226325004c1d7ade0c6
References: #13446
(cherry picked from commit 102532a2a1473140705de0296915e571eda14961)

2 weeks agodocs: document sequence arguments to any_ and all_
nightcityblade [Tue, 28 Jul 2026 18:09:29 +0000 (14:09 -0400)] 
docs: document sequence arguments to any_ and all_

<!-- Provide a general summary of your proposed changes in the Title field above -->

### Description
<!-- Describe your changes in detail -->

Document that Python sequences passed to `any_()` or `all_()` should be
wrapped in `literal()` to form a SQL expression, and clarify that PostgreSQL
array-parameter adaptation depends on the DBAPI.

Fixes: #13357
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [x] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [ ] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #13456
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13456
Pull-request-sha: fcc704f0909ca21cd998bd0fc3896d02aa0fe2fd

Change-Id: Iac9c79c8e5b0b4762c6d969ed76038ef2ccf972f
(cherry picked from commit 2bf968d4e98158c6a07e83593da4e1e146dcedd3)

2 weeks agotest(mysql): cover ordered from-select upserts
nightcityblade [Tue, 28 Jul 2026 18:06:15 +0000 (14:06 -0400)] 
test(mysql): cover ordered from-select upserts

### Description

Extends the MySQL `INSERT ... FROM SELECT ... ON DUPLICATE KEY UPDATE`
compiler regression test with the ordered-select shape reported in #10675.
This verifies that enabling MySQL 8's row-alias behavior does not append an
invalid `AS new` after the `ORDER BY` clause and continues to use `VALUES()`
for the update expressions.

Fixes #10675

### Checklist

This pull request is:

- [ ] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #13454
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13454
Pull-request-sha: 33cb578407bb1de396d26e2c368d81b3fff8c303

Change-Id: I1c19a34e1fa551e7b4fce9647fdff98ef9a9075a
(cherry picked from commit 52d9ad783f8051efbcbfe8b878cf746f551dfb65)

2 weeks agocorrect '-' to ':' to sync regexp and storage_format (#13463)
Sam Fletcher [Tue, 28 Jul 2026 18:03:11 +0000 (19:03 +0100)] 
correct '-' to ':' to sync regexp and storage_format (#13463)

(cherry picked from commit d25b6ce2ed97d7cc29fed06e3ebe6c68945cb5a6)

3 weeks agoMerge "audit all types for literal_execute() handling" into rel_2_0
Michael Bayer [Thu, 23 Jul 2026 17:18:20 +0000 (17:18 +0000)] 
Merge "audit all types for literal_execute() handling" into rel_2_0

3 weeks agoaudit all types for literal_execute() handling
Mike Bayer [Wed, 22 Jul 2026 15:29:37 +0000 (11:29 -0400)] 
audit all types for literal_execute() handling

Added auditing to the test suite which exercises the literal execute
processors across all datatypes and dialects to ensure that string input is
either appropriately rejected or correctly escaped.  Literal execute
processors are invoked when the :paramref:`.bindparam.literal_execute`
parameter is used with an explicit :func:`.bindparam` object, which
overrides DBAPI-native bind handling to render the value inline with the
statement instead. Datatypes that were updated include the originally
reported SQL Server ``Uuid`` / ``UNIQUEIDENTIFIER`` rendering which now
escapes properly, the :class:`.JSONPATH` type that's currently
PostgreSQL-only, and a full family of numeric types stemming from the
:class:`_types.Float` and :class:`_types.Numeric` bases which now coerce
the value to a number, rejecting non-numeric input.  Thanks to Javid Khan
for helping to identify the issue.

Fixes: #13448
Change-Id: Ic1a0643fa08e6ba92a54b6032355ef66f61fdb89
(cherry picked from commit 4eba6997dc0f4cd103d47bbc78a5aafaf0c137b1)

3 weeks agoescape single quotes in postgresql nextval() identifier rendering
Javid Khan [Tue, 21 Jul 2026 05:53:51 +0000 (01:53 -0400)] 
escape single quotes in postgresql nextval() identifier rendering

Fixed bug in the PostgreSQL dialect where a single quote in a sequence,
table, or schema name, such as one supplied via a ``schema_translate_map``
or an explicit :class:`.Sequence`, could result in a malformed
``nextval()`` statement. The quote is now properly escaped. Pull request
courtesy dxbjavid.

Fixes: #13429
Closes: #13430
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13430
Pull-request-sha: 0c19bcbd85c69b492542c43a693600595cbd0916

Change-Id: I6198d491a8ead7429fb5ac70e0502a6644f06810
(cherry picked from commit dbf2f9583b6767a14a5db3dc40777b6bf0c2c0df)

3 weeks agoBump actions/setup-python from 6 to 7
dependabot[bot] [Mon, 20 Jul 2026 15:12:42 +0000 (15:12 +0000)] 
Bump actions/setup-python from 6 to 7

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

Change-Id: I626f88eaa852c25fe1e01ec3f85b0d28ea481e00

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit b36f38dff498de31bffce513b104eab202bd7d20)

3 weeks agoFix ORM UPDATE..RETURNING cache adaptation with synchronize_session=fetch
Mike Bayer [Sat, 18 Jul 2026 15:59:14 +0000 (11:59 -0400)] 
Fix ORM UPDATE..RETURNING cache adaptation with synchronize_session=fetch

Fixed result-metadata corruption affecting ORM-enabled UPDATE statements
that use .returning() together with synchronize_session="fetch".  In this
configuration the RETURNING clause is rendered in mapper/table column order
rather than the user-requested .returning() order; on a compiled-cache hit,
the cursor result metadata was positionally adapted against the cached
statement's user-requested column order, causing column values to be
returned under the wrong keys (e.g. row[T.a] returning T.b's value).

The mis-adaptation was frequently masked by cached row-getter functions
produced by a prior, correctly-adapted execution, so the wrong values
surfaced most reliably under concurrent execution racing on the shared
compiled cache.  The fix disables result-set adapt_to_context for this
path, mirroring the ORM INSERT and ORM SELECT load paths, since the cached
keymap already carries the correct Column objects.

ORM DELETE statements are not affected: DELETE does not pass through
crud._get_crud_params() and therefore retains the user-requested RETURNING
order; a non-regression DELETE case is included in the test.

Fixes: #13439
Change-Id: If58e93a0bb3220dc5637bc7bcf346d2177529d6d
(cherry picked from commit bd0da4263052b4571f3b16eda3552e134b9b1689)

4 weeks agoUse coercion rules for aliased() against select/union constructs
Rens Groothuijsen [Thu, 16 Jul 2026 00:03:25 +0000 (20:03 -0400)] 
Use coercion rules for aliased() against select/union constructs

Calling :func:`_orm.aliased` against a :func:`_sql.select` or
:func:`_sql.union` / :class:`_sql.CompoundSelect` construct, which
previously failed with an obscure ``AttributeError`` regarding a missing
``.mapper`` attribute, now raises when using SQLAlchemy 2.1, and emits a
deprecation warning under SQLAlchemy 2.0 as it coerces the construct into a
subquery instead.  This matches the behavior of other similar implicit
SELECT-to-FROM coercions.  Pull request courtesy Rens Groothuijsen.

Fixes: #6274
Closes: #12433
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12433
Pull-request-sha: 416dde8509ac05b209400603d9e00bc82aa47c79

Change-Id: I63bdec71074b81fb85bf29e6ca0dd81cbe3f8cb3
(cherry picked from commit 16177b8c73e492e5adaad8f51095f9981831da41)

4 weeks agofix for mypy 2.3.0
Mike Bayer [Thu, 16 Jul 2026 02:02:34 +0000 (22:02 -0400)] 
fix for mypy 2.3.0

Change-Id: I69875630edfcab55895c5319612f068ab2798a39

4 weeks agofix rst doc formatting
Mike Bayer [Sun, 12 Jul 2026 22:57:16 +0000 (18:57 -0400)] 
fix rst doc formatting

Change-Id: If839f4a15bb8b7e0bdd50281ac5559c88a728226
(cherry picked from commit 149572707d5332df77838e9014616dedb0f416e5)

4 weeks agorewrite SQLite in-memory database docs for concurrency
Mike Bayer [Sun, 12 Jul 2026 22:11:21 +0000 (18:11 -0400)] 
rewrite SQLite in-memory database docs for concurrency

Rewrote the "Using a Memory Database in Multiple Threads" section
in the pysqlite dialect docs to lead with the fundamental constraint
that a :memory: database is scoped to a single connection, and is
not suitable for concurrent use without shared cache or full
serialization.

Added a new "Using a Shared-Cache Memory Database" subsection
recommending the file::memory:?cache=shared&uri=true URI approach,
which gives each checkout its own DBAPI connection with independent
transaction state while sharing one in-memory database.  Documented
process-global scoping and named databases for isolation.

Demoted the StaticPool approach to a secondary subsection with a
prominent warning about its single-connection limitation and silent
data loss under concurrent sessions.

Added a corresponding "Using a Memory Database with Multiple
Coroutines" section to the aiosqlite dialect docs, cross-referencing
the pysqlite shared-cache documentation.

References: #13428, #6987
Change-Id: Ic07c5a2a564e8eca19e596267f61051a2aaa0258
(cherry picked from commit 702a7f11dd8a9d3dae30048aa3d2fc0197330d88)

4 weeks agoMerge "fix catastrophic backtracking in sqlite inline unique reflection regex" into...
Michael Bayer [Sat, 11 Jul 2026 21:42:50 +0000 (21:42 +0000)] 
Merge "fix catastrophic backtracking in sqlite inline unique reflection regex" into rel_2_0

4 weeks agofix catastrophic backtracking in sqlite inline unique reflection regex
Javid Khan [Wed, 8 Jul 2026 14:20:43 +0000 (10:20 -0400)] 
fix catastrophic backtracking in sqlite inline unique reflection regex

Fixes: #13419
### Description

While reflecting a SQLite table, `get_unique_constraints` scans the stored
`CREATE TABLE` text (taken verbatim from `sqlite_master.sql`) with an
`INLINE_UNIQUE_PATTERN` to spot inline `UNIQUE` columns. The tail of that
pattern is `[\t ]+[a-z0-9_ ]+?[\t ]+UNIQUE`, where the lazy middle class
itself contains a space, so all three quantifiers can lay claim to the same
space character. When a column definition contains a run of whitespace that
isn't followed by `UNIQUE`, the engine tries every way of splitting that run
across the three quantifiers, which is cubic in the length of the run.

SQLite keeps the original whitespace of a `CREATE TABLE` statement in
`sqlite_master`, so any account that can create a table can leave a long gap
in a column definition and make later reflection of that schema hang.
A small reproduction:

```python
from sqlalchemy import create_engine, inspect

e = create_engine("sqlite://")
with e.begin() as c:
    c.exec_driver_sql(
        "CREATE TABLE t (x INTEGER" + " " * 1000 + "NOT NULL, "
        "y INTEGER NOT NULL UNIQUE)"
    )
inspect(e).get_unique_constraints("t")   # ~11s before, instant after
```

The fix tokenises the inter-keyword whitespace with disjoint classes,
`[\t ]+[a-z0-9_]+(?:[\t ]+[a-z0-9_]+)*?[\t ]+UNIQUE`, so a space only ever
belongs to a separator and never to a token. Valid inline `UNIQUE` columns
reflect exactly as before; I have added a regression test that reflects a
table carrying a long whitespace run and runs in linear time on the new
pattern.

### Checklist

This pull request is:

- [x] A short code fix

Closes: #13398
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13398
Pull-request-sha: e398806f1243897f25c6ef0697200a49df464243

Change-Id: I7e394357162c9d3aad6c7a72d9276321d404ca64
(cherry picked from commit 121a17bb32046b980f120abca4793aad116aa23c)

4 weeks agomigration note on subqueries
jonathan vanasco [Sat, 11 Jul 2026 17:16:58 +0000 (13:16 -0400)] 
migration note on subqueries

Under 2.0, calls to `in_` and `not_in` no longer accept an explicit `.subquery()`.

Passing a `.subquery()` will cause typing issues from MyPy AND will raise runtime warnings.

There was no note of this in the migration guide.  This may be an effect of another change that is disclosed in the migration guide.  If so, I suggest nesting this text (or improved text describing this) under that section for ease in discovery and migration.

Added a note to the 2.0 migration guide.

<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [x] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [ ] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #11107
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/11107
Pull-request-sha: f8669da225bc7687208d2389c6ae3bf3c63f6aaf

Change-Id: Id33779cb126a700d9adebe5f08f9d6c085589db4
(cherry picked from commit c302b2ca46754ea49c5b24fdd8b6375aafb1df96)

5 weeks agoUse _effective_decimal_return_scale in Numeric.result_processor
Kadir Can Ozden [Thu, 9 Jul 2026 15:43:58 +0000 (11:43 -0400)] 
Use _effective_decimal_return_scale in Numeric.result_processor

Fixed an issue in :class:`.Numeric` where the
:paramref:`.Numeric.decimal_return_scale` parameter was ignored when the
DBAPI does not support native decimal objects (i.e.
``dialect.supports_native_decimal`` is ``False``).  In this path the result
processor was computing the conversion scale from
:paramref:`.Numeric.scale` directly, bypassing
:paramref:`.Numeric.decimal_return_scale` entirely.  The behavior now
matches :class:`.Float`, which already used the correct
``_effective_decimal_return_scale`` property. Pull request courtesy Kadir
Can Ozden.

Fixes: #13424
Closes: #13137
Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com>
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13137
Pull-request-sha: 9d5dbc80a4d053b46454c87d56d36b51c672a2dc

Change-Id: Ib671aa9db19c64fe69d95a47a4b8420b96e918b9
(cherry picked from commit 117851648a21cf6cb12430df33913f200a090100)

5 weeks agoupdate for mypy 2.2.0
Mike Bayer [Wed, 8 Jul 2026 22:57:13 +0000 (18:57 -0400)] 
update for mypy 2.2.0

Change-Id: I5478706dd47825bba38a87f81cd4e05e3e596a67
(cherry picked from commit 4009b58467c0f76d318a336894d754adb9ff4f74)

7 weeks agooverride get_select_precolumns() in StrSQLCompiler
Mike Bayer [Wed, 24 Jun 2026 12:49:30 +0000 (08:49 -0400)] 
override get_select_precolumns() in StrSQLCompiler

Fixed issue where :meth:`_sql.Select.get_final_froms` would emit a
deprecation warning when the statement made use of the PostgreSQL-specific
expression argument to :meth:`_sql.Select.distinct`; the same spurious
warning would be emitted when stringifying such a statement without
explicitly using a PostgreSQL dialect.  The fix ensures that this 1.4-era
warning is suppressed under both 2.0 and 2.1.

Note that under SQLAlchemy 2.1, passing an expression to
:meth:`_sql.Select.distinct` is deprecated overall, and is replaced by a
new PostgreSQL-specific construct (see :ticket:`12342`).

Fixes: #13396
Change-Id: I587e24aa7016c56b1d5bfe1048c4b6eb809dfb30
(cherry picked from commit d011fcf9c2532abeae5a686db78b6c1ad1318bce)

7 weeks agoMerge "quote driver name and pass-through keys in pyodbc connect string" into rel_2_0
Michael Bayer [Tue, 23 Jun 2026 18:11:28 +0000 (18:11 +0000)] 
Merge "quote driver name and pass-through keys in pyodbc connect string" into rel_2_0

7 weeks agouse @classmethod per pytest guidance
Mike Bayer [Mon, 22 Jun 2026 15:36:02 +0000 (11:36 -0400)] 
use @classmethod per pytest guidance

Fixed class-scoped pytest fixtures that were defined as instance methods
using ``self``, which is deprecated as of pytest 9.1 and will be removed in
pytest 10. Fixtures are now decorated with a compatibility ``@classmethod``
decorator and use ``cls`` as the first parameter.

In the 2.0 branch, the approach is considerably more complicated
as python 3.7, 3.8, 3.9 doesn't work with this pattern; since the
warning appears in pytest 9.1 and not 9.0, which itself is only
python 3.10+, we use a conditional classmethod wrapper.

in the 2.1 branch, we can just use straight `@classmethod`.

Fixes: #13392
Change-Id: I866de54e22569c9d55eb97dce165670994ec4a57
(cherry picked from commit cd7eeb34d3741c94b2f9476aec7f3386132a71d5)

8 weeks agoquote driver name and pass-through keys in pyodbc connect string
dxbjavid [Wed, 17 Jun 2026 12:49:06 +0000 (08:49 -0400)] 
quote driver name and pass-through keys in pyodbc connect string

Tightened the construction of the ODBC connection string in the pyodbc
connector (as well as the mssql-python connector in 2.1) so that the
driver name, the names of pass-through connection parameters, and values
containing ``}`` are brace-quoted.  Previously a ``}`` in the driver name
or in a pass-through value, or a ``;`` in the name of a pass-through
parameter, could close the surrounding token early and allow the
remainder of the string to be interpreted as additional connection
attributes.  Pull request courtesy dxbjavid.

Fixes: #13380
Closes: #13379
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13379
Pull-request-sha: 34433408bff86a9044be5d431b31688ab6d7578d

Change-Id: I5a0b522e62d306cf6dc59c7f61fe584df02a948d
(cherry picked from commit 8604972666978ca981623c7f415e405bc074663a)

8 weeks agoFix is_pep695 misidentifying Annotated[TypeAliasType] as PEP 695
Mike Bayer [Wed, 17 Jun 2026 22:06:56 +0000 (18:06 -0400)] 
Fix is_pep695 misidentifying Annotated[TypeAliasType] as PEP 695

The is_pep695() function incorrectly identified
Annotated[TypeAliasType, ...] as a PEP 695 type alias because
Annotated's __origin__ attribute returns the first type argument
(the TypeAliasType) rather than Annotated itself.  This caused
_init_column_for_annotation to crash with AttributeError when
attempting to access __value__ on the Annotated wrapper.

Added a check for is_pep593() before recursing through __origin__
in is_pep695(), so Annotated types are correctly excluded.

Fixes: #13386
Change-Id: I36ef83ebbab5abc08bed0131efb552c3fc001911

8 weeks agoVersion 2.0.52 placeholder
Mike Bayer [Mon, 15 Jun 2026 15:41:38 +0000 (11:41 -0400)] 
Version 2.0.52 placeholder

8 weeks ago- 2.0.51 rel_2_0_51
Mike Bayer [Mon, 15 Jun 2026 15:00:12 +0000 (11:00 -0400)] 
- 2.0.51

8 weeks agofix backtracking hang in hstore literal parser
dxbjavid [Fri, 12 Jun 2026 11:19:04 +0000 (07:19 -0400)] 
fix backtracking hang in hstore literal parser

Fixed regular expression in the pure Python hstore result processor,
used when ``use_native_hstore=False`` is set, which could hang on
malformed hstore text containing unterminated quoted segments with
backslashes.  Pull request courtesy dxbjavid.

Fixes: #13370
Closes: #13371
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13371
Pull-request-sha: f5eddae11c435c78f326b70a15357cbaf6d09337

Change-Id: I0d2d7565dc88f56a73b41e2ad20ca1c5a6f738bb
(cherry picked from commit 0c38dfff3025176324996970dfb0c0f3e05ff28d)

2 months agochore: improve sqlalchemy maintenance path (#13351)
lphuc2250gma [Thu, 11 Jun 2026 21:19:57 +0000 (17:19 -0400)] 
chore: improve sqlalchemy maintenance path (#13351)

Co-authored-by: Noa Levi <275430404+lphuc2250gma@users.noreply.github.com>
(cherry picked from commit 41caa189ae948647074d06c5ccc4c292ba20d5f5)

2 months agoDocument quoted_name use for PostgreSQL INHERITS (#13342)
CaoRongkai [Thu, 11 Jun 2026 21:19:16 +0000 (05:19 +0800)] 
Document quoted_name use for PostgreSQL INHERITS (#13342)

(cherry picked from commit ea1a30f4606eeaee7d696e0d1291a3501ff1fc8a)

Change-Id: I7046bd046a8b8818760b6d253ca528f62ed8a95d

2 months agoMerge "allow rollback within _prepare_impl on twophase prepare failure" into rel_2_0
Michael Bayer [Wed, 10 Jun 2026 13:08:52 +0000 (13:08 +0000)] 
Merge "allow rollback within _prepare_impl on twophase prepare failure" into rel_2_0

2 months agoallow rollback within _prepare_impl on twophase prepare failure
Mike Bayer [Tue, 9 Jun 2026 18:47:46 +0000 (14:47 -0400)] 
allow rollback within _prepare_impl on twophase prepare failure

When tpc_prepare() raised during SessionTransaction._prepare_impl(),
the error handler's call to self.rollback() was blocked by the
@declare_states decorator, which had set _next_state to
CHANGE_IN_PROGRESS. This caused IllegalStateChangeError to be raised
instead of the original database exception, masking the real error
and preventing proper cleanup.

Used _expect_state(SessionTransactionState.CLOSED) to temporarily
allow the rollback state transition, matching the existing pattern
used in commit() for the close() call.

Fixes: #13356
Change-Id: Ie8212d5b6f8515340cf9d83c56dcbfa5a7415812
(cherry picked from commit 30d75f9a30beab059b6ce93d2c200fd8944d0eb9)

2 months agorepair xid in psycopg
Federico Caselli [Fri, 5 Jun 2026 19:51:13 +0000 (21:51 +0200)] 
repair xid in psycopg

Repaired bug introduced in :ticket:`13229` where a two-phase
transaction recovery would not return the correct transaction
identifier when generating the identifiers using the ``xid()``
method of the psycopg connection.

Fixes: #13355
Change-Id: Iffe68c1701afaa678fa7b598559dd396d3f8db41
(cherry picked from commit 75cb5aec658196a0bae5d07216d790126ebc0739)

2 months agoRemoved erroneous debug print (#13349)
Bradley Davis [Thu, 4 Jun 2026 19:51:32 +0000 (12:51 -0700)] 
Removed erroneous debug print (#13349)

(cherry picked from commit 563146468ab5da1e4aea7eca2f6bbb09daa03986)

2 months agoHoist loop-invariant set intersection in _get_display_froms
sebastianbreguel [Sun, 31 May 2026 20:12:19 +0000 (16:12 -0400)] 
Hoist loop-invariant set intersection in _get_display_froms

Fixes #13336.

`SelectState._get_display_froms` recomputed a loop-invariant `_cloned_intersection(...)` once per FROM element in each of the three correlation comprehensions, making each branch O(N²) in the number of FROM elements. This hoists the call so it runs once, which is O(N).

`_cloned_intersection` / `_cloned_difference` are pure and return a set, and neither argument changes during the comprehension, so the result is identical. A function-level benchmark asserts `old == new` at every N (full numbers in #13336), and `test/sql/` plus the ORM compilation/query tests pass: 7442 passed, 359 skipped. Net -14 lines.

Per the issue discussion, no changelog entry is included.

### Checklist

This pull request is:

- [x] A short code fix
  - Issue with a runnable demonstration: #13336
  - Behavior-preserving (no logic change), so it is covered by the existing `test/sql/` and ORM compilation/query suites rather than adding new tests.

Closes: #13337
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13337
Pull-request-sha: beba43e77a773a4d9e9d55cc39c7c85ecda6293e

Change-Id: I95b02ffa66ef709c16bf5275924ec03244c19ecb
(cherry picked from commit abfe6cc47c12b87164a63739e3718257b452dac6)

2 months agoAdd ambiguous column support to SimpleResultMetaData
me-saurabhkohli [Fri, 29 May 2026 20:03:40 +0000 (16:03 -0400)] 
Add ambiguous column support to SimpleResultMetaData

Fixed issue where :meth:`.Result.freeze` would lose track of ambiguous
column names present in the original :class:`.CursorResult`, causing
key-based access on the thawed result to silently return a value instead of
raising :class:`.InvalidRequestError`.  The
:class:`.SimpleResultMetaData` now accepts and propagates ambiguous key
information so that frozen, thawed, and pickled results raise consistently
for duplicate column names.  Pull request courtesy Saurabh Kohli.

Fixes: #9427
Closes: #13335
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13335
Pull-request-sha: c03904ece298493ca69bf6e9cbdae23c7fb6a7b0

Change-Id: Ia184f77b442b069e6f9a4f94a967ead41a1704b6
(cherry picked from commit 4fb459aaf05dd9c31ce3ece57c1bbf81ca9855de)

2 months agoMerge "Fix subqueryload losing .and_() criteria when combined with of_type()" into...
Michael Bayer [Thu, 28 May 2026 14:16:59 +0000 (14:16 +0000)] 
Merge "Fix subqueryload losing .and_() criteria when combined with of_type()" into rel_2_0

2 months agoFix lambda statements with non-lambda criteria
cjc0013 [Mon, 25 May 2026 16:46:50 +0000 (12:46 -0400)] 
Fix lambda statements with non-lambda criteria

Fixed issue where :class:`_sql.StatementLambdaElement` would proxy
attribute access through the cached "expected" expression rather than the
resolved expression, causing stale closure-bound parameter values to be
used when a lambda statement was extended with non-lambda criteria such as
an additional ``.where()`` clause.  Courtesy cjc0013.

Fixes: #10827
Closes: #13327
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13327
Pull-request-sha: ec3e6735bf95d62d768f214dd5a49bbfc4fecaa5

Change-Id: I8a32c11f3da63109cf37c39541df8ebfee52b8c5
(cherry picked from commit c41f25b17031d8e9ca3d7e613c0d4dcd78b693fe)

2 months agoFix subqueryload losing .and_() criteria when combined with of_type()
Arya Rizky [Tue, 12 May 2026 19:08:02 +0000 (15:08 -0400)] 
Fix subqueryload losing .and_() criteria when combined with of_type()

Fixed issue where :func:`_orm.subqueryload` combined with
:meth:`.PropComparator.of_type` and :meth:`.PropComparator.and_` would
silently drop the additional filter criteria, causing all related objects
to be loaded instead of only those matching the filter.  The
:class:`.LoaderCriteriaOption` was being constructed against the base
entity rather than the effective entity indicated by
:meth:`.PropComparator.of_type`.  Pull request courtesy Arya Rizky.

Fixes: #13207
Closes: #13290
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13290
Pull-request-sha: b7a8617cdee3757f4af4abdb4ff0090d69bb1fb5

Change-Id: I2c24652ec112511deaf39dbb9d6197e2097904ed
(cherry picked from commit cf3cfa307f5b8cdfbd47b104db38c193503de1c8)

2 months agoFix Session bulk mappings typing for mapped classes
proto-atlas [Mon, 25 May 2026 19:14:40 +0000 (15:14 -0400)] 
Fix Session bulk mappings typing for mapped classes

Fixes #9256.

This updates the annotations for Session.bulk_insert_mappings() and Session.bulk_update_mappings().

The docstrings and runtime behavior already allow either a mapped class or a Mapper object, but the previous annotations only accepted Mapper[Any].

This patch switches those arguments to the existing _EntityBindKey alias, which matches the inputs accepted by _class_to_mapper(): mapped classes and Mapper objects, but not AliasedClass or AliasedInsp.

I also updated the internal _bulk_save_mappings() annotation so the public methods and the private helper stay consistent. The scoped_session proxy output has been kept in sync with tools/generate_proxy_methods.py, and the generator check passes.

I added a typing regression test covering both mapped classes and Mapper objects for the two bulk mapping methods. I confirmed that the mapped-class cases fail with the old annotation and pass with this change.

Checked locally:

python -m pytest -m mypy test/typing/test_mypy.py -k "session.py" -q
python -m mypy ./lib/sqlalchemy
python tools/generate_proxy_methods.py --check
python -m pytest test/orm/dml/test_bulk.py -q
python -m pytest -m mypy test/typing/test_mypy.py -k "not typed_queries.py" -q

I could not run the full typing suite locally because my local Python 3.12 environment does not include string.templatelib. I only skipped typed_queries.py; that file is expected to be covered by SQLAlchemy's Python 3.14 mypy CI job.

Closes: #13322
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13322
Pull-request-sha: bb730f34275a7c40c94e668ecda1131804ba3084

Change-Id: I4c5d516b3933b4e7fae9c844881a61f557a8bb5e
(cherry picked from commit e00937ec549ecc1d2cae49d4fe84fac3d758b6fb)

2 months agoVersion 2.0.51 placeholder
Mike Bayer [Sun, 24 May 2026 19:20:49 +0000 (15:20 -0400)] 
Version 2.0.51 placeholder

2 months ago- 2.0.50 rel_2_0_50
Mike Bayer [Sun, 24 May 2026 19:15:01 +0000 (15:15 -0400)] 
- 2.0.50

2 months agodont produce side effects for do_orm_execute
Mike Bayer [Sun, 24 May 2026 14:05:29 +0000 (10:05 -0400)] 
dont produce side effects for do_orm_execute

Fixed issue where the presence of a do_orm_execute event hook would cause
internal execution options such as yield_per and loader-specific state from
the first orm_pre_session_exec pass to leak into the second pass, leading to
errors when using relationship loaders such as selectinload and immediateload.
The execution options passed to the second compilation pass are now based on
the original options plus only the explicit updates made via
ORMExecuteState.update_execution_options() within the event hook.

Fixes: #13301
Change-Id: Ide64d7202102930b68a2ab903054d538cd2f99dd

2 months agoMerge "Fix ExcludeConstraint not forwarding info to parent constructor" into rel_2_0
Michael Bayer [Wed, 20 May 2026 21:02:40 +0000 (21:02 +0000)] 
Merge "Fix ExcludeConstraint not forwarding info to parent constructor" into rel_2_0

2 months agoimplement _post_inspect for AliasedInsp
Mike Bayer [Wed, 20 May 2026 19:59:10 +0000 (15:59 -0400)] 
implement _post_inspect for AliasedInsp

Fixed issue where using :func:`_orm.with_polymorphic` on a leaf class (a
subclass with no further descendants) or a non-inherited class would fail
with an ``AttributeError`` when used in an ORM statement, due to
:func:`_orm.configure_mappers` not being triggered implicitly. The fix
ensures that :class:`.AliasedInsp` participates in the ``_post_inspect``
hook, triggering mapper configuration during ORM statement compilation.

Fixes: #13319
Change-Id: Ic5910474676be41f8c815dc72c38fca8e20cdeb9
(cherry picked from commit afa94c32a91711b81e4e663cc328837354491315)

2 months agoFix ExcludeConstraint not forwarding info to parent constructor
WiktorB2004 [Wed, 20 May 2026 20:05:41 +0000 (16:05 -0400)] 
Fix ExcludeConstraint not forwarding info to parent constructor

Fixed issue where the :class:`.ExcludeConstraint` construct did not
correctly forward the :paramref:`.ExcludeConstraint.info` parameter to
the superclass, causing user-defined metadata to be lost. Pull request
courtesy Wiktor Byrka.

Fixes: #13317
Closes: #13316
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13316
Pull-request-sha: be7f4fee2c40d1986519e93145471faad61021af
Change-Id: Idc4846f02127d1d39a8c638cb03b0379932e9fd6
(cherry picked from commit cf2984c31d1f3edcfd26801a8ac560d95b52892e)

2 months agoMerge "Fix joinedload + of_type() + and_() invalid SQL for subclass columns" into...
Michael Bayer [Wed, 20 May 2026 20:02:55 +0000 (20:02 +0000)] 
Merge "Fix joinedload + of_type() + and_() invalid SQL for subclass columns" into rel_2_0

2 months agoMerge "Fix floordiv (//) for float/numeric by int with div_is_floordiv dialects"...
Michael Bayer [Wed, 20 May 2026 19:53:22 +0000 (19:53 +0000)] 
Merge "Fix floordiv (//) for float/numeric by int with div_is_floordiv dialects" into rel_2_0

2 months agoFix joinedload + of_type() + and_() invalid SQL for subclass columns
Joaquin Hui Gomez [Wed, 1 Apr 2026 17:29:38 +0000 (13:29 -0400)] 
Fix joinedload + of_type() + and_() invalid SQL for subclass columns

Fixed issue where using :func:`_orm.joinedload` with
:meth:`.PropComparator.of_type` targeting a joined-table subclass combined
with :meth:`.PropComparator.and_` referencing a column on that subclass
would generate invalid SQL, where the subclass column was not adapted to
the subquery alias.  Pull request courtesy Joaquin Hui Gomez.

Fixes #13203

Closes: #13206
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13206
Pull-request-sha: ba55b0c3e2a8dae28a1c7d7ae646e3480a04425c

Change-Id: I78fe4672649d1d5498e3bc653e5d943ccb55dafd
(cherry picked from commit e04e4b2b58ef9581b3a5e4129e719b0b707b446a)

2 months agoFix floordiv (//) for float/numeric by int with div_is_floordiv dialects
OSS Contributor [Mon, 23 Mar 2026 14:44:40 +0000 (10:44 -0400)] 
Fix floordiv (//) for float/numeric by int with div_is_floordiv dialects

Fixed issue where floor division (``//``) between a :class:`.Float` or
:class:`.Numeric` numerator and an :class:`.Integer` denominator would omit
the ``FLOOR()`` SQL wrapper on dialects where
:attr:`.Dialect.div_is_floordiv` is ``True`` (the default, including
PostgreSQL and SQLite).  ``FLOOR()`` is now applied if either the
denominator or the numerator is a non-integer, so that expressions such as
``float_col // int_col`` render as ``FLOOR(float_col / int_col)`` instead
of the incorrect ``float_col / int_col``.  Pull request courtesy r266-tech.

Fixes: #10528
Closes: #13191
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13191
Pull-request-sha: c9cbc47c877e19c91f912556b4ead6cd26e3cfe6

Change-Id: I5f9f02d966aa6ccee214a2c5cc27a73a4292da03
(cherry picked from commit a4c7dbc49e820e4eaf111b618b20d80e6b5ddc43)

2 months agoFix trivial PyPy failures
mattip [Wed, 20 May 2026 17:47:17 +0000 (13:47 -0400)] 
Fix trivial PyPy failures

<!-- Provide a general summary of your proposed changes in the Title field above -->

### Description

Fixes: #13274
References: #9154

There were two relatively causes to some of the ~21 failures on PyPy:
- weakrefs may be deleted but the objects not finalized on PyPy. This manifests as `ref.obj() is None` I added a test for the `release()` case that also failed on CPython before the fix.
- a condition added in 2022 for missing sqllite3 behaviour is no longer necessary, and is now causing a failure

In order to run the changes in CI, I added PyPy to the PR CI run. Before merging I will revert that change. There are still a number of failures with PyPy around different error messages, different inspect.signatures and one sticky problem with the pure-python datetime.py that actually comes from CPython. I will continue to work on them, but they are not specific to sqlalchemy.

Note the CI run is ~6 minutes where the CPython ones are ~3 minutes. This is expected, since PyPy's JIT does not kick in on short tests, and the base compiler is about 2x slower.

### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [ ] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #13276
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13276
Pull-request-sha: 00472f32f64827325f071150e8b6ecf1fbe9f22e

Change-Id: Id5d4ba37cf8db2345a948f973d7b1710910359a1
(cherry picked from commit 56edb237cb652bed221a377cdc2ae2b7b835dd61)

2 months agoMerge "document postgresql_nulls_not_distinct" into rel_2_0
Michael Bayer [Wed, 20 May 2026 14:05:42 +0000 (14:05 +0000)] 
Merge "document postgresql_nulls_not_distinct" into rel_2_0

2 months agoAdjust TypeError message to Python 3.15
Karolina Surma [Tue, 19 May 2026 14:20:38 +0000 (10:20 -0400)] 
Adjust TypeError message to Python 3.15

<!-- Provide a general summary of your proposed changes in the Title field above -->

### Description
The `.fromisoformat()` error message tested in `test_no_string()` changed in Python 3.15, this fixes the test.

See #13308 for the `rel_2_0` branch.

### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [ ] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [x] A short code fix (in a test, therefore I didn’t create an issue)
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #13307
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13307
Pull-request-sha: 90bc13fc416ea45ba5429d5f8ecffc24b108c1b1

Change-Id: I461d71b0fad18fa4f108102bb1c22c0e980fc70e
(cherry picked from commit f07ad99839105f254df4e640ab851bcc6910168c)

2 months agorobustly handle reconnect param across all pymysql variants
Mike Bayer [Tue, 19 May 2026 13:40:01 +0000 (09:40 -0400)] 
robustly handle reconnect param across all pymysql variants

Fixed issue in aiomysql and asyncmy dialects that appears as of using
pymysql 1.2.0; the dialects were not properly taking into account logic
that detects the argument signature of pymysql's ``ping()`` method which
was added as part of :ticket:`10492`.

We add a "does ping have reconnect" check for all three DBAPIs
individually.  To suit asyncmy's use of cython we also needed to
adjust vendored getargspec() routines.

Fixes: #13306
Change-Id: Iad90ec6cfe9ee3b99736dd2153264090e7f76be1
(cherry picked from commit b3b8d88d1e4cec04c2dceb9c374631e9b692ba58)

2 months agodocument postgresql_nulls_not_distinct
David Lord [Sun, 17 May 2026 20:09:16 +0000 (16:09 -0400)] 
document postgresql_nulls_not_distinct

<!-- Provide a general summary of your proposed changes in the Title field above -->

### Description
<!-- Describe your changes in detail -->

https://github.com/sqlalchemy/sqlalchemy/issues/8240 and https://github.com/sqlalchemy/sqlalchemy/pull/9834 added support for `NULLS NOT DISTINCT` to the PostgreSQL dialect, but didn't add it to the docs (only the change log). This adds a section to the "Constraint Options" section of the PostgreSQL dialect docs.

### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [x] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [ ] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

**Have a nice day!**

Closes: #13279
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13279
Pull-request-sha: cdc858cd88fbf86661662147210f9587117aa593

Change-Id: I3f2c8fe346d3235fa8ba12c4d9ab712ddb840230
(cherry picked from commit 57dcfdacaa75ddac3a9246512f3deac4aef10cf0)

2 months agoadd update to black 26.3.1 commit to blame ignore
Federico Caselli [Sun, 17 May 2026 20:08:09 +0000 (22:08 +0200)] 
add update to black 26.3.1 commit to blame ignore

Change-Id: I06a2e72d99db2f836b0a8fb18a99e4ea08d4bf43

2 months agoremove redundant deserializer assignment from asyncpg dialect (#13287)
Henry Cai [Sun, 17 May 2026 20:02:37 +0000 (13:02 -0700)] 
remove redundant deserializer assignment from asyncpg dialect (#13287)

(cherry picked from commit 120a967505efb4a50a9134bf45b8e88aebb9f483)

3 months agoMerge "update to black 26.3.1" into rel_2_0
Federico Caselli [Sun, 10 May 2026 20:24:31 +0000 (20:24 +0000)] 
Merge "update to black 26.3.1" into rel_2_0

3 months agoupdate to black 26.3.1
Federico Caselli [Fri, 8 May 2026 20:48:58 +0000 (22:48 +0200)] 
update to black 26.3.1

Closes: #13280
Change-Id: Ifbb77dd6d2a1c228ae97fcf8160f40e975edc57c
(cherry picked from commit 1e1c0084b1804eaae8b7f089435241a2b8f4be60)

3 months agocollect pep8 errors
Mike Bayer [Sun, 10 May 2026 15:30:00 +0000 (11:30 -0400)] 
collect pep8 errors

run each command in a try/except (they print out error messages
regardless) and report at the end on all individual runs.

Change-Id: I347c04f5c49c69daadf9f5f9e7c6c488cdf27f35
(cherry picked from commit 3c650cede44e74b0a1939652034debc9fa74759c)

3 months agosupport mypy 2.0
Mike Bayer [Thu, 7 May 2026 15:54:58 +0000 (11:54 -0400)] 
support mypy 2.0

mypy just went to 2.0.

and there seems to be...

exactly one "type: ignore" to remove and...that's it?

well OK!

Change-Id: I29f919641acc0e970b566c850063db7ecad70ed9
(cherry picked from commit dcb36d73bbf6a8e6e780aae3c5ae40e8d03bec3a)

3 months agoMerge "Fixes: #10673: make declared_attr covariant" into rel_2_0
Michael Bayer [Thu, 7 May 2026 15:32:26 +0000 (15:32 +0000)] 
Merge "Fixes: #10673: make declared_attr covariant" into rel_2_0

3 months agoReplace logging.WARN by logging.WARNING (#13277)
Léo Gallot [Tue, 5 May 2026 19:01:21 +0000 (21:01 +0200)] 
Replace logging.WARN by logging.WARNING (#13277)

(cherry picked from commit ffc32e517dd3e89ed3f74b78d71d452fc8663aa3)

3 months agolimit pypy to one build, fix typo (#13275)
Matti Picus [Mon, 4 May 2026 12:51:32 +0000 (15:51 +0300)] 
limit pypy to one build, fix typo (#13275)

(cherry picked from commit f353f623271087bfe47f4b7271b35578046c59b5)
Change-Id: I41ccb411b78d132cd5aa6c517d4583c85217d900

3 months agorestore skip of 3.14t with cext and greenlet
Federico Caselli [Sun, 3 May 2026 19:27:32 +0000 (21:27 +0200)] 
restore skip of 3.14t with cext and greenlet

Change-Id: Ia75ab15c73f5a93f5eb2b6b99870aab824d0a43d
(cherry picked from commit a50a9097d33614197fc8a41b788237f933455bc0)

3 months agoBump pypa/cibuildwheel from 3.3.0 to 3.4.1 (#13271)
dependabot[bot] [Sat, 2 May 2026 18:33:39 +0000 (20:33 +0200)] 
Bump pypa/cibuildwheel from 3.3.0 to 3.4.1 (#13271)

* Bump pypa/cibuildwheel from 3.3.0 to 3.4.1

Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.3.0 to 3.4.1.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.3.0...v3.4.1)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
* remove wheels for 3.13t since it's deprecated

Change-Id: I51157a09e7b01d5b23adc10d9a4b386776dedf7e

* remove tests from 3.13t

Change-Id: I73bb2761d07b0c8f549a4ba8ee7299dec6907df7

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Federico Caselli <cfederico87@gmail.com>
(cherry picked from commit 583e2c4a0cb4ae4659a0d4c268d606b10f107ffa)

# Conflicts:
# .github/workflows/create-wheels.yaml
# .github/workflows/run-test.yaml
# noxfile.py

3 months agoBump actions/checkout from 4 to 6 (#13273)
dependabot[bot] [Thu, 30 Apr 2026 19:57:42 +0000 (21:57 +0200)] 
Bump actions/checkout from 4 to 6 (#13273)

Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit db9b991551325d0194524b79e63f3af9f497b78a)

3 months agoBump actions/setup-python from 5 to 6 (#13270)
dependabot[bot] [Thu, 30 Apr 2026 19:53:11 +0000 (21:53 +0200)] 
Bump actions/setup-python from 5 to 6 (#13270)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 57ccf3e4ed3e020998325f886220c19bf9e1e6a4)

3 months agodocs: fix typo pool_echo -> echo_pool (#13269)
Léo Gallot [Thu, 30 Apr 2026 19:51:19 +0000 (21:51 +0200)] 
docs: fix typo pool_echo -> echo_pool (#13269)

(cherry picked from commit 046c434d33c803accaaf65bd1b5c4e4f28bd2d77)

3 months agoFixes: #10673: make declared_attr covariant
Luiz Felipe Neves [Thu, 30 Apr 2026 17:06:25 +0000 (13:06 -0400)] 
Fixes: #10673: make declared_attr covariant
<!-- Provide a general summary of your proposed changes in the Title field above -->

### Description
<!-- Describe your changes in detail -->
I made declared_attr covariant as suggested in #10673. mypy didn't seem to complain. Added a regression test for the use case that was asked for. Unfortunately, it seems like using `Mapped[int | UUID]` directly in the Protocol won't work:

```python
class CompareProtocol(Protocol):
    id: Mapped[int | UUID]
```

Because mypy will see this as a settable variable and not as a SQLAlchemy descriptor. Using `@property` instead seems to work and it's what I used in the test (perhaps it should be documented as the way to achieve this?):

```python
class CompareProtocol(Protocol):
    @property
    def id(self) -> Mapped[int | UUID]: ...
```

### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)

-->

This pull request is:

- [ ] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
- [X] A short code fix
- please include the issue number, and create an issue if none exists, which
  must include a complete example of the issue.  one line code fixes without an
  issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.   one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
  include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.

Closes: #13266
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13266
Pull-request-sha: 8edd2841f4bbe61f8bb9bc15a7a57e0560698779

Change-Id: I7d63ad43df0ab34ee7c7389a007191be91efa574
(cherry picked from commit f1dfe10237d754ae25b9790c9a9e4d9defccb52b)

3 months agodocs: fix incorrect execution context class reference (#13254)
Léo Gallot [Wed, 29 Apr 2026 19:56:29 +0000 (21:56 +0200)] 
docs: fix incorrect execution context class reference (#13254)

(cherry picked from commit 65192be2a46964e6934f54aab4a05218f9c4c871)

3 months agonarrow scope of _correct_for_mysql_bugs_88718_96365
Mike Bayer [Mon, 20 Apr 2026 13:30:35 +0000 (09:30 -0400)] 
narrow scope of _correct_for_mysql_bugs_88718_96365

Narrowed the scope of the internal workaround for MySQL bugs `#88718
<https://bugs.mysql.com/bug.php?id=88718>`_ and `#96365
<https://bugs.mysql.com/bug.php?id=96365>`_ so that it is only applied
where needed: MySQL 8.0.1 through 8.0.13 (where bug 88718 is present), and
on systems with ``lower_case_table_names=2`` (where bug 96365 applies,
typically macOS).  Previously the workaround was applied unconditionally
for all MySQL 8.0+ versions, which caused a ``KeyError`` during foreign key
reflection when the database user lacked SELECT privileges on referred
tables.

Fixes: #13243
Change-Id: I7c29f67d1653c5cd32f29e098f038fea1d56117b
(cherry picked from commit 530e1f71e74263ee9e23245071af2557aa65d425)

3 months agodocs: fix typo 'nad' -> 'and' in DefaultDialect.construct_arguments docstring (#13245)
Bojun Chai [Mon, 20 Apr 2026 20:30:20 +0000 (04:30 +0800)] 
docs: fix typo 'nad' -> 'and' in DefaultDialect.construct_arguments docstring (#13245)

Co-authored-by: Bojun Chai <bojunchai@microsoft.com>
(cherry picked from commit 053a90668acd235cc03b5209470e24c9742121db)

3 months agohandle asyncpg InternalClientError
Mike Bayer [Fri, 17 Apr 2026 20:13:53 +0000 (16:13 -0400)] 
handle asyncpg InternalClientError

Fixed issue where the asyncpg driver could throw an insufficiently-handled
exception ``InternalClientError`` under some circumstances, leading to
connections not being properly marked as invalidated.

Fixes: #13241
References: https://github.com/MagicStack/asyncpg/issues/1069
Change-Id: Iaaf551b3d7b062cce62e13b441161583a484615f
(cherry picked from commit 70de8780239972233fe2b7b4121251698bbf19ca)

3 months agoFix 'compatiblity' typo in sqlite dialect docstring (#13237)
Mukunda Rao Katta [Thu, 16 Apr 2026 18:56:30 +0000 (11:56 -0700)] 
Fix 'compatiblity' typo in sqlite dialect docstring (#13237)

Co-authored-by: MukundaKatta <mukundakatta@users.noreply.github.com>
(cherry picked from commit 1f27a0deefd86c14fd2de3b80e24aeb00c154da7)

4 months agoImprove pg two-phase transactions
Federico Caselli [Mon, 13 Apr 2026 21:53:00 +0000 (23:53 +0200)] 
Improve pg two-phase transactions

Improve handling of two phase transaction identifiers for PostgreSQL
when the identifier is provided by the user.
As part of this change the psycopg dialect was updated to use the DBAPI
two phase transaction API instead of executing the SQL directly.

Fixes: #13229
Change-Id: If8301a7253b4a0c88e5323c9a052c3a9fa258780
(cherry picked from commit 08cef20f4a2bfbeda61abfe6caee975190f0794c)

4 months agoImprove escaping in pysqlcipher
Federico Caselli [Mon, 13 Apr 2026 20:26:48 +0000 (22:26 +0200)] 
Improve escaping in pysqlcipher

Escape key and pragma values when utilizing the pysqlcipher dialect.

Fixes: #13230
Change-Id: I7583577a3e00e2f2986e50f32136a9ef005eb28a
(cherry picked from commit 87f17c2e59cd27e20e7badc685c482e788fb2711)

4 months agoVersion 2.0.50 placeholder
Mike Bayer [Fri, 3 Apr 2026 16:38:35 +0000 (12:38 -0400)] 
Version 2.0.50 placeholder

4 months ago- 2.0.49 rel_2_0_49
Mike Bayer [Fri, 3 Apr 2026 16:34:12 +0000 (12:34 -0400)] 
- 2.0.49

4 months agocorrect that last exclude, only the greenlet builds
Mike Bayer [Fri, 3 Apr 2026 16:19:52 +0000 (12:19 -0400)] 
correct that last exclude, only the greenlet builds

Change-Id: I6944fdbf6c96b2b462bc91040bc347f9736c754a

4 months agodisable failing actions combos so we can get a green
Mike Bayer [Fri, 3 Apr 2026 16:02:03 +0000 (12:02 -0400)] 
disable failing actions combos so we can get a green

Change-Id: I120b14b03f6baeff67be7195a07f47e29e67ba84

4 months agoMerge "really remove cx_oracle from test setup" into rel_2_0
Michael Bayer [Wed, 1 Apr 2026 20:28:19 +0000 (20:28 +0000)] 
Merge "really remove cx_oracle from test setup" into rel_2_0

4 months agoreally remove cx_oracle from test setup
Mike Bayer [Wed, 1 Apr 2026 20:10:17 +0000 (16:10 -0400)] 
really remove cx_oracle from test setup

in 6282bcef11781b5ded26d48b22b5f we tried to disable cx_oracle
testing bug failed because pyproject was still pulling it in.
really fix this time

Change-Id: If5a46bf1ad9a9ee48e8693cccdc4b8b40cee392d

4 months agoupdate for mypy 1.20.0
Mike Bayer [Wed, 1 Apr 2026 18:31:21 +0000 (14:31 -0400)] 
update for mypy 1.20.0

Change-Id: I95f72b8a1818b79d01d26531202199f24fe3b808
(cherry picked from commit 120eb13e8e08d167fafd56590aaeb3c048f7afcc)

4 months agoaccommodate subclass mapper in post-loader entity_isa check
Mike Bayer [Sun, 29 Mar 2026 17:46:39 +0000 (13:46 -0400)] 
accommodate subclass mapper in post-loader entity_isa check

Fixed issue where using chained loader options such as
:func:`_orm.selectinload` after :func:`_orm.joinedload` with
:meth:`_orm.PropComparator.of_type` for a polymorphic relationship would
not properly apply the chained loader option. The loader option is now
correctly applied when using a call such as
``joinedload(A.b.of_type(poly)).selectinload(poly.SubClass.c)`` to eagerly
load related objects.

Fixes: #13209
Change-Id: I2d14838f1b1a9a2b18dc52137910dab0bccf0dd5
(cherry picked from commit 2ac8c1a7c71400c1bc13f54f3c05cfd2e3ae1442)