summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-09-09 17:01:38 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-09-09 17:01:38 +0000
commit9d5264f9f99f75187b3f95d08ebabbaea8529901 (patch)
tree2a417b1f665b7688fb1a1f2bb622722aba24675b /lib/sqlalchemy
parentfbd0a0c725249ef22260a3714ed564a191c0c45c (diff)
downloadsqlalchemy-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__.py23
-rw-r--r--lib/sqlalchemy/orm/dependency.py6
-rw-r--r--lib/sqlalchemy/orm/properties.py3
-rw-r--r--lib/sqlalchemy/schema.py3
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: