summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/attributes.py
Commit message (Collapse)AuthorAgeFilesLines
* happy new year 2023Mike Bayer2023-01-031-1/+1
| | | | Change-Id: I625af65b3fb1815b1af17dc2ef47dd697fdc3fb1
* remove errant NO_KEY symbolMike Bayer2022-12-271-7/+9
| | | | | | | | | | the symbol from base is used in the event API and is passed along from attributes here. for the additional use where it's an exception case for attribute name as passed by hybrid, use a different symbol name. Change-Id: I8c5c0e71d19185ebec64f2fcbfe1e9be74e54287
* add "merge" to viewonly cascades; propagate NO_RAISE when mergingMike Bayer2022-11-241-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | Fixed bug where :meth:`_orm.Session.merge` would fail to preserve the current loaded contents of relationship attributes that were indicated with the :paramref:`_orm.relationship.viewonly` parameter, thus defeating strategies that use :meth:`_orm.Session.merge` to pull fully loaded objects from caches and other similar techniques. In a related change, fixed issue where an object that contains a loaded relationship that was nonetheless configured as ``lazy='raise'`` on the mapping would fail when passed to :meth:`_orm.Session.merge`; checks for "raise" are now suspended within the merge process assuming the :paramref:`_orm.Session.merge.load` parameter remains at its default of ``True``. Overall, this is a behavioral adjustment to a change introduced in the 1.4 series as of :ticket:`4994`, which took "merge" out of the set of cascades applied by default to "viewonly" relationships. As "viewonly" relationships aren't persisted under any circumstances, allowing their contents to transfer during "merge" does not impact the persistence behavior of the target object. This allows :meth:`_orm.Session.merge` to correctly suit one of its use cases, that of adding objects to a :class:`.Session` that were loaded elsewhere, often for the purposes of restoring from a cache. Fixes: #8862 Change-Id: I8731c7810460e6a71f8bf5e8ded59142b9b02956
* add common base class for all SQL col expression objectsMike Bayer2022-11-211-1/+2
| | | | | | | | | | | Added a new type :class:`.SQLColumnExpression` which may be indicated in user code to represent any SQL column oriented expression, including both those based on :class:`.ColumnElement` as well as on ORM :class:`.QueryableAttribute`. This type is a real class, not an alias, so can also be used as the foundation for other objects. Fixes: #8847 Change-Id: I3161bdff1c9f447793fce87864e1774a90cd4146
* Try running pyupgrade on the codeFederico Caselli2022-11-161-2/+2
| | | | | | | | 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
* implement write-only colletions, typing for dynamicMike Bayer2022-10-061-5/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For 2.0, we provide a truly "larger than memory collection" implementation, a write-only collection that will never under any circumstances implicitly load the entire collection, even during flush. This is essentially a much more "strict" version of the "dynamic" loader, which in fact has a lot of scenarios that it loads the full backing collection into memory, mostly defeating its purpose. Typing constructs are added that support both the new feature WriteOnlyMapping as well as the legacy feature DynamicMapping. These have been integrated with "annotion based mapping" so that relationship() uses these annotations to configure the loader strategy as well. additional changes: * the docs triggered a conflict in hybrid's "transformers" section, this section is hard-coded to Query using a pattern that doesnt seem to have any use and isn't part of the current select() interface, so just removed this section * As the docs for WriteOnlyMapping are very long, collections.rst is broken up into two pages now. Fixes: #6229 Fixes: #7123 Change-Id: I6929f3da6e441cad92285e7309030a9bac4e429d
* reorganize Mapped[] super outside of MapperPropertyMike Bayer2022-10-051-8/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | We made all the MapperProperty classes a subclass of Mapped[] to allow declarative mappings to name Mapped[] on the left side. this was cheating a bit because MapperProperty is not actually a descriptor, and the mapping process replaces the object with InstrumentedAttribute at mapping time, which is the actual Mapped[] descriptor. But now in I6929f3da6e441cad92285e7309030a9bac4e429d we are considering making the "cheating" a little more extensive by putting DynamicMapped / WriteOnlyMapped in Relationship's hierarchy, which need a flat out "type: ignore" to work. Instead of pushing more cheats into the core classes, move out the "Declarative"-facing versions of these classes to be typing only: Relationship, Composite, Synonym, and MappedSQLExpression added for ColumnProperty. Keep the internals expressed on the old names, RelationshipProperty, CompositeProperty, SynonymProperty, ColumnProprerty, which will remain "pure" with fully correct typing. then have the typing only endpoints be where the "cheating" and "type: ignores" have to happen, so that these are more or less slightly better forms of "Any". Change-Id: Ied7cc11196c9204da6851f49593d1b1fd2ef8ad8
* New ORM Query Guide featuring DML supportMike Bayer2022-09-251-1/+1
| | | | | | | | | | | | | | | | | reviewers: these docs publish periodically at: https://docs.sqlalchemy.org/en/gerrit/4042/orm/queryguide/index.html See the "last generated" timestamp near the bottom of the page to ensure the latest version is up Change includes some other adjustments: * small typing fixes for end-user benefit * removal of a bunch of old examples for patterns that nobody uses or aren't really what we promote now * modernization of some examples, including inheritance Change-Id: I9929daab7797be9515f71c888b28af1209e789ff
* Propagate key for collection eventsMike Bayer2022-08-161-9/+29
| | | | | | | | | | | | | | | Added new parameter :paramref:`_orm.AttributeEvents.include_key`, which will include the dictionary or list key for operations such as ``__setitem__()`` (e.g. ``obj[key] = value``) and ``__delitem__()`` (e.g. ``del obj[key]``), using a new keyword parameter "key" or "keys", depending on event, e.g. :paramref:`_orm.AttributeEvents.append.key`, :paramref:`_orm.AttributeEvents.bulk_replace.keys`. This allows event handlers to take into account the key that was passed to the operation and is of particular importance for dictionary operations working with :class:`_orm.MappedCollection`. Fixes: #8375 Change-Id: Icc472f7c28848f94e15c94a399cc13a88782e1e4
* QueryableAttribute can be used as DDL columnMike Bayer2022-05-261-0/+1
| | | | | | | We have a lot of mappings with like ForeignKey(A.id) so this needs to be included. Change-Id: I8ac4211fb09720f093fe7f6353f365ee1d7faaae
* revenge of pep 484Mike Bayer2022-05-151-15/+59
| | | | | | trying to get remaining must-haves for ORM Change-Id: I66a3ecbbb8e5ba37c818c8a92737b576ecf012f7
* pep484: attributes and relatedMike Bayer2022-05-031-239/+686
| | | | | | | also implements __slots__ for QueryableAttribute, InstrumentedAttribute, Relationship.Comparator. Change-Id: I47e823160706fc35a616f1179a06c7864089e5b5
* 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-3/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-3/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-15/+48
| | | | | | | | 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
* pep-484: the pep-484ening, SQL part threeMike Bayer2022-03-301-1/+2
| | | | | | | | | | | | | | | hitting DML which is causing us to open up the ColumnCollection structure a bit, as we do put anonymous column expressions with None here. However, we still want Table /TableClause to have named column collections that don't return None, so parametrize the "key" in this collection also. * rename some "immutable" elements to "readonly". we change the contents of immutablecolumncollection underneath, so it's not "immutable" Change-Id: I2593995a4e5c6eae874bed5bf76117198be8ae97
* pep484 for hybridMike Bayer2022-03-171-2/+8
| | | | | Change-Id: I53274b13094d996e11b04acb03f9613edbddf87f References: #6810
* pep-484 - SQL column operationsMike Bayer2022-03-151-1/+6
| | | | | | | | | note we are taking out the ColumnOperartors[SQLCoreOperations] thing; not really clear why that was needed and at the moment it seems I was likely confused. Change-Id: I834b75f9b44f91b97e29f2e1a7b1029bd910e0a1
* 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-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Initial ORM typing layoutMike Bayer2022-01-141-85/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | introduces: 1. new mapped_column() helper 2. DeclarativeBase helper 3. declared_attr has been re-typed 4. rework of Mapped[] to return InstrumentedAtribute for class get, so works without Mapped itself having expression methods 5. ORM constructs now generic on [_T] also includes some early typing work, most of which will be in later commits: 1. URL and History become typing.NamedTuple 2. come up with type-checking friendly way of type checking cy extensions, where type checking will be applied to the py versions, just needed to come up with a succinct conditional pattern for the imports References: #6810 References: #7535 References: #7562 Change-Id: Ie5d9a44631626c021d130ca4ce395aba623c71fb
* happy new year 2022Mike Bayer2022-01-061-1/+1
| | | | Change-Id: I49abf2607e0eb0623650efdf0091b1fb3db737ea
* Update Black's target-version to py37Hugo van Kemenade2022-01-051-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | <!-- 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
* Replace raise_ with raise fromFederico Caselli2021-12-271-57/+37
| | | | | Change-Id: I7aaeb5bc130271624335b79cf586581d6c6c34c7 References: #4600
* implement attributes.Proxy._clone()Mike Bayer2021-12-091-0/+10
| | | | | | | | | | | Fixed issue where the internal cloning used by the :meth:`_orm.PropComparator.any` method on a :func:`_orm.relationship` in the case where the related class also makes use of ORM polymorphic loading, would fail if a hybrid property on the related, polymorphic class were used within the criteria for the ``any()`` operation. Fixes: #7425 Change-Id: I5f4f4ec5fab17df228bc6e3de412d24114b20600
* Warn when caching is disabled / documentMike Bayer2021-12-061-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds new warnings for all elements that don't indicate their caching behavior, including user-defined ClauseElement subclasses and third party dialects. it additionally adds new documentation to discuss an apparent performance degradation in 1.4 when caching is disabled as a result in the significant expense incurred by ORM lazy loaders, which in 1.3 used BakedQuery so were actually cached. As a result of adding the warnings, a fair degree of lesser used SQL expression objects identified that they did not define caching behavior so would have been producing ``[no key]``, including PostgreSQL constructs ``hstore`` and ``array``. These have been amended to use inherit cache where appropriate. "on conflict" constructs in PostgreSQL, MySQL, SQLite still explicitly don't generate a cache key at this time. The change also adds a test for all constructs via assert_compile() to assert they will not generate cache warnings. Fixes: #7394 Change-Id: I85958affbb99bfad0f5efa21bc8f2a95e7e46981
* Clean up most py3k compatFederico Caselli2021-11-241-13/+5
| | | | Change-Id: I8172fdcc3103ff92aa049827728484c8779af6b7
* Remove object in class definitionFederico Caselli2021-11-221-2/+2
| | | | | References: #4600 Change-Id: I2a62ddfe00bc562720f0eae700a497495d7a987a
* Merge "implement deferred scalarobject history load"mike bayer2021-07-101-19/+53
|\
| * implement deferred scalarobject history loadMike Bayer2021-07-091-19/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Modified the approach used for history tracking of scalar object relationships that are not many-to-one, i.e. one-to-one relationships that would otherwise be one-to-many. When replacing a one-to-one value, the "old" value that would be replaced is no longer loaded immediately, and is instead handled during the flush process. This eliminates an historically troublesome lazy load that otherwise often occurs when assigning to a one-to-one attribute, and is particularly troublesome when using "lazy='raise'" as well as asyncio use cases. This change does cause a behavioral change within the :meth:`_orm.AttributeEvents.set` event, which is nonetheless currently documented, which is that the event applied to such a one-to-one attribute will no longer receive the "old" parameter if it is unloaded and the :paramref:`_orm.relationship.active_history` flag is not set. As is documented in :meth:`_orm.AttributeEvents.set`, if the event handler needs to receive the "old" value when the event fires off, the active_history flag must be established either with the event listener or with the relationship. This is already the behavior with other kinds of attributes such as many-to-one and column value references. The change additionally will defer updating a backref on the "old" value in the less common case that the "old" value is locally present in the session, but isn't loaded on the relationship in question, until the next flush occurs. If this causes an issue, again the normal :paramref:`_orm.relationship.active_history` flag can be set to ``True`` on the relationship. A private flag which restores the old value is retained for now, as support within relevant test suites to exercise the old and new behaviors together. This is so that if the behavioral change produces problems we have test harnesses set up to further examine these behaviors. The "legacy" style can go away in 2.0 or in a much later 1.4 release. Fixes: #6708 Change-Id: Id7f72fc39dcbec9119b665e528667a9919bb73b4
* | Replace all http:// links to https://Federico Caselli2021-07-041-1/+1
|/ | | | | | Also replace http://pypi.python.org/pypi with https://pypi.org/project Change-Id: I84b5005c39969a82140706472989f2a30b0c7685
* Create new event for collection add w/o mutationMike Bayer2021-05-121-0/+6
| | | | | | | | | | | | | | | | Fixed issue when using :paramref:`_orm.relationship.cascade_backrefs` parameter set to ``False``, which per :ref:`change_5150` is set to become the standard behavior in SQLAlchemy 2.0, where adding the item to a collection that uniquifies, such as ``set`` or ``dict`` would fail to fire a cascade event if the object were already associated in that collection via the backref. This fix represents a fundamental change in the collection mechanics by introducing a new event state which can fire off for a collection mutation even if there is no net change on the collection; the action is now suited using a new event hook :meth:`_orm.AttributeEvents.append_wo_mutation`. Fixes: #6471 Change-Id: Ic50413f7e62440dad33ab84838098ea62ff4e815
* Correct cache key for proxy_owner, with_context_optionsMike Bayer2021-05-101-1/+5
| | | | | | | | | | | | | | | | | | Fixed issue in subquery loader strategy which prevented caching from working correctly. This would have been seen in the logs as a "generated" message instead of "cached" for all subqueryload SQL emitted, which by saturating the cache with new keys would degrade overall performance; it also would produce "LRU size alert" warnings. In this issue we also observe that the local LRU cache for lazyloader and selectinloader will get used for all subsequent loads as well, which makes it more likely to hit the limit of 30. However rather than trying to work this out, it would be better if we removed the loader-local LRU caches altogether once we are confident these are working well. Fixes: #6459 Change-Id: Id953e8f75536bb87f7e3315929cebcd8f84a5a50
* accommodate HasEntityNamespace in context.all_selected_columnsMike Bayer2021-04-291-0/+1
| | | | | | | | | | Fixed regression in hybrid_property where a hybrid against a SQL function would generate an ``AttributeError`` when attempting to generate an entry for the ``.c`` collection of a subquery in some cases; among other things this would impact its use in cases like that of ``Query.count()``. Fixes: #6401 Change-Id: Icc243c699e9a5c88448076c6427ec389eaa8b8ed
* add optional proxy_class to track w/ proxy_keyMike Bayer2021-04-281-0/+1
| | | | | | | | | | | Fixed regression in ORM where using hybrid property to indicate an expression from a different entity would confuse the column-labeling logic in the ORM and attempt to derive the name of the hybrid from that other class, leading to an attribute error. The owning class of the hybrid attribute is now tracked along with the name. Fixes: #6386 Change-Id: Ica9497ea34fef799d6265de44104c1f3f3b30232
* dont assume ClauseElement in attributes, coercionsMike Bayer2021-04-231-1/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fixed two distinct issues, each of which would come into play under certain circumstances, most likely however one which is a common mis-configuration in :class:`_hybrid.hybrid_property`, where the "expression" implementation would return a non :class:`_sql.ClauseElement` such as a boolean value. For both issues, 1.3's behavior was to silently ignore the mis-configuration and ultimately attempt to interpret the value as a SQL expression, which would lead to an incorrect query. * Fixed issue regarding interaction of the attribute system with hybrid_property, where if the ``__clause_element__()`` method of the attribute returned a non-:class:`_sql.ClauseElement` object, an internal ``AttributeError`` would lead the attribute to return the ``expression`` function on the hybrid_property itself, as the attribute error was against the name ``.expression`` which would invoke the ``__getattr__()`` method as a fallback. This now raises explicitly. In 1.3 the non-:class:`_sql.ClauseElement` was returned directly. * Fixed issue in SQL argument coercions system where passing the wrong kind of object to methods that expect column expressions would fail if the object were altogether not a SQLAlchemy object, such as a Python function, in cases where the object were not just coerced into a bound value. Again 1.3 did not have a comprehensive argument coercion system so this case would also pass silently. Fixes: #6350 Change-Id: I5bba0a6b27f45e5f8ebadfd6d511fa773388ef7c
* synonym fixes and enhancementsMike Bayer2021-04-161-0/+2
| | | | | | | | | | | | | | | | | Fixed regression where an attribute that is mapped to a :func:`_orm.synonym` could not be used in column loader options such as :func:`_orm.load_only`. Established support for :func:`_orm.synonym` in conjunction with hybrid property, associationproxy, including that synonyms can be established linking to these constructs which work fully. This is a behavior that was semi-explicitly disallowed previously, however since it did not fail in every scenario, explicit support for assoc proxy and hybrids has been added. Fixes: #6272 Fixes: #6267 Change-Id: Ie75bb3b535feeb6ccf3f6a391f21b69f241e625e
* Check for hybrid's attribute name and support no nameMike Bayer2021-04-071-3/+15
| | | | | | | | | | | | | | | Fixed regression where the ORM compilation scheme would assume the function name of a hybrid property would be the same as the attribute name in such a way that an ``AttributeError`` would be raised, when it would attempt to determine the correct name for each element in a result tuple. A similar issue exists in 1.3 but only impacts the names of tuple rows. The fix here adds a check that the hybrid's function name is actually present in the ``__dict__`` of the class or its superclasses before assigning this name; otherwise, the hybrid is considered to be "unnamed" and ORM result tuples will use the naming scheme of the underlying expression. Fixes: #6215 Change-Id: I584c0c05efec957f4dcaccf5df371399a57dffe9
* Support __visit_name__ on PropComparator to work in cloningMike Bayer2021-03-241-0/+4
| | | | | | | | | Repaired support so that the :meth:`_sql.Select.params` method can work correctly with a :class:`_sql.Select` object that includes joins across ORM relationship structures, which is a new feature in 1.4. Fixes: #6124 Change-Id: Ia92fc33c3acbe66910e9e3bf00af9100de19b2b8
* Implement Mypy pluginMike Bayer2021-03-131-1/+80
| | | | | | | | | | | Rudimentary and experimental support for Mypy has been added in the form of a new plugin, which itself depends on new typing stubs for SQLAlchemy. The plugin allows declarative mappings in their standard form to both be compatible with Mypy as well as to provide typing support for mapped classes and instances. Fixes: #4609 Change-Id: Ia035978c02ad3a5c0e5b3c6c30044dd5a3155170
* Further refine labeling for renamed columnsMike Bayer2021-02-121-1/+1
| | | | | | | | | | | | | | | Forked from I22f6cf0f0b3360e55299cdcb2452cead2b2458ea we are attempting to decide the case for columns mapped under a different name. since the .key feature of Column seems to support this fully, see if an annotation can be used to indicate an effective .key for a column. The effective change is that the labeling of column expressions in rows has been improved to retain the original name of the ORM attribute even if used in a subquery. References: #5933 Change-Id: If251f556f7d723f50d349f765f1690d6c679d2ef
* happy new yearMike Bayer2021-01-041-1/+1
| | | | Change-Id: Ic5bb19ca8be3cb47c95a0d3315d84cb484bac47c
* Use .expression accessor for hybrid exampleMike Bayer2020-12-151-0/+8
| | | | | | | | | | hybrids since 1.1 use InstrumentedAttribute at the expression level, so this doc needed to illustrate how to get at the SQL expression. Also added a docstring for QueryableAttribute.expression. Fixes: #5773 Change-Id: I4941d245ec947999abfa8e13f047e06a0bd47e5b
* Some small improvements on the tutorial 2.0 documentsFederico Caselli2020-11-131-2/+5
| | | | Change-Id: I7fb37d45c29307b2213bebd0ef280d73804ac473
* upgrade to black 20.8b1Mike Bayer2020-09-281-5/+3
| | | | | | | It's better, the majority of these changes look more readable to me. also found some docstrings that had formatting / quoting issues. Change-Id: I582a45fde3a5648b2f36bab96bad56881321899b
* Raise UnmappedInstanceError if the attribute of a database object is an ↵RamonWill2020-08-131-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | unmapped object. The proposed change will raise an UnmappedInstanceError instead of an attribute error if an instance an Instrumented Attribute is unmapped. ### Description If a user tries to access an attribute of a database object that is unmapped then an error is raised. The reason for this is because the __get__ descriptor uses instance_state(instance) which uses the operator.attrgetter method to see if the object in question has the attribute "_sa_instance_state" that mapped objects have. If it doesn't contain this attribute it means that the object is unmapped. This pull request is: - [ ] A documentation / typographical 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!** Fixes: #3858 Closes: #5478 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5478 Pull-request-sha: 853051c9225446b69f52b13ade78709ad2617f6d Change-Id: I5989c81227e55e628babdd11406d1e8ec0e8d93a
* Implement relationship AND criteria; global loader criteriaMike Bayer2020-08-051-0/+28
| | | | | | | | | | | | | | | | | | | Added the ability to add arbitrary criteria to the ON clause generated by a relationship attribute in a query, which applies to methods such as :meth:`_query.Query.join` as well as loader options like :func:`_orm.joinedload`. Additionally, a "global" version of the option allows limiting criteria to be applied to particular entities in a query globally. Documentation is minimal at this point, new examples will be coming in a subsequent commit. Some adjustments to execution options in how they are represented in the ORMExecuteState as well as well as a few ORM tests that forgot to get merged in a preceding commit. Fixes: #4472 Change-Id: I2b8fc57092dedf35ebd16f6343ad0f0d7d332beb
* introduce deferred lambdasMike Bayer2020-07-031-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The coercions system allows us to add in lambdas as arguments to Core and ORM elements without changing them at all. By allowing the lambda to produce a deterministic cache key where we can also cheat and yank out literal parameters means we can move towards having 90% of "baked" functionality in a clearer way right in Core / ORM. As a second step, we can have whole statements inside the lambda, and can then add generation with __add__(), so then we have 100% of "baked" functionality with full support of ad-hoc literal values. Adds some more short_selects tests for the moment for comparison. Other tweaks inside cache key generation as we're trying to approach a certain level of performance such that we can remove the use of "baked" from the loader strategies. As we have not yet closed #4639, however the caching feature has been fully integrated as of b0cfa7379cf8513a821a3dbe3028c4965d9f85bd, we will also add complete caching documentation here and close that issue as well. Closes: #4639 Fixes: #5380 Change-Id: If91f61527236fd4d7ae3cad1f24c38be921c90ba
* Turn on caching everywhere, add loggingMike Bayer2020-06-101-5/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A variety of caching issues found by running all tests with statement caching turned on. The cache system now has a more conservative approach where any subclass of a SQL element will by default invalidate the cache key unless it adds the flag inherit_cache=True at the class level, or if it implements its own caching. Add working caching to a few elements that were omitted previously; fix some caching implementations to suit lesser used edge cases such as json casts and array slices. Refine the way BaseCursorResult and CursorMetaData interact with caching; to suit cases like Alembic modifying table structures, don't cache the cursor metadata if it were created against a cursor.description using non-positional matching, e.g. "select *". if a table re-ordered its columns or added/removed, now that data is obsolete. Additionally we have to adapt the cursor metadata _keymap regardless of if we just processed cursor.description, because if we ran against a cached SQLCompiler we won't have the right columns in _keymap. Other refinements to how and when we do this adaption as some weird cases were exposed in the Postgresql dialect, a text() construct that names just one column that is not actually in the statement. Fixed that also as it looks like a cut-and-paste artifact that doesn't actually affect anything. Various issues with re-use of compiled result maps and cursor metadata in conjunction with tables being changed, such as change in order of columns. mappers can be cleared but the class remains, meaning a mapper has to use itself as the cache key not the class. lots of bound parameter / literal issues, due to Alembic creating a straight subclass of bindparam that renders inline directly. While we can update Alembic to not do this, we have to assume other people might be doing this, so bindparam() implements the inherit_cache=True logic as well that was a bit involved. turn on cache stats in logging. Includes a fix to subqueryloader which moves all setup to the create_row_processor() phase and elminates any storage within the compiled context. This includes some changes to create_row_processor() signature and a revising of the technique used to determine if the loader can participate in polymorphic queries, which is also applied to selectinloading. DML update.values() and ordered_values() now coerces the keys as we have tests that pass an arbitrary class here which only includes __clause_element__(), so the key can't be cached unless it is coerced. this in turn changed how composite attributes support bulk update to use the standard approach of ClauseElement with annotations that are parsed in the ORM context. memory profiling successfully caught that the Session from Query was getting passed into _statement_20() so that was a big win for that test suite. Apparently Compiler had .execute() and .scalar() methods stuck on it, these date back to version 0.4 and there was a single test in the PostgreSQL dialect tests that exercised it for no apparent reason. Removed these methods as well as the concept of a Compiler holding onto a "bind". Fixes: #5386 Change-Id: I990b43aab96b42665af1b2187ad6020bee778784