Commit Graph

17684 Commits

Author SHA1 Message Date
Lysandros Nikolaou b8ab31e7f1 Add explicit multi-threaded tests and support free-threaded build
Implemented initial support for free-threaded Python by adding new tests
and reworking the test harness and GitHub Actions to include Python 3.13t
and Python 3.14t in test runs. Two concurrency issues have been identified
and fixed: the first involves initialization of the ``.c`` collection on a
``FromClause``, a continuation of 🎫`12302`, where an optional mutex
under free-threading is added; the second involves synchronization of the
pool "first_connect" event, which first received thread synchronization in
🎫`2964`, however under free-threading the creation of the mutex
itself runs under the same free-threading mutex. Initial pull request and
test suite courtesy Lysandros Nikolaou.

py313t: yes
py314t: yes
Fixes: #12881
Closes: #12882
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12882
Pull-request-sha: 53d65d96b9

Co-authored-by: Mike Bayer <mike_mp@zzzcomputng.com>
Change-Id: I2e4f2e9ac974ab6382cb0520cc446b396d9680a6
2025-10-02 10:08:01 -04:00
Michael Bayer 29db79c71f Merge "skip windows/macosx for GC sensitive tests" into main 2025-09-30 17:29:16 +00:00
Mike Bayer ce51ba50b2 copy 2.0 changelog for unblock python 3.14
Change-Id: I2f7c94a01cb8d081f1bde8dc6685eaccba19f5f2
(cherry picked from commit 7cd36dabf6)
2025-09-30 11:27:55 -04:00
Mike Bayer 3f6dd98ae4 skip windows/macosx for GC sensitive tests
can't get these to pass on GH actions anymore,
something has changed.

Change-Id: Iecd78b7f959def69b0a016f8341fef035a0d6d39
2025-09-29 22:17:30 -04:00
Michael Bayer ecd1788f23 Merge "lock down format_docs_code.py to specific paths" into main 2025-09-29 18:16:16 +00:00
Mike Bayer 828ca9d243 Squashed commit of the following:
commit 24ff4a8bba
Author: yuanoOo <zhaomingyuan.zmy@digital-engine.com>
Date:   Sun Sep 28 16:28:57 2025 +0800

    docs: Add OceanBase SQLAlchemy plugin to dialects documentation

    - Add OceanBase entry to External Dialects table
    - Add link to oceanbase-sqlalchemy plugin repository
    - References: https://github.com/oceanbase/ecology-plugins/tree/main/oceanbase-sqlalchemy-plugin

Change-Id: I6d99421e5e931d8306416e3afdb14e65e88f9be1
2025-09-29 12:16:13 -04:00
Mike Bayer 9f16251b64 lock down format_docs_code.py to specific paths
the script too quick to pick up on dot directories,
random .py files I have in my local checkout, etc.

Change-Id: I6eb66ddd3598495a420d9e4fc0f644b60fb3ec6d
2025-09-29 11:56:05 -04:00
Mike Bayer 2e058575c2 some tox readability improvements
Change-Id: Iffc9a41b4a42330eb1e71704b0efdee94387af98
2025-09-26 15:59:11 -04:00
Michael Bayer de92e8d3e9 Merge "use standard path for asyncio create w/ exception handler" into main 2025-09-23 19:55:54 +00:00
Michael Bayer a11e98a67e Merge "add create_type to Enum" into main 2025-09-23 14:51:45 +00:00
Mike Bayer 3d7022a9c8 use standard path for asyncio create w/ exception handler
Refactored all asyncio dialects so that exceptions which occur on failed
connection attempts are appropriately wrapped with SQLAlchemy exception
objects, allowing for consistent error handling.

