summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/mapping/sync.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-05-25 14:20:23 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-05-25 14:20:23 +0000
commitbb79e2e871d0a4585164c1a6ed626d96d0231975 (patch)
tree6d457ba6c36c408b45db24ec3c29e147fe7504ff /lib/sqlalchemy/mapping/sync.py
parent4fc3a0648699c2b441251ba4e1d37a9107bd1986 (diff)
downloadsqlalchemy-bb79e2e871d0a4585164c1a6ed626d96d0231975.tar.gz
merged 0.2 branch into trunk; 0.1 now in sqlalchemy/branches/rel_0_1
Diffstat (limited to 'lib/sqlalchemy/mapping/sync.py')
-rw-r--r--lib/sqlalchemy/mapping/sync.py129
1 files changed, 0 insertions, 129 deletions
diff --git a/lib/sqlalchemy/mapping/sync.py b/lib/sqlalchemy/mapping/sync.py
deleted file mode 100644
index cfce9b6b6..000000000
--- a/lib/sqlalchemy/mapping/sync.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# mapper/sync.py
-# Copyright (C) 2005,2006 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of SQLAlchemy and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-
-
-import sqlalchemy.sql as sql
-import sqlalchemy.schema as schema
-from sqlalchemy.exceptions import *
-
-"""contains the ClauseSynchronizer class which is used to map attributes between two objects
-in a manner corresponding to a SQL clause that compares column values."""
-
-ONETOMANY = 0
-MANYTOONE = 1
-MANYTOMANY = 2
-
-class ClauseSynchronizer(object):
- """Given a SQL clause, usually a series of one or more binary
- expressions between columns, and a set of 'source' and 'destination' mappers, compiles a set of SyncRules
- corresponding to that information. The ClauseSynchronizer can then be executed given a set of parent/child
- objects or destination dictionary, which will iterate through each of its SyncRules and execute them.
- Each SyncRule will copy the value of a single attribute from the parent
- to the child, corresponding to the pair of columns in a particular binary expression, using the source and
- destination mappers to map those two columns to object attributes within parent and child."""
- def __init__(self, parent_mapper, child_mapper, direction):
- self.parent_mapper = parent_mapper
- self.child_mapper = child_mapper
- self.direction = direction
- self.syncrules = []
-
- def compile(self, sqlclause, source_tables, target_tables, issecondary=None):
- def check_for_table(binary, list1, list2):
- #print "check for table", str(binary), [str(c) for c in l]
- if binary.left.table in list1 and binary.right.table in list2:
- return (binary.left, binary.right)
- elif binary.right.table in list1 and binary.left.table in list2:
- return (binary.right, binary.left)
- else:
- return (None, None)
-
- def compile_binary(binary):
- """assembles a SyncRule given a single binary condition"""
- if binary.operator != '=' or not isinstance(binary.left, schema.Column) or not isinstance(binary.right, schema.Column):
- return
-
- if binary.left.table == binary.right.table:
- # self-cyclical relation
- if binary.left.primary_key:
- source = binary.left
- dest = binary.right
- elif binary.right.primary_key:
- source = binary.right
- dest = binary.left
- else:
- raise ArgumentError("Cant determine direction for relationship %s = %s" % (binary.left.fullname, binary.right.fullname))
- if self.direction == ONETOMANY:
- self.syncrules.append(SyncRule(self.parent_mapper, source, dest, dest_mapper=self.child_mapper))
- elif self.direction == MANYTOONE:
- self.syncrules.append(SyncRule(self.child_mapper, source, dest, dest_mapper=self.parent_mapper))
- else:
- raise AssertionError("assert failed")
- else:
- (pt, tt) = check_for_table(binary, source_tables, target_tables)
- #print "OK", binary, [t.name for t in source_tables], [t.name for t in target_tables]
- if pt and tt:
- if self.direction == ONETOMANY:
- self.syncrules.append(SyncRule(self.parent_mapper, pt, tt, dest_mapper=self.child_mapper))
- elif self.direction == MANYTOONE:
- self.syncrules.append(SyncRule(self.child_mapper, tt, pt, dest_mapper=self.parent_mapper))
- else:
- if not issecondary:
- self.syncrules.append(SyncRule(self.parent_mapper, pt, tt, dest_mapper=self.child_mapper, issecondary=issecondary))
- else:
- self.syncrules.append(SyncRule(self.child_mapper, pt, tt, dest_mapper=self.parent_mapper, issecondary=issecondary))
-
- rules_added = len(self.syncrules)
- processor = BinaryVisitor(compile_binary)
- sqlclause.accept_visitor(processor)
- if len(self.syncrules) == rules_added:
- raise ArgumentError("No syncrules generated for join criterion " + str(sqlclause))
-
- def execute(self, source, dest, obj=None, child=None, clearkeys=None):
- for rule in self.syncrules:
- rule.execute(source, dest, obj, child, clearkeys)
-
-class SyncRule(object):
- """An instruction indicating how to populate the objects on each side of a relationship.
- i.e. if table1 column A is joined against
- table2 column B, and we are a one-to-many from table1 to table2, a syncrule would say
- 'take the A attribute from object1 and assign it to the B attribute on object2'.
-
- A rule contains the source mapper, the source column, destination column,
- destination mapper in the case of a one/many relationship, and
- the integer direction of this mapper relative to the association in the case
- of a many to many relationship.
- """
- def __init__(self, source_mapper, source_column, dest_column, dest_mapper=None, issecondary=None):
- self.source_mapper = source_mapper
- self.source_column = source_column
- self.issecondary = issecondary
- self.dest_mapper = dest_mapper
- self.dest_column = dest_column
- #print "SyncRule", source_mapper, source_column, dest_column, dest_mapper
-
- def execute(self, source, dest, obj, child, clearkeys):
- if source is None:
- if self.issecondary is False:
- source = obj
- elif self.issecondary is True:
- source = child
- if clearkeys or source is None:
- value = None
- else:
- value = self.source_mapper._getattrbycolumn(source, self.source_column)
- if isinstance(dest, dict):
- dest[self.dest_column.key] = value
- else:
- #print "SYNC VALUE", value, "TO", dest, self.source_column, self.dest_column
- self.dest_mapper._setattrbycolumn(dest, self.dest_column, value)
-
-class BinaryVisitor(sql.ClauseVisitor):
- def __init__(self, func):
- self.func = func
- def visit_binary(self, binary):
- self.func(binary)
-