| 1 | # mapper/sync.py |
|---|
| 2 | # Copyright (C) 2005, 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com |
|---|
| 3 | # |
|---|
| 4 | # This module is part of SQLAlchemy and is released under |
|---|
| 5 | # the MIT License: http://www.opensource.org/licenses/mit-license.php |
|---|
| 6 | |
|---|
| 7 | """private module containing functions used for copying data between instances |
|---|
| 8 | based on join conditions. |
|---|
| 9 | """ |
|---|
| 10 | |
|---|
| 11 | from sqlalchemy.orm import exc, util as mapperutil |
|---|
| 12 | |
|---|
| 13 | def populate(source, source_mapper, dest, dest_mapper, synchronize_pairs): |
|---|
| 14 | for l, r in synchronize_pairs: |
|---|
| 15 | try: |
|---|
| 16 | value = source_mapper._get_state_attr_by_column(source, l) |
|---|
| 17 | except exc.UnmappedColumnError: |
|---|
| 18 | _raise_col_to_prop(False, source_mapper, l, dest_mapper, r) |
|---|
| 19 | |
|---|
| 20 | try: |
|---|
| 21 | dest_mapper._set_state_attr_by_column(dest, r, value) |
|---|
| 22 | except exc.UnmappedColumnError: |
|---|
| 23 | _raise_col_to_prop(True, source_mapper, l, dest_mapper, r) |
|---|
| 24 | |
|---|
| 25 | def clear(dest, dest_mapper, synchronize_pairs): |
|---|
| 26 | for l, r in synchronize_pairs: |
|---|
| 27 | if r.primary_key: |
|---|
| 28 | raise AssertionError("Dependency rule tried to blank-out primary key column '%s' on instance '%s'" % (r, mapperutil.state_str(dest))) |
|---|
| 29 | try: |
|---|
| 30 | dest_mapper._set_state_attr_by_column(dest, r, None) |
|---|
| 31 | except exc.UnmappedColumnError: |
|---|
| 32 | _raise_col_to_prop(True, None, l, dest_mapper, r) |
|---|
| 33 | |
|---|
| 34 | def update(source, source_mapper, dest, old_prefix, synchronize_pairs): |
|---|
| 35 | for l, r in synchronize_pairs: |
|---|
| 36 | try: |
|---|
| 37 | oldvalue = source_mapper._get_committed_attr_by_column(source.obj(), l) |
|---|
| 38 | value = source_mapper._get_state_attr_by_column(source, l) |
|---|
| 39 | except exc.UnmappedColumnError: |
|---|
| 40 | _raise_col_to_prop(False, source_mapper, l, None, r) |
|---|
| 41 | dest[r.key] = value |
|---|
| 42 | dest[old_prefix + r.key] = oldvalue |
|---|
| 43 | |
|---|
| 44 | def populate_dict(source, source_mapper, dict_, synchronize_pairs): |
|---|
| 45 | for l, r in synchronize_pairs: |
|---|
| 46 | try: |
|---|
| 47 | value = source_mapper._get_state_attr_by_column(source, l) |
|---|
| 48 | except exc.UnmappedColumnError: |
|---|
| 49 | _raise_col_to_prop(False, source_mapper, l, None, r) |
|---|
| 50 | |
|---|
| 51 | dict_[r.key] = value |
|---|
| 52 | |
|---|
| 53 | def source_modified(uowcommit, source, source_mapper, synchronize_pairs): |
|---|
| 54 | """return true if the source object has changes from an old to a new value on the given |
|---|
| 55 | synchronize pairs |
|---|
| 56 | |
|---|
| 57 | """ |
|---|
| 58 | for l, r in synchronize_pairs: |
|---|
| 59 | try: |
|---|
| 60 | prop = source_mapper._get_col_to_prop(l) |
|---|
| 61 | except exc.UnmappedColumnError: |
|---|
| 62 | _raise_col_to_prop(False, source_mapper, l, None, r) |
|---|
| 63 | history = uowcommit.get_attribute_history(source, prop.key, passive=True) |
|---|
| 64 | if len(history.deleted): |
|---|
| 65 | return True |
|---|
| 66 | else: |
|---|
| 67 | return False |
|---|
| 68 | |
|---|
| 69 | def _raise_col_to_prop(isdest, source_mapper, source_column, dest_mapper, dest_column): |
|---|
| 70 | if isdest: |
|---|
| 71 | raise exc.UnmappedColumnError("Can't execute sync rule for destination column '%s'; mapper '%s' does not map this column. Try using an explicit `foreign_keys` collection which does not include this column (or use a viewonly=True relation)." % (dest_column, source_mapper)) |
|---|
| 72 | else: |
|---|
| 73 | raise exc.UnmappedColumnError("Can't execute sync rule for source column '%s'; mapper '%s' does not map this column. Try using an explicit `foreign_keys` collection which does not include destination column '%s' (or use a viewonly=True relation)." % (source_column, source_mapper, dest_column)) |
|---|