Fixes: #11956
Change-Id: Ic3fdbf334f059f92b03896b6429efa50968ca8a8
2025-09-23 10:45:22 -04:00
Mike Bayer 89a4174a8d Improve asyncpg exception hierarchy and asyncio hierarchies overall
The "emulated" exception hierarchies for the asyncio
drivers such as asyncpg, aiomysql, aioodbc, etc. have been standardized
on a common base :class:`.EmulatedDBAPIException`, which is now what's
available from the :attr:`.StatementException.orig` attribute on a
SQLAlchemy :class:`.DBAPIException` object.   Within :class:`.EmulatedDBAPIException`
and the subclasses in its hiearchy, the original driver-level exception is
also now avaliable via the :attr:`.EmulatedDBAPIException.orig` attribute,
and is also available from :class:`.DBAPIException` directly using the
:attr:`.DBAPIException.driver_exception` attribute.

Added additional emulated error classes for the subclasses of
``asyncpg.exception.IntegrityError`` including ``RestrictViolationError``,
``NotNullViolationError``, ``ForeignKeyViolationError``,
``UniqueViolationError`` ``CheckViolationError``,
``ExclusionViolationError``.  These exceptions are not directly thrown by
SQLAlchemy's asyncio emulation, however are available from the
newly added :attr:`.DBAPIException.driver_exception` attribute when a
:class:`.IntegrityError` is caught.

Fixes: #8047
Change-Id: I6a34e85b055265c087b0615f7c573be8582b3486
2025-09-23 09:49:19 -04:00
Mike Bayer fbb623d9ce add create_type to Enum
Added new parameter :paramref:`.Enum.create_type` to the Core
:class:`.Enum` class. This parameter is automatically passed to the
corresponding :class:`_postgresql.ENUM` native type during DDL operations,
allowing control over whether the PostgreSQL ENUM type is implicitly
created or dropped within DDL operations that are otherwise targeting
tables only. This provides control over the
:paramref:`_postgresql.ENUM.create_type` behavior without requiring
explicit creation of a :class:`_postgresql.ENUM` object.

Fixes: #10604
Change-Id: I450003ec2a2a65c119fe7ca8ff201392ce6b91e1
2025-09-21 12:15:49 -04:00
Michael Bayer f4f5b1931a Merge "Apply nested for joined eager m2o w/ GROUP BY, DISTINCT" into main 2025-09-21 16:14:46 +00:00
Mike Bayer ba8efc5944 Apply nested for joined eager m2o w/ GROUP BY, DISTINCT
Fixed issue where joined eager loading would fail to use the "nested" form
of the query when GROUP BY or DISTINCT were present if the eager joins
being added were many-to-ones, leading to additional columns in the columns
clause which would then cause errors.  The check for "nested" is tuned to
be enabled for these queries even for many-to-one joined eager loaders, and
the "only do nested if it's one to many" aspect is now localized to when
the query only has LIMIT or OFFSET added.

Fixes: #11226
Change-Id: I0b4b71cacfe1c6a25d0924e0954ceced1e399ca1
2025-09-21 11:01:46 -04:00
Mike Bayer fb3243475e remove _py3k suffixes from test files
on the theme of 2.0/2.1 are relatively similar right now, do
some more cleanup removing the py3k suffixes that we dont need anymore.

I'm not sure that the logic that would search for these suffixes is
even present anymore and I would guess we removed it when we removed
py2k support.  However, I am planning on possibly bringing it back
for some of the py314 stuff, so I still want to be able to do
suffix stuff.  that will be for another patch.

Change-Id: I929e6edd922f8d5f943acce77191fb1e3035b42c
2025-09-20 18:31:25 -04:00
Michael Bayer 1239df3597 Merge "deprecate ARRAY.any(), ARRAY.all(), postgresql.Any(), postgresql.All()" into main 2025-09-20 21:29:29 +00:00
Mike Bayer efd49a19a4 deprecate ARRAY.any(), ARRAY.all(), postgresql.Any(), postgresql.All()
The :meth:`_types.ARRAY.Comparator.any` and
:meth:`_types.ARRAY.Comparator.all` methods for the :class:`_types.ARRAY`
type are now deprecated for removal; these two methods along with
:func:`_postgresql.Any` and :func:`_postgresql.All` have been legacy for
some time as they are superseded by the :func:`_sql.any_` and
:func:`_sql.all_` functions, which feature more intutive use.

