qtable = quote(table_name)
cursor = _pragma_cursor(connection.execute("%stable_info(%s)" % (pragma, qtable)))
row = cursor.fetchone()
-
+
# consume remaining rows, to work around
# http://www.sqlite.org/cvstrac/tktview?tn=1884
while cursor.fetchone() is not None:
# detect if there's anything changed or loaded
# by a preprocessor on this state/attribute. if not,
# we should be able to skip it entirely.
- sum_ = attributes.get_all_pending(state, state.dict, self.key)
+ sum_ = state.manager[self.key].impl.get_all_pending(state, state.dict)
if not sum_:
continue
elif self.hasparent(child) is False:
uowcommit.register_object(child, isdelete=True,
operation="delete", prop=self.prop)
- for c, m in self.mapper.cascade_iterator(
+ for c, m, st_, dct_ in self.mapper.cascade_iterator(
'delete', child):
uowcommit.register_object(
- attributes.instance_state(c),
+ st_,
isdelete=True)
if pks_changed:
continue
uowcommit.register_object(child, isdelete=True,
operation="delete", prop=self.prop)
- for c, m in self.mapper.cascade_iterator(
+ for c, m, st_, dct_ in self.mapper.cascade_iterator(
'delete', child):
uowcommit.register_object(
- attributes.instance_state(c), isdelete=True)
+ st_, isdelete=True)
def presort_saves(self, uowcommit, states):
for state in states:
uowcommit.register_object(child, isdelete=True,
operation="delete", prop=self.prop)
- for c, m in self.mapper.cascade_iterator(
+ for c, m, st_, dct_ in self.mapper.cascade_iterator(
'delete', child):
uowcommit.register_object(
- attributes.instance_state(c),
+ st_,
isdelete=True)
def process_deletes(self, uowcommit, states):
if self.hasparent(child) is False:
uowcommit.register_object(child, isdelete=True,
operation="delete", prop=self.prop)
- for c, m in self.mapper.cascade_iterator(
+ for c, m, st_, dct_ in self.mapper.cascade_iterator(
'delete',
child):
uowcommit.register_object(
- attributes.instance_state(c), isdelete=True)
+ st_, isdelete=True)
def process_deletes(self, uowcommit, states):
secondary_delete = []
reference so that they don't fall out of scope immediately.
"""
- visited_instances = util.IdentitySet()
+ visited_states = set()
prp, mpp = object(), object()
- visitables = [(deque(self._props.values()), prp, state, state.dict)]
+ visitables = deque([(deque(self._props.values()), prp, state, state.dict)])
while visitables:
iterator, item_type, parent_state, parent_dict = visitables[-1]
if type_ not in prop.cascade:
continue
queue = deque(prop.cascade_iterator(type_, parent_state,
- parent_dict, visited_instances, halt_on))
+ parent_dict, visited_states, halt_on))
if queue:
visitables.append((queue,mpp, None, None))
elif item_type is mpp:
instance, instance_mapper, corresponding_state, \
corresponding_dict = iterator.popleft()
- yield (instance, instance_mapper)
+ yield instance, instance_mapper, corresponding_state, corresponding_dict
visitables.append((deque(instance_mapper._props.values()),
prp, corresponding_state, corresponding_dict))
dest_state.get_impl(self.key).set(dest_state,
dest_dict, obj, None)
- def cascade_iterator(self, type_, state, dict_, visited_instances, halt_on=None):
+ def cascade_iterator(self, type_, state, dict_, visited_states, halt_on=None):
if not type_ in self.cascade:
return
passive = attributes.PASSIVE_OFF
if type_ == 'save-update':
- instances = attributes.get_all_pending(state, dict_, self.key)
+ instances = state.manager[self.key].impl.get_all_pending(state, dict_)
else:
instances = state.value_as_iterable(dict_, self.key,
if instances:
for c in instances:
if c is not None and \
- c is not attributes.PASSIVE_NO_RESULT and \
- c not in visited_instances:
-
+ c is not attributes.PASSIVE_NO_RESULT:
+
instance_state = attributes.instance_state(c)
+ if instance_state in visited_states:
+ continue
+
instance_dict = attributes.instance_dict(c)
if halt_on and halt_on(instance_state):
c.__class__
))
- visited_instances.add(c)
+ visited_states.add(instance_state)
# cascade using the mapper local to this
# object, so that its individual properties are located
def _save_or_update_state(self, state):
self._save_or_update_impl(state)
- self._cascade_save_or_update(state)
- def _cascade_save_or_update(self, state):
- for state, mapper in _cascade_unknown_state_iterator(
- 'save-update', state,
- halt_on=self._contains_state):
- self._save_or_update_impl(state)
+ mapper = _state_mapper(state)
+ for o, m, st_, dct_ in mapper.cascade_iterator('save-update', state, halt_on=self._contains_state):
+ self._save_or_update_impl(st_)
def delete(self, instance):
"""Mark an instance as deleted.
# yield the state, object, mapper. yielding the object
# allows the iterator's results to be held in a list without
# states being garbage collected
- for (o, m) in mapper.cascade_iterator(cascade, state, **kwargs):
- yield attributes.instance_state(o), o, m
-
-def _cascade_unknown_state_iterator(cascade, state, **kwargs):
- mapper = _state_mapper(state)
- for (o, m) in mapper.cascade_iterator(cascade, state, **kwargs):
- yield _state_for_unknown_persistence_instance(o), m
+ for o, m, st_, dct_ in mapper.cascade_iterator(cascade, state, **kwargs):
+ yield st_, o, m
def _state_for_unsaved_instance(instance, create=False):
try:
def __init__(self, key):
self.key = key
-
+
+ # TODO: migrate these to unwrapped events
+
def append(self, state, item, initiator):
# process "save_update" cascade rules for when
# an instance is appended to the list of another instance
sess = session._state_session(state)
if sess:
prop = _state_mapper(state)._props[self.key]
+ item_state = attributes.instance_state(item)
if prop.cascade.save_update and \
(prop.cascade_backrefs or self.key == initiator.key) and \
- item not in sess:
- sess.add(item)
+ not sess._contains_state(item_state):
+ sess._save_or_update_state(item_state)
return item
def remove(self, state, item, initiator):
if sess:
prop = _state_mapper(state)._props[self.key]
# expunge pending orphans
+ item_state = attributes.instance_state(item)
if prop.cascade.delete_orphan and \
- item in sess.new and \
- prop.mapper._is_orphan(attributes.instance_state(item)):
+ item_state in sess._new and \
+ prop.mapper._is_orphan(item_state):
sess.expunge(item)
def set(self, state, newvalue, oldvalue, initiator):
sess = session._state_session(state)
if sess:
prop = _state_mapper(state)._props[self.key]
- if newvalue is not None and \
- prop.cascade.save_update and \
- (prop.cascade_backrefs or self.key == initiator.key) and \
- newvalue not in sess:
- sess.add(newvalue)
- if prop.cascade.delete_orphan and \
- oldvalue in sess.new and \
- prop.mapper._is_orphan(attributes.instance_state(oldvalue)):
- sess.expunge(oldvalue)
+ if newvalue is not None:
+ newvalue_state = attributes.instance_state(newvalue)
+ if prop.cascade.save_update and \
+ (prop.cascade_backrefs or self.key == initiator.key) and \
+ not sess._contains_state(newvalue_state):
+ sess._save_or_update_state(newvalue_state)
+
+ if oldvalue is not None and prop.cascade.delete_orphan:
+ oldvalue_state = attributes.instance_state(oldvalue)
+
+ if oldvalue_state in sess._new and \
+ prop.mapper._is_orphan(oldvalue_state):
+ sess.expunge(oldvalue)
return newvalue
print "SQLA Version: %s" % __version__
print "Total calls %d" % stats.total_calls
+print "Total cpu seconds: %.2f" % stats.total_tt
print 'Total execute calls: %d' \
% counts_by_methname["<method 'execute' of 'sqlite3.Cursor' "
"objects>"]