Mike Bayer [Sat, 8 Dec 2007 23:03:22 +0000 (23:03 +0000)]
- added new methods to TypeDecorator, process_bind_param() and
process_result_value(), which automatically take advantage of the processing
of the underlying type. Ideal for using with Unicode or Pickletype.
TypeDecorator should now be the primary way to augment the behavior of any
existing type including other TypeDecorator subclasses such as PickleType.
Mike Bayer [Sat, 8 Dec 2007 18:58:03 +0000 (18:58 +0000)]
- flush() refactor merged from uow_nontree branch r3871-r3885
- topological.py cleaned up, presents three public facing functions which
return list/tuple based structures, without exposing any internals. only
the third function returns the "hierarchical" structure. when results
include "cycles" or "child" items, 2- or 3- tuples are used to represent
results.
- unitofwork uses InstanceState almost exclusively now. new and deleted lists
are now dicts which ref the actual object to provide a strong ref for the
duration that they're in those lists. IdentitySet is only used for the public
facing versions of "new" and "deleted".
- unitofwork topological sort no longer uses the "hierarchical" version of the sort
for the base sort, only for the "per-object" secondary sort where it still
helps to group non-dependent operations together and provides expected insert
order. the default sort deals with UOWTasks in a straight list and is greatly
simplified. Tests all pass but need to see if svilen's stuff still works,
one block of code in _sort_cyclical_dependencies() seems to not be needed anywhere
but i definitely put it there for a reason at some point; if not hopefully we
can derive more test coverage from that.
- the UOWEventHandler is only applied to object-storing attributes, not
scalar (i.e. column-based) ones. cuts out a ton of overhead when setting
non-object based attributes.
- InstanceState also used throughout the flush process, i.e. dependency.py,
mapper.save_obj()/delete_obj(), sync.execute() all expect InstanceState objects
in most cases now.
- mapper/property cascade_iterator() takes InstanceState as its argument,
but still returns lists of object instances so that they are not dereferenced.
- a few tricks needed when dealing with InstanceState, i.e. when loading a list
of items that are possibly fresh from the DB, you *have* to get the actual objects
into a strong-referencing datastructure else they fall out of scope immediately.
dependency.py caches lists of dependent objects which it loads now (i.e. history
collections).
- AttributeHistory is gone, replaced by a function that returns a 3-tuple of
added, unchanged, deleted. these collections still reference the object
instances directly for the strong-referencing reasons mentiontioned, but
it uses less IdentitySet logic to generate.
Mike Bayer [Fri, 7 Dec 2007 16:47:00 +0000 (16:47 +0000)]
fix to unique bind params, you *can* use the same unique bindparam multiple times
in a statement. the collision check is strictly detecting non-unique's that happen to have
the same name.
Mike Bayer [Fri, 7 Dec 2007 16:13:19 +0000 (16:13 +0000)]
- added "cascade delete" behavior to "dynamic" relations just like
that of regular relations. if passive_deletes flag (also just added)
is not set, a delete of the parent item will trigger a full load of
the child items so that they can be deleted or updated accordingly.
Mike Bayer [Thu, 6 Dec 2007 22:23:10 +0000 (22:23 +0000)]
- generation of "unique" bind parameters has been simplified to use the same
"unique identifier" mechanisms as everything else. This doesn't affect
user code, except any code that might have been hardcoded against the generated
names. Generated bind params now have the form "<paramname>_<num>",
whereas before only the second bind of the same name would have this form.
- bindparam() objects themselves can be used as keys for execute(), i.e.
statement.execute({bind1:'foo', bind2:'bar'})
Mike Bayer [Thu, 6 Dec 2007 19:15:04 +0000 (19:15 +0000)]
- query.get() and query.load() do not take existing filter or other
criterion into account; these methods *always* look up the given id
in the database or return the current instance from the identity map,
disregarding any existing filter, join, group_by or other criterion
which has been configured. [ticket:893]
Mike Bayer [Wed, 5 Dec 2007 22:04:27 +0000 (22:04 +0000)]
- ordering of cols in pks_by_table and cols_by_table is significant;
particularly for pks_by_table the ordering is expected to match the ordering
of pk columns in the table for usage in query.get() as well as identity key
generation
Mike Bayer [Wed, 5 Dec 2007 20:43:16 +0000 (20:43 +0000)]
- a major behavioral change to collection-based backrefs: they no
longer trigger lazy loads ! "reverse" adds and removes
are queued up and are merged with the collection when it is
actually read from and loaded; but do not trigger a load beforehand.
For users who have noticed this behavior, this should be much more
convenient than using dynamic relations in some cases; for those who
have not, you might notice your apps using a lot fewer queries than
before in some situations. [ticket:871]
Mike Bayer [Wed, 5 Dec 2007 03:07:21 +0000 (03:07 +0000)]
- basic framework for generic functions, [ticket:615]
- changed the various "literal" generation functions to use an anonymous
bind parameter. not much changes here except their labels now look
like ":param_1", ":param_2" instead of ":literal"
- from_obj keyword argument to select() can be a scalar or a list.
Mike Bayer [Tue, 4 Dec 2007 17:06:55 +0000 (17:06 +0000)]
- relaxed rules on column_property() expressions having labels; any
ColumnElement is accepted now, as the compiler auto-labels non-labeled
ColumnElements now. a selectable, like a select() statement, still
requires conversion to ColumnElement via as_scalar() or label().
Mike Bayer [Sun, 2 Dec 2007 00:31:26 +0000 (00:31 +0000)]
- moved class-level attributes placed by the attributes package into a _class_state
variable attached to the class.
- mappers track themselves primarily using the "mappers" collection on _class_state.
ClassKey is gone and mapper lookup uses regular dict keyed to entity_name; removes
a fair degree of WeakKeyDictionary overhead as well as ClassKey overhead.
- mapper_registry renamed to _mapper_registry; is only consulted by the
compile_mappers(), mapper.compile() and clear_mappers() functions/methods.
Mike Bayer [Sat, 1 Dec 2007 23:00:05 +0000 (23:00 +0000)]
- several ORM attributes have been removed or made private:
mapper.get_attr_by_column(), mapper.set_attr_by_column(),
mapper.pks_by_table, mapper.cascade_callable(),
MapperProperty.cascade_callable(), mapper.canload()
- refinements to mapper PK/table column organization, session cascading,
some naming convention work
Mike Bayer [Fri, 30 Nov 2007 00:40:56 +0000 (00:40 +0000)]
- added support for version_id_col in conjunction with inheriting mappers.
version_id_col is typically set on the base mapper in an inheritance
relationship where it takes effect for all inheriting mappers.
[ticket:883]
- a little rearrangement of save_obj()
Mike Bayer [Thu, 29 Nov 2007 19:37:05 +0000 (19:37 +0000)]
- adjustment to the previous checkin regarding inheritance to not conflict with globals
- fix to self-referential eager loading such that if the same mapped
instance appears in two or more distinct sets of columns in the same
result set, its eagerly loaded collection will be populated regardless
of whether or not all of the rows contain a set of "eager" columns for
that collection. this would also show up as a KeyError when fetching
results with join_depth turned on.
Mike Bayer [Thu, 29 Nov 2007 15:36:13 +0000 (15:36 +0000)]
- fixed bug where Query would not apply a subquery to the SQL when LIMIT
was used in conjunction with an inheriting mapper where the eager
loader was only in the parent mapper.
Mike Bayer [Tue, 27 Nov 2007 16:23:02 +0000 (16:23 +0000)]
opened up the test for "reflection with convert_unicode=True". this is since convert_unicode by default has assert_unicode, want to ensure that other dialects (at least oracle) support this (i.e. not unicode schema names themselves, just that they dont sent thru bytestrings to a String).
if maxdb or sybase *should* be able to handle this too though I can't test on this end.
Mike Bayer [Sun, 25 Nov 2007 23:14:03 +0000 (23:14 +0000)]
- added new flag to String and create_engine(), assert_unicode=(True|False|None).
When convert_unicode=True, this flag also defaults to `True`, and results in all
unicode conversion operations raising an exception when a non-unicode bytestring
is passed as a bind parameter. It is strongly advised that all unicode-aware
applications make proper use of Python unicode objects (i.e. u'hello' and
not 'hello').
Mike Bayer [Sun, 25 Nov 2007 03:28:49 +0000 (03:28 +0000)]
- named_with_column becomes an attribute
- cleanup within compiler visit_select(), column labeling
- is_select() removed from dialects, replaced with returns_rows_text(), returns_rows_compiled()
- should_autocommit() removed from dialects, replaced with should_autocommit_text() and
should_autocommit_compiled()
- typemap and column_labels collections removed from Compiler, replaced with single "result_map" collection.
- ResultProxy uses more succinct logic in combination with result_map to target columns
Mike Bayer [Sat, 24 Nov 2007 01:59:29 +0000 (01:59 +0000)]
- decruftify old visitors used by orm, convert to functions that
use a common traversal function.
- TranslatingDict is finally gone, thanks to column.proxy_set simpleness...hooray !
- shoved "slice" use case on RowProxy into an exception case. knocks noticeable time off of large result set operations.
Mike Bayer [Fri, 23 Nov 2007 19:01:40 +0000 (19:01 +0000)]
more changes to merge(dont_load); since we now have a guarantee that
all merged instances aren't dirty, we can copy the attribues without using
any append/replace events, and therefore don't have any concern of lazy loaders
firing off. added tests to ensure that '_is_orphan()' doesn't get screwed up,
and also that the 'dirty' list on the new session stays empty, which is an
extra bonus of this approach.
Mike Bayer [Fri, 23 Nov 2007 05:24:32 +0000 (05:24 +0000)]
- some clarifications and fixes to merge(instance, dont_load=True).
fixed bug where lazy loaders were getting disabled on returned instances.
Also, we currently do not support merging an instance which has uncommitted
changes on it, in the case that dont_load=True is used....this will
now raise an error. This is due to complexities in merging the
"committed state" of the given instance to correctly correspond to the
newly copied instance. Since the use case for dont_load=True is
caching, the given instances shouldn't have any uncommitted changes on them
anyway.
Mike Bayer [Tue, 20 Nov 2007 15:55:36 +0000 (15:55 +0000)]
- clarified the error message which occurs when you try to update()
an instance with the same identity key as an instance already present
in the session.
- opened up the recursive checks in session.merge() a little bit
Jason Kirtland [Sun, 18 Nov 2007 18:19:52 +0000 (18:19 +0000)]
Migrated Connection.properties to Connection.info ('info' is the new standard name for user-writable property collections that came out of [ticket:573]). 'properties' is now an alias, will be removed in 0.5.
Mike Bayer [Sun, 18 Nov 2007 16:32:47 +0000 (16:32 +0000)]
- PickleType will compare using `==` when set up with mutable=False,
and not the `is` operator. To use `is` or any other comparator, send
in a custom comparison function using PickleType(comparator=my_custom_comparator).
Mike Bayer [Sun, 18 Nov 2007 02:13:56 +0000 (02:13 +0000)]
- session.refresh() and session.expire() now support an additional argument
"attribute_names", a list of individual attribute keynames to be refreshed
or expired, allowing partial reloads of attributes on an already-loaded
instance.
- finally simplified the behavior of deferred attributes, deferred polymorphic
load, session.refresh, session.expire, mapper._postfetch to all use a single
codepath through query._get(), which now supports a list of individual attribute names
to be refreshed. the *one* exception still remaining is mapper._get_poly_select_loader(),
which may stay that way since its inline with an already processing load operation.
otherwise, query._get() is the single place that all "load this instance's row" operation
proceeds.
- cleanup all over the place
Mike Bayer [Wed, 14 Nov 2007 16:43:21 +0000 (16:43 +0000)]
- DeferredColumnLoader checks row for column, if present sends it to
ColumnLoader to create the row processor
- eager loaders ensure deferred foreign key cols are present in the primary list of columns (and secondary...). because eager loading with LIMIT/OFFSET doesn't re-join to the parent table anymore this is now necessary. [ticket:864]