which indicates to the ORM that a positive set of None should be
persisted as the value NULL, instead of omitting the column from
the INSERT statement. This feature is used both as part of the
implementation for 🎫`3514` as well as a standalone feature
available on any type. fixes#3250
- add new documentation section illustrating the "how to force null"
use case of #3250
- alter our change from #3514 so that the class-level flag is now
called "should_evaluate_none"; so that "evaluates_none" is now
a generative method.
- Fixes to the ORM and to the postgresql JSON type regarding the
``None`` constant in conjunction with the Postgresql :class:`.JSON` type. When
the :paramref:`.JSON.none_as_null` flag is left at its default
value of ``False``, the ORM will now correctly insert the Json
"'null'" string into the column whenever the value on the ORM
object is set to the value ``None`` or when the value ``None``
is used with :meth:`.Session.bulk_insert_mappings`,
**including** if the column has a default or server default on it. This
makes use of a new type-level flag "evaluates_none" which is implemented
by the JSON type based on the none_as_null flag. fixes#3514
- Added a new constant :attr:`.postgresql.JSON.NULL`, indicating
that the JSON NULL value should be used for a value
regardless of other settings. part of fixes#3514
- The "hashable" flag on special datatypes such as :class:`.postgresql.ARRAY`,
:class:`.postgresql.JSON` and :class:`.postgresql.HSTORE` is now
set to False, which allows these types to be fetchable in ORM
queries that include entities within the row. fixes#3499
- The Postgresql :class:`.postgresql.ARRAY` type now supports multidimensional
indexed access, e.g. expressions such as ``somecol[5][6]`` without
any need for explicit casts or type coercions, provided
that the :paramref:`.postgresql.ARRAY.dimensions` parameter is set to the
desired number of dimensions. fixes#3487
- The return type for the :class:`.postgresql.JSON` and :class:`.postgresql.JSONB`
when using indexed access has been fixed to work like Postgresql itself,
and returns an expression that itself is of type :class:`.postgresql.JSON`
or :class:`.postgresql.JSONB`. Previously, the accessor would return
:class:`.NullType` which disallowed subsequent JSON-like operators to be
used. part of fixes#3503
- The :class:`.postgresql.JSON`, :class:`.postgresql.JSONB` and
:class:`.postgresql.HSTORE` datatypes now allow full control over the
return type from an indexed textual access operation, either ``column[someindex].astext``
for a JSON type or ``column[someindex]`` for an HSTORE type,
via the :paramref:`.postgresql.JSON.astext_type` and
:paramref:`.postgresql.HSTORE.text_type` parameters. also part of fixes#3503
- The :attr:`.postgresql.JSON.Comparator.astext` modifier no longer
calls upon :meth:`.ColumnElement.cast` implicitly, as PG's JSON/JSONB
types allow cross-casting between each other as well. Code that
makes use of :meth:`.ColumnElement.cast` on JSON indexed access,
e.g. ``col[someindex].cast(Integer)``, will need to be changed
to call :attr:`.postgresql.JSON.Comparator.astext` explicitly. This is
part of the refactor in references #3503 for consistency in operator
use.
``__eq__()`` to return a non-boolean-capable object, such as
some geoalchemy types as well as numpy types, were being tested
for ``bool()`` during a unit of work update operation, where in
0.9 the return value of ``__eq__()`` was tested against "is True"
to guard against this.
fixes#3469
as a result of the bugfix for 🎫`3167`,
where attribute and validation events are no longer
called within the flush process. The mutable
extension was relying upon this behavior in the case where a column
level Python-side default were responsible for generating the new value
on INSERT or UPDATE, or when a value were fetched from the RETURNING
clause for "eager defaults" mode. The new value would not be subject
to any event when populated and the mutable extension could not
establish proper coercion or history listening. A new event
:meth:`.InstanceEvents.refresh_flush` is added which the mutable
extension now makes use of for this use case.
fixes#3427
- Added new event :meth:`.InstanceEvents.refresh_flush`, invoked
when an INSERT or UPDATE level default value fetched via RETURNING
or Python-side default is invoked within the flush process. This
is to provide a hook that is no longer present as a result of
🎫`3167`, where attribute and validation events are no longer
called within the flush process.
- Added a new semi-public method to :class:`.MutableBase`
:meth:`.MutableBase._get_listen_keys`. Overriding this method
is needed in the case where a :class:`.MutableBase` subclass needs
events to propagate for attribute keys other than the key to which
the mutable type is associated with, when intercepting the
:meth:`.InstanceEvents.refresh` or
:meth:`.InstanceEvents.refresh_flush` events. The current example of
this is composites using :class:`.MutableComposite`.
we only call upon the history API fully for primary key columns.
We also now skip the whole step of looking at PK columns and using
any history at all if no net changes are detected on the object.
``@validates`` would have events triggered within the flush process,
when those columns were the targets of a "fetch and populate"
operation, such as an autoincremented primary key, a Python side
default, or a server-side default "eagerly" fetched via RETURNING.
fixes#3167
into more performant executemany() call, similarly to how INSERT
statements can be batched; this will be invoked within flush
to the degree that subsequent UPDATE statements for the
same mapping and table involve the identical columns within the
VALUES clause, as well as that no VALUES-level SQL expressions
are embedded.
- some other inlinings within persistence.py
when we do a get; we return the None as always but we leave the dict blank
and the loader callable still in place. The case for this implicit get on a pending object is not
super common and there really should be no change in state at all when this
operation proceeds. This change is more dramatic as it reverses
a behavior SQLA has had since the first release.
fixes#3061
fix that is updated more comprehensively in 1.0 via 🎫`3061`.
The fix in 🎫`3060` unfortunately produces a new issue whereby
an eager load of a many-to-one attribute can produce an event
that is interpreted into an attribute change.
of work such that loading for related many-to-one objects is slightly
more aggressive, in the case of a graph of self-referential objects
that are to be deleted; the load of related objects is to help
determine the correct order for deletion if passive_deletes is
not set.
- revert the changes to test_delete_unloaded_m2o, these deletes do in fact
need to occur in the order of the two child objects first.
that might take one of multiple directions; apply this to test_delete_unloaded_m2o
which is now illustrating multiple paths due to #3060/#3061, though still doing the
right thing.
scenario, where an INSERT/DELETE can be turned into an UPDATE.
In this situation, a many-to-one relationship set to None, or
in some cases a scalar attribute set to None, may not be detected
as a net change in value, and therefore the UPDATE would not reset
what was on the previous row. This is due to some as-yet
unresovled side effects of the way attribute history works in terms
of implicitly assuming None isn't really a "change" for a previously
un-set attribute. See also 🎫`3061`. fixes#3060
to True, indicates that a series of DELETE statements should confirm
that the cursor rowcount matches the number of primary keys that should
have matched; this behavior had been taken off in most cases
(except when version_id is used) to support the unusual edge case of
self-referential ON DELETE CASCADE; to accomodate this, the message
is now just a warning, not an exception, and the flag can be used
to indicate a mapping that expects self-refererntial cascaded
deletes of this nature. See also 🎫`2403` for background on the
original change. re: #2403fix#3007
where one is to be deleted from ON DELETE CASCADE succeeds; the check here makes that fail.
We will need to add an option to enable/disable this check per mapping, will likely
do this in next version
it for DELETE would fail to target the correct row for DELETE.
Then to compound matters, basic "number of rows matched" checks were
not being performed. Both issues are fixed, however note that the
"rows matched" check requires so-called "sane multi-row count"
functionality; the DBAPI's executemany() method must count up the
rows matched by individual statements and SQLAlchemy's dialect must
mark this feature as supported, currently applies to some mysql dialects,
psycopg2, sqlite only. fixes#3006
- Enabled "sane multi-row count" checking for the psycopg2 DBAPI, as
this seems to be supported as of psycopg2 2.0.9.
become an externally usable package but still remains within the main sqlalchemy parent package.
in this system, we use kind of an ugly hack to get the noseplugin imported outside of the
"sqlalchemy" package, while still making it available within sqlalchemy for usage by
third party libraries.
such as before_flush(), before_update(),
etc. will now function as they would
within non-event code, regarding consideration
of the PK/FK values used in the lazy-emitted
query. Previously,
special flags would be established that
would cause lazy loads to load related items
based on the "previous" value of the
parent PK/FK values specifically when called
upon within a flush; the signal to load
in this way is now localized to where the
unit of work actually needs to load that
way. Note that the UOW does
sometimes load these collections before
the before_update() event is called,
so the usage of "passive_updates" or not
can affect whether or not a collection will
represent the "old" or "new" data, when
accessed within a flush event, based
on when the lazy load was emitted.
The change is backwards incompatible in
the exceedingly small chance that
user event code depended on the old
behavior. [ticket:2350]
whereby setting a non-None self-referential
many-to-one relationship to None
would fail to persist the change if the
former value was not already loaded.
[ticket:2477].
execute syncrule for destination column 'q';
mapper 'X' does not map this column" to
reference the correct mapper. [ticket:2163].
Also in 0.6.8.
- test/orm/test_sync.py covers orm/sync.py 100%
all referncing tests to not use globals
- tests that deal with pickle specifically load the fixture classes
from test.lib.pickleable, which gets some more classes added
- removed weird sa05 pickling tests that don't matter
access to the cls/self.tables/classes registries
- express orm/_base.py ORMTest in terms of engine/_base.py TablesTest,
factor out common steps into TablesTest, remove AltEngineTest as a
separate class. will further consolidate these base classes
the flush along relationship() dependencies even if
the given objects don't have any inter-attribute
references in memory, which was the behavior in
0.5 and earlier, so a flush of Parent/Child with
only foreign key/primary key set will succeed.
This while still maintaining 0.6 and above's not
generating a ton of useless internal dependency
structures within the flush that don't correspond
to state actually within the current flush.
[ticket:2082]
loads during a flush(). A change in version 0.6.6
([ticket:2002]) required that more "unnecessary" m2o
loads during a flush could occur. Extra loading modes have
been added so that the SQL emitted in this
specific use case is trimmed back, while still
retrieving the information the flush needs in order
to not miss anything. [ticket:2049]
- add a test for batch inserts
- don't need elaborate _inserted_primary_key thing
- take some cruft out of ExecutionContext, ResultProxy,
EC members can be non-underscored, have mapper just call the
EC members for now.
- simplify "connection_callable", no need for a "flush_opts"
dictionary since this point of expansion is not needed
which triggered unnecessarily on expired/unloaded
collections. This load now takes place only if
passive_updates is False and the parent primary
key has changed, or if passive_deletes is False
and a delete of the parent has occurred.
[ticket:1845]
- with m2m we have to go back to the previous approach of having both sides of
the DP fire off, tracking each pair of objects. history may not be consistently present
in one side or the other
- this revealed a whole lot of issues with self-referential m2m, which are fixed
- one-to-many relationships now maintain a list of positive
parent-child associations within the flush, preventing
previous parents marked as deleted from cascading a
delete or NULL foreign key set on those child objects,
despite the end-user not removing the child from the old
association. [ticket:1764]
- re-established Preprocess as unique on their arguments,
as they were definitely duped in inheritance scenarios
- added a "memo" feature to UOWTransaction which represents the usual
pattern of using the .attributes collection
- added the test case from [ticket:1081] into perf/
pulled into the unit of work at all. this involves dancing around lists
of states, seeing if child objects exist, not adding excessive callcounts
while doing that, etc.