diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-09-09 17:01:38 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-09-09 17:01:38 +0000 |
| commit | 9d5264f9f99f75187b3f95d08ebabbaea8529901 (patch) | |
| tree | 2a417b1f665b7688fb1a1f2bb622722aba24675b /lib/sqlalchemy | |
| parent | fbd0a0c725249ef22260a3714ed564a191c0c45c (diff) | |
| download | sqlalchemy-9d5264f9f99f75187b3f95d08ebabbaea8529901.tar.gz | |
- added 'passive_deletes="all"' flag to relation(), disables all
nulling-out of foreign key attributes during a flush where the parent
object is deleted.
- fix to FK compile fix from yesterday
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/__init__.py | 23 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/dependency.py | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/schema.py | 3 |
4 files changed, 24 insertions, 11 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 0d4dec4bc..5a2c41449 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -168,14 +168,21 @@ def relation(argument, secondary=None, **kwargs): indicates the ordering that should be applied when loading these items. passive_deletes=False - Indicates if lazy-loaders should not be executed during the ``flush()`` - process, which normally occurs in order to locate all existing child - items when a parent item is to be deleted. Setting this flag to True is - appropriate when ``ON DELETE CASCADE`` rules have been set up on the - actual tables so that the database may handle cascading deletes - automatically. This strategy is useful particularly for handling the - deletion of objects that have very large (and/or deep) child-object - collections. + Indicates the behavior of delete operations. + A value of True indicates that unloaded child items should not be loaded + during a delete operation on the parent. Normally, when a parent + item is deleted, all child items are loaded so that they can either be + marked as deleted, or have their foreign key to the parent set to NULL. + Marking this flag as True usually implies an ON DELETE <CASCADE|SET NULL> + rule is in place which will handle updating/deleting child rows on the + database side. + + Additionally, setting the flag to the string value 'all' will disable + the "nulling out" of the child foreign keys, when there is no delete or + delete-orphan cascade enabled. This is typically used when a triggering + or error raise scenario is in place on the database side. Note that + the foreign key attributes on in-session child objects will not be changed + after a flush occurs so this is a very special use-case setting. post_update this indicates that the relationship should be handled by a second diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index 3b837d275..1e461e6bf 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -188,7 +188,7 @@ class OneToManyDP(DependencyProcessor): # the child objects have to have their foreign key to the parent set to NULL # this phase can be called safely for any cascade but is unnecessary if delete cascade # is on. - if not self.cascade.delete or self.post_update: + if (not self.cascade.delete or self.post_update) and not self.passive_deletes=='all': for obj in deplist: childlist = self.get_object_dependencies(obj, uowcommit, passive=self.passive_deletes) if childlist is not None: @@ -217,7 +217,7 @@ class OneToManyDP(DependencyProcessor): if delete: # head object is being deleted, and we manage its list of child objects # the child objects have to have their foreign key to the parent set to NULL - if not self.post_update and not self.cascade.delete: + if not self.post_update and not self.cascade.delete and not self.passive_deletes=='all': for obj in deplist: childlist = self.get_object_dependencies(obj, uowcommit, passive=self.passive_deletes) if childlist is not None: @@ -265,7 +265,7 @@ class ManyToOneDP(DependencyProcessor): def process_dependencies(self, task, deplist, uowcommit, delete = False): #print self.mapper.mapped_table.name + " " + self.key + " " + repr(len(deplist)) + " process_dep isdelete " + repr(delete) + " direction " + repr(self.direction) if delete: - if self.post_update and not self.cascade.delete_orphan: + if self.post_update and not self.cascade.delete_orphan and not self.passive_deletes=='all': # post_update means we have to update our row to not reference the child object # before we can DELETE the row for obj in deplist: diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 20cbcb235..90a7ba3a4 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -161,6 +161,9 @@ class PropertyLoader(StrategizedProperty): self.cascade = mapperutil.CascadeOptions("all, delete-orphan") else: self.cascade = mapperutil.CascadeOptions("save-update, merge") + + if self.passive_deletes == 'all' and ("delete" in self.cascade or "delete-orphan" in self.cascade): + raise exceptions.ArgumentError("Can't set passive_deletes='all' in conjunction with 'delete' or 'delete-orphan' cascade") self.association = association if association: diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 212fdac82..3b7f08f79 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -509,6 +509,8 @@ class Column(SchemaItem, expression._ColumnClause): if not self._is_oid: self._pre_existing_column = table._columns.get(self.key) table._columns.add(self) + else: + self._pre_existing_column = None if self.primary_key: table.primary_key.add(self) elif self.key in table.primary_key: @@ -555,6 +557,7 @@ class Column(SchemaItem, expression._ColumnClause): c.orig_set = self.orig_set c.__originating_column = self.__originating_column c._distance = self._distance + 1 + c._pre_existing_column = self._pre_existing_column if not c._is_oid: selectable.columns.add(c) if self.primary_key: |