Fixes: #10821
Change-Id: I8eb3bbcb98af4ee60a21767dc3bdac771cbc0b4c
2025-09-20 16:39:28 -04:00
Michael Bayer a5fdbb086e Merge "Use ARRAY type for any_(), all_() coercion" into main 2025-09-20 20:34:07 +00:00
Mike Bayer aaa85f707e Use ARRAY type for any_(), all_() coercion
Fixed issue where the :func:`_sql.any_` and :func:`_sql.all_` aggregation
operators would not correctly coerce the datatype of the compared value, in
those cases where the compared value were not a simple int/str etc., such
as a Python ``Enum`` or other custom value.   This would lead to execution
time errors for these values.  This issue is essentially the same as
🎫`6515` which was for the now-legacy :meth:`.ARRAY.any` and
:meth:`.ARRAY.all` methods.

Fixes: #12874
Change-Id: I980894c23b9974bc84d584a1a4c5fae72dded6d3
2025-09-20 14:24:48 -04:00
Michael Bayer 408b8f14fb Merge "refactor test_sqlite into a package" into main 2025-09-20 18:12:11 +00:00
Michael Bayer 3eab3db295 Merge "raise for ENUM/DOMAIN with reserved type name and no schema" into main 2025-09-20 18:11:57 +00:00
KapilDagur 555a18ac02 raise for ENUM/DOMAIN with reserved type name and no schema
A :class:`.CompileError` is raised if attempting to create a PostgreSQL
:class:`_postgresql.ENUM` or :class:`_postgresql.DOMAIN` datatype using a
name that matches a known pg_catalog datatype name, and a default schema is
not specified.   These types must be explicit within a schema in order to
be differentiated from the built-in pg_catalog type.  The "public" or
otherwise default schema is not chosen by default here since the type can
only be reflected back using the explicit schema name as well (it is
otherwise not visible due to the pg_catalog name).  Pull request courtesy
Kapil Dagur.

We originally thought we were going to do some default logic for the
default / "public" schema however this produces a type that is not
symmetric to its reflection, since the schema name must be explicit
for our current reflection queries.

So since it's an extremely bad idea to make an ENUM/DOMAIN with a
reserved type name anyway, we raise a compileerror if the type
has a known name.   this is not robust against other names that
might exist in pg_catalog or other schemas that are in the search
path with these names.  People just have to know what they're doing
here, the error here only covers a small subset of real world cases.

Fixes: #12761
Closes: #12822
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12822
Pull-request-sha: 793cf27be2

Change-Id: I9df9c216ab4102f06685a64ae7e55db1b3a9535e
2025-09-20 11:29:26 -04:00
Mike Bayer 94e4d8dcd5 refactor test_sqlite into a package
this is many years overdue, let's do it while 2.1/2.0 are in
sync and we are far away from 1.4 now

Change-Id: Icf90f957e4d56382a4c91250f55bec4c7abc9d79
2025-09-20 11:27:12 -04:00
Mike Bayer a04deb60ac limit STRICT to appropraite sqlite versions
Change-Id: Id7c302e9a182b0aa2cddd255d44afc3aa7bb77f4
2025-09-19 16:35:44 -04:00
Mike Bayer 9a6854223c fix tests for aggregate_order_by
forgot this doesnt work on sqlite older than 3.44

Change-Id: Icebc2ffaceb078a436a8f61ba583bc05b77f680d
2025-09-19 15:18:39 -04:00
Michael Bayer 4b29b262aa Merge "Add note regarding indexes with subscription of jsonb" into main 2025-09-19 18:58:51 +00:00
Federico Caselli 9156fadc3c Add note regarding indexes with subscription of jsonb
Fixes: #12868
Change-Id: I2a5a6a94a7a8f8796d898d4b7e69967a981c59e8
2025-09-19 13:45:25 -04:00
Mike Bayer 8488cc7aa6 add RegistryEvents
Added :class:`_orm.RegistryEvents` event class that allows event listeners
to be established on a :class:`_orm.registry` object. The new class
provides three events: :meth:`_orm.RegistryEvents.resolve_type_annotation`
which allows customization of type annotation resolution that can
supplement or replace the use of the
:paramref:`.registry.type_annotation_map` dictionary, including that it can
be helpful with custom resolution for complex types such as those of
:pep:`695`, as well as :meth:`_orm.RegistryEvents.before_configured` and
:meth:`_orm.RegistryEvents.after_configured`, which are registry-local
forms of the mapper-wide version of these hooks.

