def _setattrbycolumn(self, obj, column, value):
self.columntoproperty[column][0].setattr(obj, value)
-
- def save(self, obj, traverse = True):
- """saves the object across all its primary tables.
- based on the existence of the primary key for each table, either inserts or updates.
- primary key is determined by the underlying database engine's sequence methodology.
- the traverse flag indicates attached objects should be saved as well.
-
- if smart attributes are being used for the object, the "dirty" flag, or the absense
- of the attribute, determines if the item is saved. if smart attributes are not being
- used, the item is saved unconditionally.
- """
-
- if objectstore.uow().is_dirty(obj):
- def foo():
- # TODO: unitofwork.begin()
-
- # TODO: put a registry for statements in the unitofwork,
- # where we can store insert/update statements and pre-compile them
- insert_statement = None
- update_statement = None
- for table in self.tables:
- params = {}
- for primary_key in table.primary_keys:
- if self._getattrbycolumn(obj, primary_key) is None:
- statement = table.insert()
- for col in table.columns:
- params[col.key] = self._getattrbycolumn(obj, col)
- break
- else:
- clause = sql.and_()
- for col in table.columns:
- if col.primary_key:
- clause.clauses.append(col == self._getattrbycolumn(obj, col))
- else:
- params[col.key] = self._getattrbycolumn(obj, col)
- statement = table.update(clause)
- statement.echo = self.echo
- statement.execute(**params)
- if isinstance(statement, sql.Insert):
- primary_keys = table.engine.last_inserted_ids()
- index = 0
- for col in table.primary_keys:
- newid = primary_keys[index]
- index += 1
- self._setattrbycolumn(obj, col, newid)
- self.put(obj)
- # TODO: make this "register_saved", which gets committed
- # to "clean" when you call "unitofwork.commit()"
- # also put a reentrant "begin/commit" onto unitofwork to handle nests
- objectstore.uow().register_clean(obj)
- for prop in self.props.values():
- if not isinstance(prop, ColumnProperty):
- prop.save(obj, traverse)
-
- # TODO: unitofwork.commit()
- self.transaction(foo)
- else:
- for prop in self.props.values():
- prop.save(obj, traverse)
def save_obj(self, obj):
for table in self.tables:
self.put(obj)
def register_dependencies(self, obj, uow):
- print "hi1"
for prop in self.props.values():
prop.register_dependencies(obj, uow)
"""called when the MapperProperty is first attached to a new parent Mapper."""
pass
- def save(self, object, traverse):
- """called when the instance is being saved"""
- pass
-
def delete(self, object):
"""called when the instance is being deleted"""
pass
setter = ForeignKeySetter(self.parent, self.mapper, self.parent.table, self.target, self.secondary)
+ print "procdep " + repr(deplist)
if self.secondaryjoin is not None:
secondary_delete = []
secondary_insert = []
for obj in deplist:
childlist = getlist(obj)
+ print "added! " + repr(childlist.added_items())
for child in childlist.added_items():
setter.obj = obj
setter.child = child
else:
raise " no foreign key ?"
- def save(self, obj, traverse):
- # saves child objects
-
- if self.secondary is not None:
- secondary_delete = []
- secondary_insert = []
-
- setter = ForeignKeySetter(self.parent, self.mapper, self.parent.table, self.target, self.secondary, obj)
-
- if self.uselist:
- childlist = objectstore.uow().register_list_attribute(obj, self.key)
- else:
- childlist = objectstore.uow().register_attribute(obj, self.key)
-
- for child in childlist.deleted_items():
- setter.child = child
- setter.associationrow = {}
- setter.clearkeys = True
- self.primaryjoin.accept_visitor(setter)
- self.mapper.save(child, traverse)
- if self.secondary is not None:
- self.secondaryjoin.accept_visitor(setter)
- secondary_delete.append(setter.associationrow)
-
- for child in childlist.added_items():
- setter.child = child
- setter.associationrow = {}
- self.primaryjoin.accept_visitor(setter)
- self.mapper.save(child, traverse)
- if self.secondary is not None:
- self.secondaryjoin.accept_visitor(setter)
- secondary_insert.append(setter.associationrow)
-
- if self.secondary is not None:
- # TODO: use unitofwork statement repository thing to get these
- # delete/insert statements
- # then, see if unitofwork can even bunch these all up at the end to do an even
- # bigger grouping within the "commit"
- if len(secondary_delete):
- statement = self.secondary.delete(sql.and_(*[c == sql.bindparam(c.key) for c in self.secondary.c]))
- statement.echo = self.mapper.echo
- statement.execute(*secondary_delete)
- if len(secondary_insert):
- statement = self.secondary.insert()
- statement.echo = self.mapper.echo
- statement.execute(*secondary_insert)
-
- for child in childlist.unchanged_items():
- self.mapper.save(child, traverse)
- # TODO: make this "register_saved_property", or something similar, which gets
- # a "clear_history" when you call "unitofwork.commit()"
- # also put a reentrant "begin/commit" onto unitofwork to handle nests
- childlist.clear_history()
def delete(self):
self.mapper.delete()
return True
else:
return False
+
+class UOWListElement(util.HistoryArraySet):
+ class listpointer(object): pass
+
+ def __init__(self, obj, items = None):
+ util.HistoryArraySet.__init__(self, items)
+ self.obj = weakref.ref(obj)
+
+ # cant hash a UserList, so make a bullshit pointer to us
+ self.listpointer = UOWListElement.listpointer()
+ self.listpointer.list = self
+
+ def _setrecord(self, item):
+ res = util.HistoryArraySet._setrecord(self, item)
+ if res:
+ uow().modified_lists.append(self.listpointer)
+ return res
+ def _delrecord(self, item):
+ res = util.HistoryArraySet._delrecord(self, item)
+ if res:
+ uow().modified_lists.append(self.listpointer)
+ return res
class UnitOfWork(object):
def __init__(self):
self.new = util.HashSet()
self.dirty = util.HashSet()
+ self.modified_lists = util.HashSet()
self.deleted = util.HashSet()
self.attribute_history = weakref.WeakKeyDictionary()
try:
childlist = obj.__dict__[key]
except KeyError:
- childlist = util.HistoryArraySet()
+ childlist = UOWListElement(obj)
obj.__dict__[key] = childlist
if callable(childlist):
childlist = childlist()
if not isinstance(childlist, util.HistoryArraySet):
- childlist = util.HistoryArraySet(childlist)
+ childlist = UOWListElement(obj, childlist)
obj.__dict__[key] = childlist
if data is not None and childlist.data != data:
childlist.set_data(data)
mapper = sqlalchemy.mapper.object_mapper(obj)
mapperlist = mappers.setdefault(mapper, [])
mapperlist.append(obj)
-
+ for array in self.modified_lists:
+ mapper = sqlalchemy.mapper.object_mapper(array.list.obj())
+ mapperlist = mappers.setdefault(mapper, [])
+ mapperlist.append(array.list.obj())
+
for mapper in mappers.keys():
mapperlist = mappers[mapper]
+ print repr(mapperlist)
mapper.register_dependencies(mapperlist, self)
mapperlist = mappers.keys()
for mapper in mapperlist:
obj_list = mappers[mapper]
+ print "mapper " + mapper.table.name
deplist = self.dependencies.get(mapper, [])
+ print "deps " + repr(deplist)
for obj in obj_list:
mapper.save_obj(obj)
for dep in deplist:
self.new.clear()
self.dirty.clear()
+ for item in self.modified_lists:
+ item = item.list
+ item.clear_history()
+ self.modified_lists.clear()
def register_dependency(self, obj, dependency, processor, stuff_to_process):
self.dependencies[(obj, dependency)] = True