summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/context.py
Commit message (Collapse)AuthorAgeFilesLines
* apply criteria options from top-level core-only statementMike Bayer2023-04-171-19/+55
| | | | | | | | | | | | | | Made an improvement to the :func:`_orm.with_loader_criteria` loader option to allow it to be indicated in the :meth:`.Executable.options` method of a top-level statement that is not itself an ORM statement. Examples include :func:`_sql.select` that's embedded in compound statements such as :func:`_sql.union`, within an :meth:`_dml.Insert.from_select` construct, as well as within CTE expressions that are not ORM related at the top level. Improved propagation of :func:`_orm.with_loader_criteria` within ORM enabled UPDATE and DELETE statements as well. Fixes: #9635 Change-Id: I088ad91929dc797c06f292f5dc547d48ffb30430
* immediateload lazy relationships named in refresh.attribute_namesMike Bayer2023-02-161-0/+1
| | | | | | | | | | | | | | | | | | The :meth:`_orm.Session.refresh` method will now immediately load a relationship-bound attribute that is explicitly named within the :paramref:`_orm.Session.refresh.attribute_names` collection even if it is currently linked to the "select" loader, which normally is a "lazy" loader that does not fire off during a refresh. The "lazy loader" strategy will now detect that the operation is specifically a user-initiated :meth:`_orm.Session.refresh` operation which named this attribute explicitly, and will then call upon the "immediateload" strategy to actually emit SQL to load the attribute. This should be helpful in particular for some asyncio situations where the loading of an unloaded lazy-loaded attribute must be forced, without using the actual lazy-loading attribute pattern not supported in asyncio. Fixes: #9298 Change-Id: I9b50f339bdf06cdb2ec98f8e5efca2b690895dd7
* generalize adapt_on_names to expect non-named elementsMike Bayer2023-02-101-4/+10
| | | | | | | | | | | | | | | | | | | | The fix in #9217 opened up adapt_on_names to more kinds of expressions than it was prepared for; adjust that logic and also refine in the ORM where we are using it, as we dont need it (yet) for the DML RETURNING use case. Fixed regression introduced in version 2.0.2 due to :ticket:`9217` where using DML RETURNING statements, as well as :meth:`_sql.Select.from_statement` constructs as was "fixed" in :ticket:`9217`, in conjunction with ORM mapped classes that used expressions such as with :func:`_orm.column_property`, would lead to an internal error within Core where it would attempt to match the expression by name. The fix repairs the Core issue, and also adjusts the fix in :ticket:`9217` to not take effect for the DML RETURNING use case, where it adds unnecessary overhead. Fixes: #9273 Change-Id: Ie0344efb12ff7df48f21e71e62dc598c76a6a0de
* Fixed regression when using from_statement in orm context.Mike Bayer2023-02-031-9/+3
| | | | | | | | | | | | Fixed regression when using :meth:`_sql.Select.from_statement` in an ORM context, where matching of columns to SQL labels based on name alone was disabled for ORM-statements that weren't fully textual. This would prevent arbitrary SQL expressions with column-name labels from matching up to the entity to be loaded, which previously would work within the 1.4 and previous series, so the previous behavior has been restored. Fixes: #9217 Change-Id: I5f7ab9710a96a98241388883365e56d308b4daf2
* happy new year 2023Mike Bayer2023-01-031-1/+1
| | | | Change-Id: I625af65b3fb1815b1af17dc2ef47dd697fdc3fb1
* rename 2.0.0b5 to 2.0.0rc1Mike Bayer2022-12-271-1/+1
| | | | | | it's hoped for 2.0.0 final to be next, in early January Change-Id: If4285f0929f4a2895f2bc93d9e8336599b973bcf
* reorganize pre_session_exec around do_orm_executeMike Bayer2022-12-261-14/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | Allow do_orm_execute() events to both receive the complete state of bind_argments, load_options, update_delete_options as they do already, but also allow them to *change* all those things via new execution options. Options like autoflush, populate_existing etc. can now be updated within a do_orm_execute() hook and those changes will take effect all the way through. Took a few tries to get something that covers every case here, in particular horizontal sharding which is consuming those options as well as using context.invoke(), without excess complexity. The good news seems to be that a simple reorg and replacing the "reentrant" boolean with "is this before do_orm_execute is invoked" was all that was needed. As part of this we add a new "identity_token" option allowing this option to be controlled from do_orm_execute() as well as from the outside. WIP Fixes: #7837 Change-Id: I087728215edec8d1b1712322ab389e3f52ff76ba
* include pk cols in refresh() if relationships are requestedMike Bayer2022-12-181-9/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A series of changes and improvements regarding :meth:`_orm.Session.refresh`. The overall change is that primary key attributes for an object are now included in a refresh operation unconditionally when relationship-bound attributes are to be refreshed, even if not expired and even if not specified in the refresh. * Improved :meth:`_orm.Session.refresh` so that if autoflush is enabled (as is the default for :class:`_orm.Session`), the autoflush takes place at an earlier part of the refresh process so that pending primary key changes are applied without errors being raised. Previously, this autoflush took place too late in the process and the SELECT statement would not use the correct key to locate the row and an :class:`.InvalidRequestError` would be raised. * When the above condition is present, that is, unflushed primary key changes are present on the object, but autoflush is not enabled, the refresh() method now explicitly disallows the operation to proceed, and an informative :class:`.InvalidRequestError` is raised asking that the pending primary key changes be flushed first. Previously, this use case was simply broken and :class:`.InvalidRequestError` would be raised anyway. This restriction is so that it's safe for the primary key attributes to be refreshed, as is necessary for the case of being able to refresh the object with relationship-bound secondary eagerloaders also being emitted. This rule applies in all cases to keep API behavior consistent regardless of whether or not the PK cols are actually needed in the refresh, as it is unusual to be refreshing some attributes on an object while keeping other attributes "pending" in any case. * The :meth:`_orm.Session.refresh` method has been enhanced such that attributes which are :func:`_orm.relationship`-bound and linked to an eager loader, either at mapping time or via last-used loader options, will be refreshed in all cases even when a list of attributes is passed that does not include any columns on the parent row. This builds upon the feature first implemented for non-column attributes as part of :ticket:`1763` fixed in 1.4 allowing eagerly-loaded relationship-bound attributes to participate in the :meth:`_orm.Session.refresh` operation. If the refresh operation does not indicate any columns on the parent row to be refreshed, the primary key columns will nonetheless be included in the refresh operation, which allows the load to proceed into the secondary relationship loaders indicated as it does normally. Previously an :class:`.InvalidRequestError` error would be raised for this condition (:ticket:`8703`) * Fixed issue where an unnecessary additional SELECT would be emitted in the case where :meth:`_orm.Session.refresh` were called with a combination of expired attributes, as well as an eager loader such as :func:`_orm.selectinload` that emits a "secondary" query, if the primary key attributes were also in an expired state. As the primary key attributes are now included in the refresh automatically, there is no additional load for these attributes when a relationship loader goes to select for them (:ticket:`8997`) * Fixed regression caused by :ticket:`8126` released in 2.0.0b1 where the :meth:`_orm.Session.refresh` method would fail with an ``AttributeError``, if passed both an expired column name as well as the name of a relationship-bound attribute that was linked to a "secondary" eagerloader such as the :func:`_orm.selectinload` eager loader (:ticket:`8996`) Fixes: #8703 Fixes: #8996 Fixes: #8997 Fixes: #8126 Change-Id: I88dcbc0a9a8337f6af0bc4bcc5b0261819acd1c4
* disable polymorphic adaption in most casesMike Bayer2022-12-071-15/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Improved a fix first made in version 1.4 for :ticket:`8456` which scaled back the usage of internal "polymorphic adapters", that are used to render ORM queries when the :paramref:`_orm.Mapper.with_polymorphic` parameter is used. These adapters, which are very complex and error prone, are now used only in those cases where an explicit user-supplied subquery is used for :paramref:`_orm.Mapper.with_polymorphic`, which includes only the use case of concrete inheritance mappings that use the :func:`_orm.polymorphic_union` helper, as well as the legacy use case of using an aliased subquery for joined inheritance mappings, which is not needed in modern use. For the most common case of joined inheritance mappings that use the built-in polymorphic loading scheme, which includes those which make use of the :paramref:`_orm.Mapper.polymorphic_load` parameter set to ``inline``, polymorphic adapters are now no longer used. This has both a positive performance impact on the construction of queries as well as a substantial simplification of the internal query rendering process. The specific issue targeted was to allow a :func:`_orm.column_property` to refer to joined-inheritance classes within a scalar subquery, which now works as intuitively as is feasible. ORM context, mapper, strategies now use ORMAdapter in all cases instead of straight ColumnAdapter; added some more parameters to ORMAdapter to make this possible. ORMAdapter now includes a "trace" enumeration that identifies the use path for the adapter and can aid in debugging. implement __slots__ for the ExternalTraversal hierarchy up to ORMAdapter. Within this change, we have to change the ClauseAdapter.wrap() method, which is only used in one polymorphic codepath, to use copy.copy() instead of `__dict__` access (apparently `__reduce_ex__` is implemented for objects with `__slots__`), and we also remove pickling ability, which should not be needed for adapters (this might have been needed for 1.3 and earlier in order for Query to be picklable, but none of that state is present within Query / select() / etc. anymore). Fixes: #8168 Change-Id: I3f6593eb02ab5e5964807c53a9fa4894c826d017
* Add tests for issue #8168; slight internal adjustmentsMike Bayer2022-12-051-9/+5
| | | | | | | | | | | | | The issue in #8168 was improved, but not completely fixed, by #8456. This includes some small changes to ORM context that are a prerequisite for getting ORM adaptation to be better. Have these in 2.0.0b4 so that we have at least a better starting point. References: #8168 Change-Id: I51dbe333b156048836d074fbba1d850f9eb67fd2
* Try running pyupgrade on the codeFederico Caselli2022-11-161-11/+6
| | | | | | | | command run is "pyupgrade --py37-plus --keep-runtime-typing --keep-percent-format <files...>" pyupgrade will change assert_ to assertTrue. That was reverted since assertTrue does not exists in sqlalchemy fixtures Change-Id: Ie1ed2675c7b11d893d78e028aad0d1576baebb55
* Improve typings of execution optionsFederico Caselli2022-11-021-2/+2
| | | | | Fixes: #8605 Change-Id: I4aec83b9f321462427c3f4ac941c3b272255c088
* ensure _ORMJoin transfers parententity from left sideMike Bayer2022-10-281-0/+1
| | | | | | | | | | | | | | | | | | Fixed bug involving :class:`.Select` constructs which used a combination of :meth:`.Select.select_from` with an ORM entity followed by :meth:`.Select.join` against the entity sent in :meth:`.Select.select_from`, as well as using plain :meth:`.Select.join_from`, which when combined with a columns clause that didn't explicitly include that entity would then cause "automatic WHERE criteria" features such as the IN expression required for a single-table inheritance subclass, as well as the criteria set up by the :func:`_orm.with_loader_criteria` option, to not be rendered for that entity. The correct entity is now transferred to the :class:`.Join` object that's generated internally, so that the criteria against the left side entity is correctly added. Fixes: #8721 Change-Id: I8266430063e2c72071b7262fdd5ec5079fbcba3e
* ORM bulk insert via executeMike Bayer2022-09-241-32/+141
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * ORM Insert now includes "bulk" mode that will run essentially the same process as session.bulk_insert_mappings; interprets the given list of values as ORM attributes for key names * ORM UPDATE has a similar feature, without RETURNING support, for session.bulk_update_mappings * Added support for upserts to do RETURNING ORM objects as well * ORM UPDATE/DELETE with list of parameters + WHERE criteria is a not implemented; use connection * ORM UPDATE/DELETE defaults to "auto" synchronize_session; use fetch if RETURNING is present, evaluate if not, as "fetch" is much more efficient (no expired object SELECT problem) and less error prone if RETURNING is available UPDATE: howver this is inefficient! please continue to use evaluate for simple cases, auto can move to fetch if criteria not evaluable * "Evaluate" criteria will now not preemptively unexpire and SELECT attributes that were individually expired. Instead, if evaluation of the criteria indicates that the necessary attrs were expired, we expire the object completely (delete) or expire the SET attrs unconditionally (update). This keeps the object in the same unloaded state where it will refresh those attrs on the next pass, for this generally unusual case. (originally #5664) * Core change! update/delete rowcount comes from len(rows) if RETURNING was used. SQLite at least otherwise did not support this. adjusted test_rowcount accordingly * ORM DELETE with a list of parameters at all is also a not implemented as this would imply "bulk", and there is no bulk_delete_mappings (could be, but we dont have that) * ORM insert().values() with single or multi-values translates key names based on ORM attribute names * ORM returning() implemented for insert, update, delete; explcit returning clauses now interpret rows in an ORM context, with support for qualifying loader options as well * session.bulk_insert_mappings() assigns polymorphic identity if not set. * explicit RETURNING + synchronize_session='fetch' is now supported with UPDATE and DELETE. * expanded return_defaults() to work with DELETE also. * added support for composite attributes to be present in the dictionaries used by bulk_insert_mappings and bulk_update_mappings, which is also the new ORM bulk insert/update feature, that will expand the composite values into their individual mapped attributes the way they'd be on a mapped instance. * bulk UPDATE supports "synchronize_session=evaluate", is the default. this does not apply to session.bulk_update_mappings, just the new version * both bulk UPDATE and bulk INSERT, the latter with or without RETURNING, support *heterogenous* parameter sets. session.bulk_insert/update_mappings did this, so this feature is maintained. now cursor result can be both horizontally and vertically spliced :) This is now a long story with a lot of options, which in itself is a problem to be able to document all of this in some way that makes sense. raising exceptions for use cases we haven't supported is pretty important here too, the tradition of letting unsupported things just not work is likely not a good idea at this point, though there are still many cases that aren't easily avoidable Fixes: #8360 Fixes: #7864 Fixes: #7865 Change-Id: Idf28379f8705e403a3c6a937f6a798a042ef2540
* implement batched INSERT..VALUES () () for executemanyMike Bayer2022-09-241-0/+4
| | | | | | | | | | | | | | | | | | | | the feature is enabled for all built in backends when RETURNING is used, except for Oracle that doesn't need it, and on psycopg2 and mssql+pyodbc it is used for all INSERT statements, not just those that use RETURNING. third party dialects would need to opt in to the new feature by setting use_insertmanyvalues to True. Also adds dialect-level guards against using returning with executemany where we dont have an implementation to suit it. execute single w/ returning still defers to the server without us checking. Fixes: #6047 Fixes: #7907 Change-Id: I3936d3c00003f02e322f2e43fb949d0e6e568304
* remove should_nest behavior for contains_eager()Mike Bayer2022-09-231-1/+7
| | | | | | | | | | | | | | | | | | | Fixed regression for 1.4 in :func:`_orm.contains_eager` where the "wrap in subquery" logic of :func:`_orm.joinedload` would be inadvertently triggered for use of the :func:`_orm.contains_eager` function with similar statements (e.g. those that use ``distinct()``, ``limit()`` or ``offset()``). This is not appropriate for :func:`_orm.contains_eager` which has always had the contract that the user-defined SQL statement is unmodified with the exception of adding the appropriate columns. Also includes an adjustment to the assertion in Label._make_proxy() which was there to prevent a fixed label name from being anonymized; if the label is already anonymous, the change should proceed. This logic was being hit before the contains_eager behavior was adjusted. With the adjustment, this code is not used. Fixes: #8569 Change-Id: I161e65041c0162fd2b83cbef40f57a50fcfaf0fd
* refine ruleset to determine when poly adaption should be usedMike Bayer2022-08-291-13/+6
| | | | | | | | | | | | | | Fixed regression appearing in the 1.4 series where a joined-inheritance query placed as a subquery within an enclosing query for that same entity would fail to render the JOIN correctly for the inner query. The issue manifested in two different ways prior and subsequent to version 1.4.18 (related issue #6595), in one case rendering JOIN twice, in the other losing the JOIN entirely. To resolve, the conditions under which "polymorphic loading" are applied have been scaled back to not be invoked for simple joined inheritance queries. Fixes: #8456 Change-Id: Ie4332fadb1dfc670cd31d098a6586a9f6976bcf7
* refine transfer of cached ORM options for selectin, lazyMike Bayer2022-08-171-21/+17
| | | | | | | | | | | | | | | | | | | | | | | | | Fixed issue involving :func:`_orm.with_loader_criteria` where a closure variable used as bound parameter value within the lambda would not carry forward correctly into additional relationship loaders such as :func:`_orm.selectinload` and :func:`_orm.lazyload` after the statement were cached, using the stale originally-cached value instead. This change brings forth a good refinement where we finally realize we shouldn't be testing every ORM option with lots of switches, we just let the option itself be given "here is your uncached version, you are cached, tell us what to do!". the current decision is that strategy loader options used the cached in all cases as they always have, with_loader_criteria uses the uncached, because the uncached will have been invoked with new closure state that we definitely need. The only edge that might not work is if with_loader_criteria referenced an entity that is local to the query, namely a specific AliasedInsp, however that's not a documented case for this. if we had to do that, then we perhaps would introduce a more complex reconcilation logic, and this would also give us the hook to do that. Fixes: #8399 Change-Id: Ided8e2123915131e3f11cf6b06d773039e73797a
* reorg bulk persistence into a separate moduleMike Bayer2022-08-111-1/+44
| | | | | | | | | | | | This restores persistence.py to only functions that are used by unitofwork.py, and all the "bulk" stuff gets its own module bulk_persistence.py. Also fixes up the ORM context class hierarchy for bulk. This is all ahead of the ORM-insert changes coming in, so that the later review can be about logic and not about reorganization. Change-Id: I035896e9e77fcece866d246edf30097cccad0182
* support "SELECT *" for ORM queriesMike Bayer2022-07-101-0/+12
| | | | | | | | | | | | | | | | | | A :func:`_sql.select` construct that is passed a sole '*' argument for ``SELECT *``, either via string, :func:`_sql.text`, or :func:`_sql.literal_column`, will be interpreted as a Core-level SQL statement rather than as an ORM level statement. This is so that the ``*``, when expanded to match any number of columns, will result in all columns returned in the result. the ORM- level interpretation of :func:`_sql.select` needs to know the names and types of all ORM columns up front which can't be achieved when ``'*'`` is used. If ``'*`` is used amongst other expressions simultaneously with an ORM statement, an error is raised as this can't be interpreted correctly by the ORM. Fixes: #8235 Change-Id: Ic8e84491e14acdc8570704eadeaeaf6e16b1e870
* repair yield_per for non-SS dialects and add new optionsMike Bayer2022-07-011-7/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Implemented new :paramref:`_engine.Connection.execution_options.yield_per` execution option for :class:`_engine.Connection` in Core, to mirror that of the same :ref:`yield_per <orm_queryguide_yield_per>` option available in the ORM. The option sets both the :paramref:`_engine.Connection.execution_options.stream_results` option at the same time as invoking :meth:`_engine.Result.yield_per`, to provide the most common streaming result configuration which also mirrors that of the ORM use case in its usage pattern. Fixed bug in :class:`_engine.Result` where the usage of a buffered result strategy would not be used if the dialect in use did not support an explicit "server side cursor" setting, when using :paramref:`_engine.Connection.execution_options.stream_results`. This is in error as DBAPIs such as that of SQLite and Oracle already use a non-buffered result fetching scheme, which still benefits from usage of partial result fetching. The "buffered" strategy is now used in all cases where :paramref:`_engine.Connection.execution_options.stream_results` is set. Added :meth:`.FilterResult.yield_per` so that result implementations such as :class:`.MappingResult`, :class:`.ScalarResult` and :class:`.AsyncResult` have access to this method. Fixes: #8199 Change-Id: I6dde3cbe483a1bf81e945561b60f4b7d1c434750
* create new approach for deeply nested post loader optionsMike Bayer2022-06-181-2/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | Added very experimental feature to the :func:`_orm.selectinload` and :func:`_orm.immediateload` loader options called :paramref:`_orm.selectinload.recursion_depth` / :paramref:`_orm.immediateload.recursion_depth` , which allows a single loader option to automatically recurse into self-referential relationships. Is set to an integer indicating depth, and may also be set to -1 to indicate to continue loading until no more levels deep are found. Major internal changes to :func:`_orm.selectinload` and :func:`_orm.immediateload` allow this feature to work while continuing to make correct use of the compilation cache, as well as not using arbitrary recursion, so any level of depth is supported (though would emit that many queries). This may be useful for self-referential structures that must be loaded fully eagerly, such as when using asyncio. A warning is also emitted when loader options are connected together with arbitrary lengths (that is, without using the new ``recursion_depth`` option) when excessive recursion depth is detected in related object loading. This operation continues to use huge amounts of memory and performs extremely poorly; the cache is disabled when this condition is detected to protect the cache from being flooded with arbitrary statements. Fixes: #8126 Change-Id: I9f162e0a09c1ed327dd19498aac193f649333a01
* Fixed orm not applying fetchFederico Caselli2022-06-041-0/+8
| | | | | | | | Fixed an issue where :meth:`_sql.GenerativeSelect.fetch` would be ignored when executing a statement using the ORM. Fixes: #8091 Change-Id: I6790c7272a71278e90de2529c8bc8ae89e54e288
* revenge of pep 484Mike Bayer2022-05-151-24/+76
| | | | | | trying to get remaining must-haves for ORM Change-Id: I66a3ecbbb8e5ba37c818c8a92737b576ecf012f7
* dont use the label convention for memoized entitiesMike Bayer2022-05-091-10/+38
| | | | | | | | | | Fixed issue where ORM results would apply incorrect key names to the returned :class:`.Row` objects in the case where the set of columns to be selected were changed, such as when using :meth:`.Select.with_only_columns`. Fixes: #8001 Change-Id: If3a2a5d00d15ebc2e9d41494845cfb3b06f80dcc
* inline mypy config; files ignoring type errors for the momentMike Bayer2022-04-281-1/+1
| | | | | | | | | | | | | | | | | | | to simplify pyproject.toml change the remaining files that aren't going to be typed on this first pass (unless of course someone wants to type some of these) to include # mypy: ignore-errors. for the moment, only a handful of ORM modules are to have more type checking implemented. It's important that ignore-errors is used and not "# type: ignore", as in the latter case, mypy doesn't even read the existing types in the file, which makes it impossible to type any files that refer to those modules at all. to simplify ongoing typing work use inline mypy config for remaining files that are "done" for now, indicating the level of type checking they currently have. Change-Id: I98669c1a305c2f0adba85d10b5425541f3fe9533
* pep484 ORM / SQL result supportMike Bayer2022-04-271-2/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | after some experimentation it seems mypy is more amenable to the generic types being fully integrated rather than having separate spin-off types. so key structures like Result, Row, Select become generic. For DML Insert, Update, Delete, these are spun into type-specific subclasses ReturningInsert, ReturningUpdate, ReturningDelete, which is fine since the "row-ness" of these constructs doesn't happen until returning() is called in any case. a Tuple based model is then integrated so that these objects can carry along information about their return types. Overloads at the .execute() level carry through the Tuple from the invoked object to the result. To suit the issue of AliasedClass generating attributes that are dynamic, experimented with a custom subclass AsAliased, but then just settled on having aliased() lie to the type checker and return `Type[_O]`, essentially. will need some type-related accessors for with_polymorphic() also. Additionally, identified an issue in Update when used "mysql style" against a join(), it basically doesn't work if asked to UPDATE two tables on the same column name. added an error message to the specific condition where it happens with a very non-specific error message that we hit a thing we can't do right now, suggest multi-table update as a possible cause. Change-Id: I5eff7eefe1d6166ee74160b2785c5e6a81fa8b95
* pep-484: ORM public API, constructorsMike Bayer2022-04-201-12/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | for the moment, abandoning using @overload with relationship() and mapped_column(). The overloads are very difficult to get working at all, and the overloads that were there all wouldn't pass on mypy. various techniques of getting them to "work", meaning having right hand side dictate what's legal on the left, have mixed success and wont give consistent results; additionally, it's legal to have Optional / non-optional independent of nullable in any case for columns. relationship cases are less ambiguous but mypy was not going along with things. we have a comprehensive system of allowing left side annotations to drive the right side, in the absense of explicit settings on the right. so type-centric SQLAlchemy will be left-side driven just like dataclasses, and the various flags and switches on the right side will just not be needed very much. in other matters, one surprise, forgot to remove string support from orm.join(A, B, "somename") or do deprecations for it in 1.4. This is a really not-directly-used structure barely mentioned in the docs for many years, the example shows a relationship being used, not a string, so we will just change it to raise the usual error here. Change-Id: Iefbbb8d34548b538023890ab8b7c9a5d9496ec6e
* pep-484: session, instancestate, etcMike Bayer2022-04-121-2/+21
| | | | | | | | Also adds some fixes to annotation-based mapping that have come up, as well as starts to add more pep-484 test cases Change-Id: Ia722bbbc7967a11b23b66c8084eb61df9d233fee
* cx_Oracle modernizeMike Bayer2022-04-071-80/+162
| | | | | | | | | | | | | | | | | | | Full "RETURNING" support is implemented for the cx_Oracle dialect, meaning multiple RETURNING rows are now recived for DML statements that produce more than one row for RETURNING. cx_Oracle 7 is now the minimum version for cx_Oracle. Getting Oracle to do multirow returning took about 5 minutes. however, getting Oracle's RETURNING system to integrate with ORM-enabled insert, update, delete, is a big deal because that architecture wasn't really working very robustly, including some recent changes in 1.4 for FromStatement were done in a hurry, so this patch also cleans up the FromStatement situation and begins to establish it more concretely as the base for all ReturnsRows / TextClause ORM scenarios. Fixes: #6245 Change-Id: I2b4e6007affa51ce311d2d5baa3917f356ab961f
* apply loader criteria more specifically when refresh is trueMike Bayer2022-03-281-1/+4
| | | | | | | | | Fixed bug in :func:`_orm.with_loader_criteria` function where loader criteria would not be applied to a joined eager load that were invoked within the scope of a refresh operation for the parent object. Fixes: #7862 Change-Id: If1ac86eaa95880b5ec5bdeee292d6e8000aac705
* support add_cte() for TextualSelectMike Bayer2022-02-231-2/+62
| | | | | | | | | | | Fixed issue where the :meth:`.HasCTE.add_cte` method as called upon a :class:`.TextualSelect` instance was not being accommodated by the SQL compiler. The fix additionally adds more "SELECT"-like compiler behavior to :class:`.TextualSelect` including that DML CTEs such as UPDATE and INSERT may be accommodated. Fixes: #7760 Change-Id: Id97062d882e9b2a81b8e31c2bfaa9cfc5f77d5c1
* pep-484 for sqlalchemy.event; use future annotationsMike Bayer2022-02-151-0/+3
| | | | | | | | | | __future__.annotations mode allows us to use non-string annotations for argument and return types in most cases, but more importantly it removes a large amount of runtime overhead that would be spent in evaluating the annotations. Change-Id: I2f5b6126fe0019713fc50001be3627b664019ede References: #6810
* establish mypy / typing approach for v2.0Mike Bayer2022-02-131-5/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | large patch to get ORM / typing efforts started. this is to support adding new test cases to mypy, support dropping sqlalchemy2-stubs entirely from the test suite, validate major ORM typing reorganization to eliminate the need for the mypy plugin. * New declarative approach which uses annotation introspection, fixes: #7535 * Mapped[] is now at the base of all ORM constructs that find themselves in classes, to support direct typing without plugins * Mypy plugin updated for new typing structures * Mypy test suite broken out into "plugin" tests vs. "plain" tests, and enhanced to better support test structures where we assert that various objects are introspected by the type checker as we expect. as we go forward with typing, we will add new use cases to "plain" where we can assert that types are introspected as we expect. * For typing support, users will be much more exposed to the class names of things. Add these all to "sqlalchemy" import space. * Column(ForeignKey()) no longer needs to be `@declared_attr` if the FK refers to a remote table * composite() attributes mapped to a dataclass no longer need to implement a `__composite_values__()` method * with_variant() accepts multiple dialect names Change-Id: I22797c0be73a8fbbd2d6f5e0c0b7258b17fe145d Fixes: #7535 Fixes: #7551 References: #6810
* Merge "track item schema names to identify name collisions w/ default ↵mike bayer2022-01-141-1/+0
|\ | | | | | | schema" into main
| * track item schema names to identify name collisions w/ default schemaMike Bayer2022-01-141-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Added an additional lookup step to the compiler which will track all FROM clauses which are tables, that may have the same name shared in multiple schemas where one of the schemas is the implicit "default" schema; in this case, the table name when referring to that name without a schema qualification will be rendered with an anonymous alias name at the compiler level in order to disambiguate the two (or more) names. The approach of schema-qualifying the normally unqualified name with the server-detected "default schema name" value was also considered, however this approach doesn't apply to Oracle nor is it accepted by SQL Server, nor would it work with multiple entries in the PostgreSQL search path. The name collision issue resolved here has been identified as affecting at least Oracle, PostgreSQL, SQL Server, MySQL and MariaDB. Fixes: #7471 Change-Id: Id65e7ca8c43fe8d95777084e8d5ec140ebcd784d
* | initial reorganize for static typingMike Bayer2022-01-121-1/+1
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | start applying foundational annotations to key elements. two main elements addressed here: 1. removal of public_factory() and replacement with explicit functions. this just works much better with typing. 2. typing support for column expressions and operators. The biggest part of this involves stubbing out all the ColumnOperators methods under ColumnElement in a TYPE_CHECKING section. Took me a while to see this method vs. much more complicated things I thought I needed. Also for this version implementing #7519, ColumnElement types against the Python type and not TypeEngine. it is hoped this leads to easier transferrence between ORM/Core as well as eventual support for result set typing. Not clear yet how well this approach will work and what new issues it may introduce. given the current approach we now get full, rich typing for scenarios like this: from sqlalchemy import column, Integer, String, Boolean c1 = column('a', String) c2 = column('a', Integer) expr1 = c2.in_([1, 2, 3]) expr2 = c2 / 5 expr3 = -c2 expr4_a = ~(c2 == 5) expr4_b = ~column('q', Boolean) expr5 = c1 + 'x' expr6 = c2 + 10 Fixes: #7519 Fixes: #6810 Change-Id: I078d9f57955549f6f7868314287175f6c61c44cb
* change state.load_options to a tupleMike Bayer2022-01-111-3/+3
| | | | | | | | | | | | | | | | having this be an immutable sequence is safer and possibly lower overhead. The change here went in with no issues save for tests that asserted it was a set. InstanceState.load_options is only referred towards when the object is first loaded, and then within the logic that emits an object refresh as well as within a lazy loader. it's only accessed as a whole collection. Fixes: #7558 Change-Id: Id1adbec0f93bcfbfc934ec9cd39e71e74727845d
* happy new year 2022Mike Bayer2022-01-061-1/+1
| | | | Change-Id: I49abf2607e0eb0623650efdf0091b1fb3db737ea
* Remove all remaining removed_in_20 warnings slated for removalMike Bayer2022-01-051-26/+0
| | | | | | | | | | | | | | | | | | | | | | | | | Finalize all remaining removed-in-2.0 changes so that we can begin doing pep-484 typing without old things getting in the way (we will also have to do public_factory). note there are a few "moved_in_20()" and "became_legacy_in_20()" warnings still in place. The SQLALCHEMY_WARN_20 variable is now removed. Also removed here are the legacy "in place mutators" for Select statements, and some keyword-only argument signatures in Core have been added. Also in the big change department, the ORM mapper() function is removed entirely; the Mapper class is otherwise unchanged, just the public-facing API function. Mappers are now always given a registry in which to participate, however the argument signature of Mapper is not changed. ideally "registry" would be the first positional argument. Fixes: #7257 Change-Id: Ic70c57b9f1cf7eb996338af5183b11bdeb3e1623
* Update Black's target-version to py37Hugo van Kemenade2022-01-051-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | <!-- Provide a general summary of your proposed changes in the Title field above --> ### Description <!-- Describe your changes in detail --> Black's `target-version` was still set to `['py27', 'py36']`. Set it to `[py37]` instead. Also update Black and other pre-commit hooks and re-format with Black. ### 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 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: #7536 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7536 Pull-request-sha: b3aedf5570d7e0ba6c354e5989835260d0591b08 Change-Id: I8be85636fd2c9449b07a8626050c8bd35bd119d5
* ensure correlate_except is checked for empty tupleMike Bayer2022-01-031-2/+2
| | | | | | | | | | | Fixed issue where :meth:`_sql.Select.correlate_except` method, when passed either the ``None`` value or no arguments, would not correlate any elements when used in an ORM context (that is, passing ORM entities as FROM clauses), rather than causing all FROM elements to be considered as "correlated" in the same way which occurs when using Core-only constructs. Fixes: #7514 Change-Id: Ic4a5252c8f3c1140aba6c308264948f3a91f33f5
* remove 2.0-removed Query elementsMike Bayer2022-01-011-432/+68
| | | | | | | | | | | | | | * :meth:`_orm.Query.join` no longer accepts the "aliased" and "from_joinpoint" arguments * :meth:`_orm.Query.join` no longer accepts chains of multiple join targets in one method call. * ``Query.from_self()`` and ``Query.with_polymorphic()`` are removed. Change-Id: I534d04b53a538a4fc374966eb2bc8eb98a16497d References: #7257
* Replace raise_ with raise fromFederico Caselli2021-12-271-14/+8
| | | | | Change-Id: I7aaeb5bc130271624335b79cf586581d6c6c34c7 References: #4600
* factor out UnboundLoad and rearchitect strategy_options.pyMike Bayer2021-12-271-2/+19
| | | | | | | | | | | | | | | | | | | | | The architecture of Load is mostly rewritten here. The change includes removal of the "pluggable" aspect of the loader options, which would patch new methods onto Load. This has been replaced by normal methods that respond normally to typing annotations. As part of this change, the bake_loaders() and unbake_loaders() options, which have no effect since 1.4 and were unlikely to be in any common use, have been removed. Additionally, to support annotations for methods that make use of @decorator, @generative etc., modified format_argspec_plus to no longer return "args", instead returns "grouped_args" which is always grouped and allows return annotations to format correctly. Fixes: #6986 Change-Id: I6117c642345cdde65a64389bba6057ddd5374427
* restore graceful degrade of subqueryload w from_statementMike Bayer2021-12-261-0/+6
| | | | | | | | | | | | | | | Fixed regression from 1.3 where the "subqueryload" loader strategy would fail with a stack trace if used against a query that made use of :meth:`_orm.Query.from_statement` or :meth:`_sql.Select.from_statement`. As subqueryload requires modifying the original statement, it's not compatible with the "from_statement" use case, especially for statements made against the :func:`_sql.text` construct. The behavior now is equivalent to that of 1.3 and previously, which is that the loader strategy silently degrades to not be used for such statements, typically falling back to using the lazyload strategy. Fixes: #7505 Change-Id: I950800dc86a77f8320a5e696edce1ff2c84b1eb9
* add recursion check for with_loader_criteria() optionMike Bayer2021-12-221-1/+2
| | | | | | | | | | | | | Fixed recursion overflow which could occur within ORM statement compilation when using either the :func:`_orm.with_loader_criteria` feature or the the :meth:`_orm.PropComparator.and_` method within a loader strategy in conjunction with a subquery which referred to the same entity being altered by the criteria option, or loaded by the loader strategy. A check for coming across the same loader criteria option in a recursive fashion has been added to accommodate for this scenario. Fixes: #7491 Change-Id: I8701332717c45a21948ea4788a3058c0fbbf03a7
* use the options from the cached statement for propagate_optionsMike Bayer2021-12-121-1/+21
| | | | | | | | | | | Fixed caching-related issue where the use of a loader option of the form ``lazyload(aliased(A).bs).joinedload(B.cs)`` would fail to result in the joinedload being invoked for runs subsequent to the query being cached, due to a mismatch for the options / object path applied to the objects loaded for a query with a lead entity that used ``aliased()``. Fixes: #7447 Change-Id: I4e9c34654b7d3668cd8878decbd688afe2af5f81
* Removals: strings for join(), loader_options().Mike Bayer2021-12-081-7/+5
| | | | | | | | | | | | | | | | * The :meth:`_orm.Query.join` method no longer accepts strings for relationship names; the long-documented approach of using ``Class.attrname`` for join targets is now standard. * Loader options no longer accept strings for attribute names. The long-documented approach of using ``Class.attrname`` for loader option targets is now standard. It is hoped that a subsequent commit can refactor loader options to no longer need "UnboundLoad" for most cases. Change-Id: If4629882c40523dccbf4459256bf540fb468b618 References: #6986
* Clean up most py3k compatFederico Caselli2021-11-241-8/+4
| | | | Change-Id: I8172fdcc3103ff92aa049827728484c8779af6b7