note this change was prematurely merged in 7111dc0cba and reverted
for re-review and additional changes.

Fixes: #9832
(cherry picked from commit 7111dc0cba)
Change-Id: I8d69f5c7e0d004f98b7449fefe87a03bb0f29e39
2025-09-19 13:09:08 -04:00
Michael Bayer 0d72cc8fc3 Merge "Add FunctionElement.aggregate_order_by" into main 2025-09-19 16:37:55 +00:00
Mike Bayer 3800869820 clarify clauses argument for order_by, group_by
Change-Id: Idabfde4a6850a2649a2f32dc42d0320f1ec7692d
2025-09-19 10:34:59 -04:00
Reuven Starodubski 459ebc668a Add FunctionElement.aggregate_order_by
Added new generalized aggregate function ordering to functions via the
:func:`_functions.FunctionElement.aggregate_order_by` method, which
receives an expression and generates the appropriate embedded "ORDER BY" or
"WITHIN GROUP (ORDER BY)" phrase depending on backend database.  This new
function supersedes the use of the PostgreSQL
:func:`_postgresql.aggregate_order_by` function, which remains present for
backward compatibility.   To complement the new parameter, the
:paramref:`_functions.aggregate_strings.order_by` which adds ORDER BY
capability to the :class:`_functions.aggregate_strings` dialect-agnostic
function which works for all included backends. Thanks much to Reuven
Starodubski with help on this patch.

Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com>
Fixes: #12853
Closes: #12856
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12856
Pull-request-sha: d93fb591751227eb1f96052ea3ad449f511f70b3

Change-Id: I8eb41ff2d57695963a358b5f0017ca9372f15f70
2025-09-19 09:38:57 -04:00
Mike Bayer 02c9d3ab43 unmapped_dataclass
Reworked the handling of classes which extend from MappedAsDataclass but
are not themselves mapped, i.e. the declarative base as well as any
mixins or abstract classes.  These classes as before are turned into
real dataclasses, however a scan now takes place across the mapped
elements such as mapped_column(), relationship(), etc. so that we may
also take into account dataclasses.field-specific parameters like
init=False, repr, etc.  The main use case for this is so that mixin
dataclasses may make use of "default" in fields while not being rejected
by the dataclasses constructor.  The generated classes are more
functional as dataclasses in a standalone fashion as well, even though
this is not their intended use.  As a standalone dataclass, the one
feature that does not work is a field that has
a default with init=False, because we still need to have a
mapped_column() or similar present at the class level for the class
to work as a superclass.

The change also addes the :func:`_orm.unmapped_dataclass` decorator
function, which may be used
to create unmapped superclasses in a mapped hierarchy that is using the
:func:`_orm.mapped_dataclass` decorator to create mapped dataclasses.
Previously there was no way to use unmapped dataclass mixins with
the decorator approach.

Finally, the warning added in 2.0 for 🎫`9350` is turned into
an error as mentioned for 2.1, since we're deep into dataclass hierarchy
changes here.

Fixes: #12854
Change-Id: I11cd8c628d49e9ff1bdbda8a09f4112b40d84be7
2025-09-18 15:17:18 -04:00
Michael Bayer 8bb8c1a6d6 Merge "Fix get_columns sqlite reflection rejecting tables with WITHOUT_ROWID and/or STRICT for generated column case" into main 2025-09-15 21:55:45 +00:00
Mike Bayer 5333228bd7 Revert "add RegistryEvents"
This reverts commit 7111dc0cba.

Review had 18 comments still open
2025-09-15 17:26:29 -04:00
Tip ten Brink d526cedef3 Fix get_columns sqlite reflection rejecting tables with WITHOUT_ROWID and/or STRICT for generated column case
Fixed issue where SQLite table reflection would fail for tables using
``WITHOUT ROWID`` and/or ``STRICT`` table options when the table contained
generated columns. The regular expression used to parse ``CREATE TABLE``
statements for generated column detection has been updated to properly
handle these SQLite table options that appear after the column definitions.
Pull request courtesy Tip ten Brink.

