Thanks for the fast help, Francisco!  That tip about the metadata
object is very handy.  I'm now able to migrate using DeclarativeBase.
Copy-and-paste just got much easier!  One thing, I do have to include
the  'useexisting':True in table_args, even for new tables such as
Account.  Otherwise I get: "Table 'account' is already defined for
this MetaData instance".  Something going on under the SQLAlchemy hood
that I don't understand, I guess.

I'm still not able to wrap table creates within transactions.  I am
using InnoDB, and I think there are some other engines for mySQL
(falcon) that support transactions, but I can't figure out how to make
it happen for table creation.  This is just one of several things I
tried including autocommit=false, and the transaction object.  It is a
bit of an inconvenience while debugging your code, but manageable.
...
Session = sessionmaker(autocommit=True) # Or False if you want to do a
manual commit with each DB change
Session.configure(bind=migrate_engine)
session = Session()
mysql_engine_type = 'InnoDB'
...
class Account (DeclarativeBase):
        __tablename__= 'account'
        __table_args__ = {'mysql_engine':mysql_engine_type,
'useexisting':True} <<=== IMPORTANT TO ADD

        id = Column(Integer, primary_key=True)
        tm_customer_id = Column(Integer, ForeignKey('company.id'),
nullable=False)
        parent_id = Column(ForeignKey('account.id'), nullable=True)
        name = Column(Unicode(20), nullable=True)
        description = Column(Unicode(100), nullable=True)
        balance = Column(Numeric(scale=2, asdecimal=True))
        isHidden = Column(BOOLEAN)
        type = Column (String(15))

... Other classes here...

def upgrade():
        try:
                session.begin() # Start transaction, but tables are always 
committed
(See below)
        
DeclarativeBase.metadata.tables[Account.__tablename__].create(migrate_engine)
        
DeclarativeBase.metadata.tables[AccountingOperator.__tablename__].create(migrate_engine)
                # This next line causes an exception.  If a
transaction, none previous would commit
        
DeclarativeBase.metadata.tables[FAILONItemGroup.__tablename__].create(migrate_engine)
                session.commit() # End transaction for table creation
                session.begin() # Start transaction for inserts, alters, etc.
                # Adding data, cols, etc is transactional and behaves
as expected
                ...
                session.commit()
                print "UPGRADE SUCCESSFUL"
        except:
                print "UPGRADE FAILURE, ROLLING BACK"
                session.rollback()

Now the SQL echo when the Account table is created.  The commit is
still there.

Upgrading...2010-06-18 00:39:13,507 INFO sqlalchemy.engine.base.Engine.
0x...09d0
CREATE TABLE account (
        id INTEGER NOT NULL AUTO_INCREMENT,
        tm_customer_id INTEGER NOT NULL,
        parent_id INTEGER,
        name VARCHAR(20),
        description VARCHAR(100),
        balance NUMERIC(10, 2),
        `isHidden` BOOL,
        type VARCHAR(15),
        PRIMARY KEY (id),
         FOREIGN KEY(tm_customer_id) REFERENCES company (id),
         FOREIGN KEY(parent_id) REFERENCES account (id)
)ENGINE=InnoDB

2010-06-18 00:39:13,507 INFO sqlalchemy.engine.base.Engine.0x...09d0
()
2010-06-18 00:39:13,571 INFO sqlalchemy.engine.base.Engine.0x...09d0
COMMIT
2010-06-18 00:39:13,573 INFO sqlalchemy.engine.base.Engine.0x...09d0

On Jun 17, 6:00 am, Francisco Souza <franci...@franciscosouza.net>
wrote:
> > Hi ,
>
> > [...]
>
> > But do I do this?  Part of the problem is that I don't know of a way
> > to generate tables other than  create_all() (or drop_all()) when using
> > declarative syntax.  Is there another way?
>
> Hi Shane :)
>
> When you bind your declarative base to a metadata, the "metadata" object has
> a attribute called "tables", wich is a dict with all tables containeds in
> this metadata. So, you can do a create for a single table easily.
>
> >>> Base.metadata.tables['test_case'].create(engine)
>
> You can call it on your upgrade function inside the migration module.
>
> 2) Can MySQL wrap Table.create() in a transaction so that if something fails
>
> > during upgrade/downgrade I don't litter up my DB with tables?  I don't think
> > MySQL can, but maybe I am wrong.  I think some others (PostgreSQL) can.
>
> I do not know how to answer this question, becausa I am not experienced with
> MySQL, but I can check this out. What I know is that MySQL supports
> transactions only when you are working with InnoDB engine.
>
> Best wishes,
> Francisco Souza
> Software developer at Giran and also full time
> Open source evangelist at full time
>
> http://www.franciscosouza.com.br
> Twitter: @franciscosouza
> (27) 3026 0264

-- 
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.

Reply via email to