[Grok-dev] Re: STORM howto
Laurence Rowe
l at lrowe.co.uk
Mon Mar 17 07:06:40 EDT 2008
Martijn Faassen wrote:
> Laurence Rowe wrote:
>> Martijn Faassen wrote:
> [snip]
>>> You do generate the schemas in memory and then write them out? What
>>> prompted the decision to write them out?
>>
>> So I could see them and then more easily know how to subclass them -
>> for instance I needed to change the types of some fields (e.g. choice
>> instead of int, validators). Actually, recently I've moved away a bit
>> from the whole SQL first approach, mainly because I've changed
>> database twice in the past month.
>
> Interesting. I've had some discussions with the Storm people, and
> they're heavily in favor of the SQL first approach, as they feel no
> schema generation could create schemas that are really right (let alone
> accepted by DBAs if they're involved). My perspective is that there are
> situations (with smaller applications, without DBAs involved, just
> starting to develop) where it'd be nicer to have the schema be generated
> from Python, so it's a use case I'd like to try supporting at least to
> some level.
>
> Seeing that you came from the SQL first approach and are now moving the
> other way around, what is your reasoning surrounding this issue?
SQL first makes sense until you want to change database. I actually
ended up using metadata.reflect(pg_engine);
metadata.create_all(oracle_engine) - but with some fix ups in between
surrounding PassiveDefaults.
The differences between the sql dialects becomes frustrating too.
PassiveDefault(sql.text('some_func()')) gives you the power to customize
the DDL statement sufficiently.
> I think Grok should end up supporting both scenarios in some fashion,
> though that's a bit too much wishy-washy to be really nice to explain.
>
> Concerning generated schemas, I agree there are complexities involved
> when generating them during run-time. We need to play around with this
> some to see what's possible. I generally try to avoid code generation.
>
>> Starting now I would probably hack around with the declaritive stuff
>> to work out how to annotate the field info to the Column definitions
>> and autogenerate if not supplied.
>
> I'm not sure I follow you entirely, and I'm quite curious about this
> approach. :) Annotate what field info how? Zope 3 schema field info or
> something else?
Pure speculation, but the declarative example looks like:
class SomeClass(Base):
__tablename__ = 'some_table'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50))
Maybe it could be:
class SomeClass(Base):
__tablename__ = 'some_table'
id = Column('id', Integer, primary_key=True, field=schema.Int(...))
name = Column('name', String(50), field=schema.TextLine(...))
but generate a default field if none is supplied. No code generation
would be required.
It might then auto generate a SomeClass.__schema__ to go with the
__table__ and __mapper__ attributes.
> [snip]
>>> [collective.lead]
>>>> strictly zodb3 is not required, only transaction. The elro-tpc branch
>>>> will become 2.0 fairly soon. It pulls together some work done by
>>>> bitranch using scoped sessions and supporting the MyClass.query magic
>>>> and automatically associating new instances with sessions as well as
>>>> adding twophase and savepoint support. I just need to do a bit of
>>>> tidying up before I merge to trunk.
>>>
>>> I'm not sure what features you're referring to here; I'm not that
>>> familiar with SQLAlchemy. Are scoped sessions and MyClass.query magic
>>> both SQLAlchemy features? Would you recommend a new project starts
>>> with this branch?
>>
>> ScopedSessions provide per thread sessions and are a good thing.
>> Randomly they also seem to provide the option (using a special
>> session.mapper) to annotate your original class with information about
>> which metadata/session they belong too. Thinking again, I don't
>> recommend you use them. Too much magic. I've moved it to an
>> experimental module for now.
>
> So ScopedSessions are good, but the special mapper story is too much
> magic? Is that the MyClass.query magic you're talking about?
For the Plone story (and I assume the grok story too) it would limit
classes to a single session, when you may want to create multiple sites,
each with their own database, but sharing the same code. See
http://www.sqlalchemy.org/docs/04/session.html#unitofwork_contextual_associating
>> The more I think of it, I would limit the IDatabase interface to
>> session, engine and connection. It seems that the declarative approach
>> is to keep metadata separate. This should allow for having multiple
>> sites with their own databases using the same code for mappers.
>
> Where would one keep metadata around in this case?
It goes with the model. All related model objects would inherit from the
Base = declarative_base() class. The metadata object is then available
as Base.metadata, and presumably on all of the subclasses too.
> [snip]
Laurence
More information about the Grok-dev
mailing list