Fixes: #12864

Closes: #12865
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12865
Pull-request-sha: 833420afc7

Change-Id: Ia25c05746055a66234531b4f1275bd3a2f3b44ad
2025-09-15 09:48:33 -04:00
Michael Bayer 3e151fc411 Merge "add RegistryEvents" into main 2025-09-15 13:42:17 +00:00
Mike Bayer 13f569fd61 remove confusing "with_parent()" from query-enabled properties example
references: #12862
Change-Id: I22ee9fa0c566458a465867e307a77c2eb0ddcdd0
2025-09-13 09:55:14 -04:00
Mike Bayer e7ff28e21e do the mypy dance
version 1.18.1.  lots of i have no idea situations.
just add ignores, seems pretty pointless

Change-Id: Ieb1466df3f45fa6b8d11ccd36c7164645740ba35
2025-09-12 20:24:24 -04:00
Mike Bayer adabce3aa6 Add function mapped_as_dataclass
Added new decorator :func:`_orm.mapped_as_dataclass`, which is a function
based form of :meth:`_orm.registry.mapped_as_dataclass`; the method form
:meth:`_orm.registry.mapped_as_dataclass` does not seem to be correctly
recognized within the scope of :pep:`681` in recent mypy versions.

The new function is tested and mentioned in the docs, in 2.1 in a
subsequent patch (probably the one that adds unmapped_dataclass also)
we'll switch this new decorator to be the prominent one.

also alphabetize mapping_api.rst.  while the summary box at the top
auto-sorts, have the sidebar alpha also, it's kind of weird how
these were in no order at all

Fixes: #12855
Change-Id: If98724fd466004ec4c8a312a0cbf1c934a6ce9e3
2025-09-10 14:53:12 -04:00
Mike Bayer 7111dc0cba add RegistryEvents
Added :class:`_orm.RegistryEvents` event class that allows event listeners
to be established on a :class:`_orm.registry` object. The new class
provides three events: :meth:`_orm.RegistryEvents.resolve_type_annotation`
which allows customization of type annotation resolution that can
supplement or replace the use of the
:paramref:`.registry.type_annotation_map` dictionary, including that it can
be helpful with custom resolution for complex types such as those of
:pep:`695`, as well as :meth:`_orm.RegistryEvents.before_configured` and
:meth:`_orm.RegistryEvents.after_configured`, which are registry-local
forms of the mapper-wide version of these hooks.

