sync.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # orm/sync.py
  2. # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """private module containing functions used for copying data
  8. between instances based on join conditions.
  9. """
  10. from . import exc, util as orm_util, attributes
  11. def populate(source, source_mapper, dest, dest_mapper,
  12. synchronize_pairs, uowcommit, flag_cascaded_pks):
  13. source_dict = source.dict
  14. dest_dict = dest.dict
  15. for l, r in synchronize_pairs:
  16. try:
  17. # inline of source_mapper._get_state_attr_by_column
  18. prop = source_mapper._columntoproperty[l]
  19. value = source.manager[prop.key].impl.get(source, source_dict,
  20. attributes.PASSIVE_OFF)
  21. except exc.UnmappedColumnError:
  22. _raise_col_to_prop(False, source_mapper, l, dest_mapper, r)
  23. try:
  24. # inline of dest_mapper._set_state_attr_by_column
  25. prop = dest_mapper._columntoproperty[r]
  26. dest.manager[prop.key].impl.set(dest, dest_dict, value, None)
  27. except exc.UnmappedColumnError:
  28. _raise_col_to_prop(True, source_mapper, l, dest_mapper, r)
  29. # technically the "r.primary_key" check isn't
  30. # needed here, but we check for this condition to limit
  31. # how often this logic is invoked for memory/performance
  32. # reasons, since we only need this info for a primary key
  33. # destination.
  34. if flag_cascaded_pks and l.primary_key and \
  35. r.primary_key and \
  36. r.references(l):
  37. uowcommit.attributes[("pk_cascaded", dest, r)] = True
  38. def bulk_populate_inherit_keys(
  39. source_dict, source_mapper, synchronize_pairs):
  40. # a simplified version of populate() used by bulk insert mode
  41. for l, r in synchronize_pairs:
  42. try:
  43. prop = source_mapper._columntoproperty[l]
  44. value = source_dict[prop.key]
  45. except exc.UnmappedColumnError:
  46. _raise_col_to_prop(False, source_mapper, l, source_mapper, r)
  47. try:
  48. prop = source_mapper._columntoproperty[r]
  49. source_dict[prop.key] = value
  50. except exc.UnmappedColumnError:
  51. _raise_col_to_prop(True, source_mapper, l, source_mapper, r)
  52. def clear(dest, dest_mapper, synchronize_pairs):
  53. for l, r in synchronize_pairs:
  54. if r.primary_key and \
  55. dest_mapper._get_state_attr_by_column(
  56. dest, dest.dict, r) not in orm_util._none_set:
  57. raise AssertionError(
  58. "Dependency rule tried to blank-out primary key "
  59. "column '%s' on instance '%s'" %
  60. (r, orm_util.state_str(dest))
  61. )
  62. try:
  63. dest_mapper._set_state_attr_by_column(dest, dest.dict, r, None)
  64. except exc.UnmappedColumnError:
  65. _raise_col_to_prop(True, None, l, dest_mapper, r)
  66. def update(source, source_mapper, dest, old_prefix, synchronize_pairs):
  67. for l, r in synchronize_pairs:
  68. try:
  69. oldvalue = source_mapper._get_committed_attr_by_column(
  70. source.obj(), l)
  71. value = source_mapper._get_state_attr_by_column(
  72. source, source.dict, l, passive=attributes.PASSIVE_OFF)
  73. except exc.UnmappedColumnError:
  74. _raise_col_to_prop(False, source_mapper, l, None, r)
  75. dest[r.key] = value
  76. dest[old_prefix + r.key] = oldvalue
  77. def populate_dict(source, source_mapper, dict_, synchronize_pairs):
  78. for l, r in synchronize_pairs:
  79. try:
  80. value = source_mapper._get_state_attr_by_column(
  81. source, source.dict, l, passive=attributes.PASSIVE_OFF)
  82. except exc.UnmappedColumnError:
  83. _raise_col_to_prop(False, source_mapper, l, None, r)
  84. dict_[r.key] = value
  85. def source_modified(uowcommit, source, source_mapper, synchronize_pairs):
  86. """return true if the source object has changes from an old to a
  87. new value on the given synchronize pairs
  88. """
  89. for l, r in synchronize_pairs:
  90. try:
  91. prop = source_mapper._columntoproperty[l]
  92. except exc.UnmappedColumnError:
  93. _raise_col_to_prop(False, source_mapper, l, None, r)
  94. history = uowcommit.get_attribute_history(
  95. source, prop.key, attributes.PASSIVE_NO_INITIALIZE)
  96. if bool(history.deleted):
  97. return True
  98. else:
  99. return False
  100. def _raise_col_to_prop(isdest, source_mapper, source_column,
  101. dest_mapper, dest_column):
  102. if isdest:
  103. raise exc.UnmappedColumnError(
  104. "Can't execute sync rule for "
  105. "destination column '%s'; mapper '%s' does not map "
  106. "this column. Try using an explicit `foreign_keys` "
  107. "collection which does not include this column (or use "
  108. "a viewonly=True relation)." % (dest_column, dest_mapper))
  109. else:
  110. raise exc.UnmappedColumnError(
  111. "Can't execute sync rule for "
  112. "source column '%s'; mapper '%s' does not map this "
  113. "column. Try using an explicit `foreign_keys` "
  114. "collection which does not include destination column "
  115. "'%s' (or use a viewonly=True relation)." %
  116. (source_column, source_mapper, dest_column))