On 09/11/2010 04:31 AM, alex wrote:
>  On 09/10/2010 05:41 PM, Michael Bayer wrote:
>> On Sep 10, 2010, at 4:13 AM, alex wrote:
>>
>>> hello friends,
>>>
>>> as sqlite has recently introduced support for on delete/update cascade,
>>> i'd like to implement the passive_* functionality for this driver too.
>>>
>>> please give me a hint where to start.
>> passive_delete and passive_update are database agnostic and only apply to 
>> what effects the ORM can expect from the underlying schema, just use them 
>> normally.
>>
> thanks a lot for your response michael.
> i spent a little time to make a more isolated test case, and it works with
> sa+orm, but not with elixir, that seems to forget to pass the passive_deletes.
> i'm further inquiring there, in a hope to make a patch.
>
> best regards,
> alex
one further step took me closer to the problem. it happens with declarative too.
i'm attaching 3 scripts for comparison: one made with regular orm, one with
elixir and one with declarative. the same problem with elixir and declarative.
haven't tested on other rdbms.


-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
                        create_engine, ForeignKeyConstraint)
from sqlalchemy.orm import scoped_session, sessionmaker, relation
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("sqlite:///:memory:", echo=True)

Base = declarative_base(bind=engine)


class MyClass(Base):
    __tablename__ = 'mytable'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name =  Column(String(50))
#    children = relation('MyOtherClass', backref='parent')

    def __repr__(self):
        return '<MyClass %s, "%s">' % ("None" if self.id is None else str(self.id), self.name)

class MyOtherClass(Base):
    __tablename__ = 'myothertable'
    id = Column(Integer, primary_key=True, autoincrement=True)
    parent_id = Column(Integer, ForeignKey('mytable.id', ondelete="CASCADE"))
    parent = relation('MyClass', backref='children', passive_deletes=True)
    name =  Column(String(50))

    def __repr__(self):
        return '<MyOtherClass %s, %s, "%s">' % ("None" if self.parent_id is None else str(self.parent_id), "None" if self.id is None else str(self.id), self.name)

Base.metadata.create_all(engine)

session = scoped_session(sessionmaker(autocommit=False,
                                      autoflush=False,
                                      bind=engine))


alex = MyClass(name='alex')
pisi = MyClass(name='pisi')

session.add_all([
    alex, pisi
])

print alex, pisi

session.flush()

session.add_all([
    MyOtherClass(parent=alex, name='dagan'),
    MyOtherClass(parent=alex, name='shaked'),
    MyOtherClass(parent=pisi, name='dagan'),
    MyOtherClass(parent=pisi, name='shaked'),
])

session.flush()

shaked1 = session.query(MyOtherClass).filter_by(parent_id=1, name=u'shaked')

session.delete(alex)

session.flush()

for my in session.query(MyClass).all():
    print my
for my in session.query(MyOtherClass).all():
    print my

from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
                        create_engine, ForeignKeyConstraint)
from sqlalchemy.orm import (mapper, relationship, sessionmaker)

from elixir import *


engine = create_engine("sqlite:///:memory:", echo=True)

metadata.bind = engine

connection = engine.connect()
connection.execute('PRAGMA foreign_keys = ON;')


class MyClass(Entity):
    using_options(tablename='mytable')
    id = Field(Integer, primary_key=True, autoincrement=True)
    name = Field(String(20))
#    children = OneToMany('MyOtherClass', ondelete="CASCADE", passive_deletes=True)

    def __repr__(self):
        return '<MyClass %s, "%s">' % ("None" if self.id is None else str(self.id), self.name)

class MyOtherClass(Entity):
    using_options(tablename='myothertable')
    id = Field(Integer, primary_key=True, autoincrement=True)
    name = Field(String(20))
    parent = ManyToOne('MyClass', backref='children', colname='parent_id', ondelete="cascade", passive_deletes=True)

    def __repr__(self):
        return '<MyOtherClass %s, %s, "%s">' % ("None" if self.parent_id is None else str(self.parent_id), "None" if self.id is None else str(self.id), self.name)


setup_all()
create_all()


alex = MyClass(name='alex')
pisi = MyClass(name='pisi')

print alex, pisi

#session.commit()
session.flush()

print alex, pisi

alexdagan = MyOtherClass(parent=alex, name='dagan')
alexshaked = MyOtherClass(parent=alex, name='shaked')
pisidagan = MyOtherClass(parent=pisi, name='dagan')
pisishaked = MyOtherClass(parent=pisi, name='shaked')

#session.commit()
session.flush()

shaked1 = session.query(MyOtherClass).filter_by(parent_id=1, name=u'shaked')

session.delete(alex)

#session.commit()
session.flush()


for my in session.query(MyClass).all():
    print my
for my in session.query(MyOtherClass).all():
    print my

from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
                        create_engine, ForeignKeyConstraint)
from sqlalchemy.orm import (mapper, relationship, sessionmaker)


meta = MetaData()

engine = create_engine("sqlite:///:memory:", echo=True)

connection = engine.connect()
connection.execute('PRAGMA foreign_keys = ON;')

meta.create_all(engine)

mytable = Table('mytable', meta,
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('name', String(20)),
    )

myothertable = Table('myothertable', meta,
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('parent_id', Integer),
    Column('name', String(20)),
    ForeignKeyConstraint(['parent_id'], ['mytable.id'], ondelete="CASCADE"),
    )

class OldStyleBaseClass(object):
    """A base class for our SA object that do not use declarative, This simply provides keyword access for init and a decent print output, original recipe from http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GenericOrmBaseClass""";
    def __init__(self, **kw):
        for key in kw:
            if not key.startswith('_'):
                setattr(self, key, kw[key])

    def __repr__(self):
        attrs = []
        for key in self.__dict__:
            if not key.startswith('_'):
                attrs.append((key, getattr(self, key)))
        return self.__class__.__name__ + '(' + ', '.join(x[0] + '=' +
                                            repr(x[1]) for x in attrs) + ')'

    def to_dict(self):
        """Generate a JSON-style dict from a record."""
        data = dict([(key, getattr(self, key)) 
                     for key in self.__dict__ if not key.startswith('_')])
        return data

class MyClass(OldStyleBaseClass):
    pass

class MyOtherClass(OldStyleBaseClass):
    pass

mapper(MyOtherClass, myothertable)

mapper(MyClass, mytable, properties={
    'children': relationship(MyOtherClass, backref='parent', passive_deletes=True)
})

meta.create_all(engine)
session = sessionmaker(engine, expire_on_commit=False)()

alex = MyClass(name='alex')
pisi = MyClass(name='pisi')

session.add_all([
    alex, pisi
])

print alex, pisi

session.flush()

session.add_all([
    MyOtherClass(parent=alex, name='dagan'),
    MyOtherClass(parent=alex, name='shaked'),
    MyOtherClass(parent=pisi, name='dagan'),
    MyOtherClass(parent=pisi, name='shaked'),
])

session.flush()

shaked1 = session.query(MyOtherClass).filter_by(parent_id=1, name=u'shaked')

session.delete(alex)

session.flush()

for my in session.query(MyClass).all():
    print my
for my in session.query(MyOtherClass).all():
    print my

Reply via email to