I generally dont have a lot of test cases for objectstore.commit(x), since Im not as confident in its ability to always find what its supposed to be acting upon, and it relies upon the user to give it something sane;  i.e. if you had an object C that had a reference to A, which A doesnt know about, then you set C.a to None, objectstore.delete(A) and commit(A), you get an error on that as well since you didnt give it C to commit...and i cant readily fix that one.

but a "private" relation is more clear cut, so for your thing below, I added some extra "delete" steps in the dependency traversal which catch your condition below as well as the opposite condition, if you had "B" with a many-to-one "A" attribute which was marked as private, and you deleted "B" and committed "B" alone.  You can try this change out in SVN rev 1186.

also consider UOW transactions for this kind of thing which also would have worked around this issue prior to this change:

trans = objectstore.begin()
objectstore.delete(a)
trans.commit()


On Mar 22, 2006, at 3:27 PM, Aaron Bickell wrote:


I'm trying to explicitly save/delete objects, and I ran into a snag with objectstore.delete().

# it gets no more generic than this
a_table = Table('a',
    Column('a_id', Integer, Sequence('next_a_id'), primary_key=True),
    Column('a', String(10)),
    Column('b',String(20)),
    Column('c',String(64)),
    Column('d',Integer))

b_table = Table('b',
    Column('b_id',Integer,Sequence('next_b_id'),primary_key=True),
    Column('a_id',Integer,ForeignKey('a.a_id')),
    Column('b',String(10)))

class A(object):pass
class B(object):pass

B.mapper = mapper(B,b_table)
A.mapper = mapper(A,a_table,properties= {'bs' : relation(B.mapper,private=True)})

A.mapper.table.create()
B.mapper.table.create()

# create some objects
a = A()
a.bs = []
a.a = 'heyhey'
a.b = 'pokey'

# add a 'B' instance
b = B()
b.b = '1111'
a.bs.append(b)

# add another one
b = B()
b.b = '2222'
a.bs.append(b)

engine.begin()

# inserts both A and Bs   
objectstore.commit(a)

objectstore.delete(a)
objectstore.commit(a)    # deletes only instance of 'A', not children -> foreign key exception

engine.commit()

(this is run against a postgres database)

Is this a bug or am I doing something wrong?  I was very pleased to find this ability to explicitly issue the sql statements for a give graph of objects, and in fact, solves most of the issues that I've come across with sqlalchemy.  The combination of objectstore.commit/delete/remove for a given object is really useful, particularly if you need the identifiers for the objects you are creating around the same time as you instantiate them (logging, etc), and you don't have to worry about sequences v. autoincrement.  

Aaron Bickell


Reply via email to