On Feb 27, 2012, at 9:55 AM, lars van gemerden wrote:

> Thank you for the extensive reply. It makes things a lot clearer;
> still i am not sure about how to continue.
> 
> Conceptually i would like to create 2 sets of tables/classes in a
> database (as part of a prototype):
> 
> 1) one set of tables/classes with the parameters to generate other
> classes/tables from,
> 2) one set of tables/classes that is automatically generated from the
> parameters in the first set. It will feature joined inheritance with
> only one root base table/class.

> 
> The only database link between these two sets is the 'polymorphic on'
> column in the root base table in set 2, which is a foreign key to a
> Type table in set 1.
> 
> For a typical test i would like to:
> 
> 1) create records in set 1 of tables (representing classes/tables with
> their attributes/foreign keys and fields),
> 2) from these records generate the tables/classes, where the tables
> will be in set 2.
> 3) add records to the generated tables/classes and test whether
> adding, updating, deleting and querying works as intended.
> 
> To be able to perform multiple of these tests in one run, i need to
> empty the tables of set 1. However i need to completely remove any
> data (mappings, class definitions, records, tables) from set 2,
> between individual tests.


so what I would do is:

1. the "other tables" generated would be in their own MetaData object.  After 
you've done drop_all() for those, throw that whole MetaData away.
2. the "other classes" generated, I'm assuming these are generated as the 
result of some function being called and aren't declared within a module.   
When you're done with them, throw them away too.   
3. The next run of tests would redo the entire process, using a new MetaData 
object, and generating new classes.

Key here is that there's no point at which the dynamically generated 
classes/tables/mappers need to be present as de-composed elements, once they've 
been composed.   They're just thrown away.

Using two Base classes would be an easy way to achieve this.   


> 
> I (naively) thought of some ways this might be possible:
> 
> 1) use two separate metadata objects for the same database, bind them
> to separate 'Base' classes, one for each set  and replace the one
> representing set 2 before each individual test,
> 2) find some way to remove all data concerning set 2 of tables from
> mappings, metadata, database, etc. between tests,
> 3) use two databases, one for each set of tables and forego the
> foreign key realtionship between then (or maybe copy set 1 to the
> second database)
> 
> Please advise on which of these approaches are possible, more
> straightforward, ... or whether another approach might be more
> appropriate.
> 
> Cheers, Lars
> 
> 
> 
> 
> 
> 
> 
> On Feb 26, 10:47 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
>> On Feb 26, 2012, at 12:47 PM, lars van gemerden wrote:
>> 
>>> I was wrong, the method emptied the database, but I was checking the
>>> tables in the metadata.
>> 
>>> This time I am also removing the tables from the metadata, but if i
>>> generate the same tables in two separate test methods (with a call to
>>> tearDown ans setUp in between), I still get an error about a backref
>>> name on a relationship already existing.
>> 
>> OK I think you're mixing concepts up here, a backref is an ORM concept.  The 
>> Table and Metadata objects are part of Core and know absolutely nothing 
>> about the ORM or mappings.    Removing a Table from a particular MetaData 
>> has almost no effect as all the ORM mappings still point to it.  In reality 
>> the MetaData.remove() method is mostly useless, except that a create_all() 
>> will no longer hit that Table, foreign key references will no longer find 
>> it, and you can replace it with a new Table object of the same name, but 
>> again nothing to do with the ORM and nothing to do with the state of that 
>> removed Table, which still points to that MetaData and will otherwise 
>> function normally.
>> 
>> If you want to remove mappings, you can call clear_mappers().  The use case 
>> for removing individual mappers is not supported as there is no support for 
>> doing all the reverse bookkeeping of removing relationships(), backrefs, and 
>> inheritance structures, and there's really no need for such a feature.
>> 
>> Like MetaData.remove(), there's almost no real world use case for 
>> clear_mappers() except that of the SQLAlchemy unit tests themselves, or 
>> tests of other ORM-integration layers like Elixir, which are testing the ORM 
>> itself with various kinds of mappings against the same set of classes.
>> 
>> Unit tests in an outside world application would normally be against a 
>> schema that's an integral part of the application, and doesn't change with 
>> regards to classes.   There's virtually no reason in normal applications 
>> against a fixed schema to tear down mappings and table metadata between 
>> tests.    SQLAlchemy docs stress the Declarative pattern very much these 
>> days as we're really trying to get it across that the composition of class, 
>> table metadata, and mapping is best regarded as an atomic structure - it 
>> exists only as that composite, or not at all.   Breaking it apart has little 
>> use unless you're testing the mechanics of the mapping itself.
>> 
>> Throughout all of this, we are *not* talking about the tables and schema 
>> that are in the actual database.   It is typical that unit tests do drop all 
>> those tables in between test suites, and recreate them for another test 
>> suite.    Though I tend to favor not actually dropping / recreating and 
>> instead running the tests within a transaction that's rolled back at the end 
>> as it's much more efficient, especially on backends like Oracle, Postgresql, 
>> MSSQL where creates/drops are more expensive.   Dropping and recreating the 
>> tables in the database though is independent of the structure represented by 
>> Metadata/Table, though, that structure lives on and can be reused.    
>> Metadata/Table describes only the *structure* of a particular schema.   They 
>> are not linked to the actual *presence* of those tables within a target 
>> schema.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalchemy@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.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@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