Fixes: #9832
Change-Id: I32b55de8625ec435edf916a91e65f61fda50cd51
2025-09-09 11:27:29 -04:00
Mike Bayer 8f7138326c doc updates, localize test fixtures
testing with types is inherently awkward and subject
to changes in python interpreters (such as all the recent python 3.14
stuff we had them fix), but in this suite we already have a lot of
types that are defined inline inside of test methods.   so since that's
how many of the tests work anyway, organize the big series of pep-695
and pep-593 structures into fixtures or individual tests to make
the whole suite easier to follow.   pyright complains quite a lot
about this, so if this becomes a bigger issue for say mypy /pep484
target, we may have to revisit (which I'd likely do with more ignores)
or if function/method-local type declarations with global becomes a runtime
issue in py3.15 or something, we can revisit then where we would in
theory need to convert the entire suite, which I'd do with a more
consistent naming style for everything.

but for now try to go with fixtures / local type declarations so that
we dont have to wonder where all these types are used.

Change-Id: Ibe8f447eaa10f5e927b1122c8b608f11a5f5bc97
2025-09-06 20:20:00 -04:00
Michael Bayer e76b607e67 Merge "liberalize pep695 matching" into main 2025-09-06 22:58:23 +00:00
Mike Bayer a737e965c7 liberalize pep695 matching
after many days of discussion we are moving to liberalize the
matching rules used for pep695 to the simple rule that we will resolve
a pep695 type to its immediate ``__value__`` without requiring that
it be present in the type map, however without any further recursive
checks (that is, we will not resolve ``__value__`` of ``__value__``).
This allows the vast majority of simple uses of pep695 types to not
require entries in the type map, including when the type points
to a simple Python type or any type that is present in the type_map.
Also supported is resolution of generic pep695 types against the
right side, including for Annotated types.

The change here in 2.1 will form the base for a revised approach
to the RegistryEvents patch for #9832, which will still provide
the RegistryEvents.resolve_type_annotation hook.   In 2.0, we need
to scale back the warnings that are emitted so portions of this patch
will also be backported including similar changes to the test suite.

Fixes: #12829
Change-Id: Ib6e379793335da3f33f6ca2cd6874a6eaf1e36f4
2025-09-06 12:13:33 -04:00
Mike Bayer 9eb35c6664 interpret NULL in PG enum array values
Fixed issue where selecting an enum array column containing NULL values
would fail to parse properly in the PostgreSQL dialect. The
:func:`._split_enum_values` function now correctly handles NULL entries by
converting them to Python ``None`` values.

Fixes: #12847
Change-Id: I39d10bc1be6b458da7e5d3f4b740f8faafd0adc5
2025-09-05 11:44:17 -04:00
Mike Bayer e263825e3c remove upfront sanitization of entities from joins
ORM entities can now be involved within the SQL expressions used within
:paramref:`_orm.relationship.primaryjoin` and
:paramref:`_orm.relationship.secondaryjoin` parameters without the ORM
entity information being implicitly sanitized, allowing ORM-specific
features such as single-inheritance criteria in subqueries to continue
working even when used in this context.   This is made possible by overall
ORM simplifications that occurred as of the 2.0 series.  The changes here
also provide a performance boost (up to 20%) for certain query compilation
scenarios.

Here we see that we're not only able to remove the
relationships deannotation steps, but we can also change
context -> _get_current_adapter() to be an unconditional
adapter, since the only remaining case where it was conditional
was the polymorphic_adapter.  that adapter is itself
only used for exotic joined inh cases against select
statements (totally not used by anyone) or by abstract
concrete setups.   That lets us remove a whole host
of orm_annotate stuff that doesn't apply anymore.

if this does lead to user regressions in 2.1 it will be
a good reason for us to revisit the complexity here in
any case.

Fixes: #12843
Change-Id: Ic1c6e72d70ec6a27b73495c1a56e9307c9280133
2025-09-03 09:10:03 -04:00
Mike Bayer 2b2f8b4244 move callcount tests to py313, 314
Some other gerrits are making changes to callcounts
so modernize these first

Change-Id: If2125883e36146bfdae8b2e29c0db537985750ac
2025-09-02 17:29:54 -04:00
Mike Bayer 3544d89d2d support omission of standard event listen example
The required targets for before_configured() and after_configured()
are the Mapper (and soon to include registry things as well in 2.1),
update the automatic doc example thing to be able to be skipped
when there are special instructions for the target.

Also updates the event docs a bit, which were very old and
written in more of that "disorganized wall of details" style
that was very hard to unlearn

Change-Id: I729d08e25b721f4c993aa1856038b27643fc95d0
2025-09-02 11:36:14 -04:00
Michael Bayer b3feb9cd3e Merge "warn on failed aliased" into main 2025-08-31 21:10:53 +00:00
Mike Bayer 0439f17fd5 warn on failed aliased
The :func:`_orm.aliased` object now emits warnings when an attribute is
accessed on an aliased class that cannot be located in the target
selectable, for those cases where the :func:`_orm.aliased` is against a
different FROM clause than the regular mapped table (such as a subquery).
This helps users identify cases where column names don't match between the
aliased class and the underlying selectable. When
:paramref:`_orm.aliased.adapt_on_names` is ``True``, the warning suggests
checking the column name; when ``False``, it suggests using the
``adapt_on_names`` parameter for name-based matching.

Fixes: #12838
Change-Id: I4294b57f24dd3fd7741e0bcbd9b521c841ace903
2025-08-31 16:32:58 -04:00