Changeset 72

Show
Ignore:
Timestamp:
02/27/07 15:31:10 (6 years ago)
Author:
ged
Message:

- fixed foreign key names on MySQL (and possibly other) databases by

making sure the generated name is unique for the whole database, and not
only for the table on which it applies.

- added example to front page
- added an explicit link to the cheese shop on the download page

Location:
elixir/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/CHANGES

    r71 r72  
    66  list that is neither threadsafe, nor safe when doing nested class  
    77  definition.  Also added a test to validate that this works. 
     8- fixed foreign key names on MySQL (and possibly other) databases by  
     9  making sure the generated name is unique for the whole database, and not 
     10  only for the table on which it applies. 
    811- implemented singletable non-polymorphic inheritance 
    912- added support to pass non-keyword arguments to tables. You just pass 
  • elixir/trunk/docs/download.rst

    r59 r72  
    1717        out how to use it (it's pretty easy, like the name promises). 
    1818 
     19 
     20Releases 
     21-------- 
     22 
     23Each release is also available for standard download on the `Cheese Shop 
     24<http://cheeseshop.python.org/pypi/Elixir/>`_ 
     25 
    1926Development Version 
    2027------------------- 
  • elixir/trunk/docs/index.rst

    r49 r72  
    1616focuses on providing a simpler syntax for defining model objects when you do 
    1717not need the full expressiveness of SQLAlchemy's manual mapper definitions. 
     18 
     19------- 
     20Example 
     21------- 
     22 
     23Here is a very short model definition example, so that you can see what the 
     24syntax look like. For some explanation and more complete examples, please have 
     25a look at the `tutorial <tutorial.html>`_ or at the  
     26`examples page <examples.html>`_. 
     27 
     28:: 
     29 
     30    class Person(Entity): 
     31        has_field('name', Unicode(255)) 
     32 
     33        has_many('addresses', of_kind='Address') 
     34 
     35 
     36    class Address(Entity): 
     37        has_field('email', String(128)) 
     38 
     39        belongs_to('person', of_kind='Person') 
     40 
    1841 
    1942------- 
  • elixir/trunk/elixir/relationships.py

    r70 r72  
    416416                self.primaryjoin_clauses.append(field.column == pk_col) 
    417417             
    418             # TODO: better constraint-naming? 
     418            # In some databases (at lease MySQL) the constraint name needs to  
     419            # be unique for the whole database, instead of per table. 
     420            fk_name = "%s_%s_fk" % (self.entity.table.name, self.name) 
    419421            source_desc.add_constraint(ForeignKeyConstraint( 
    420422                                            fk_colnames, fk_refcols, 
    421                                             name=self.name +'_fk', 
     423                                            name=fk_name, 
    422424                                            **self.constraint_kwargs)) 
    423425     
     
    514516                        % (self.entity.__name__, self.name) 
    515517                    ) 
     518 
     519            # We use the name of the relation for the first entity  
     520            # (instead of the name of its primary key), so that we can  
     521            # have two many-to-many relations between the same objects  
     522            # without having a table name collision.  
     523            source_part = "%s_%s" % (e1_desc.tablename, self.name) 
     524 
     525            # And we use the name of the primary key for the second entity 
     526            # when there is no inverse, so that a many-to-many relation  
     527            # can be defined without an inverse. 
     528            if self.inverse: 
     529                e2_name = self.inverse.name 
     530            else: 
     531                e2_name = '_'.join([key.column.name for key in 
     532                                    e2_desc.primary_keys]) 
     533            target_part = "%s_%s" % (e2_desc.tablename, e2_name) 
     534             
     535            if self.user_tablename: 
     536                tablename = self.user_tablename 
     537            else: 
     538                # we need to keep the table name consistent (independant of  
     539                # whether this relation or its inverse is setup first) 
     540                if self.inverse and e1_desc.tablename < e2_desc.tablename: 
     541                    tablename = "%s__%s" % (target_part, source_part) 
     542                else: 
     543                    tablename = "%s__%s" % (source_part, target_part) 
     544 
     545            # In some databases (at lease MySQL) the constraint names need  
     546            # to be unique for the whole database, instead of per table. 
     547            source_fk_name = "%s_fk" % source_part 
     548            if self.inverse: 
     549                target_fk_name = "%s_fk" % target_part 
     550            else: 
     551                target_fk_name = "%s_inverse_fk" % source_part 
     552 
    516553            columns = list() 
    517554            constraints = list() 
     
    520557            self.secondaryjoin_clauses = list() 
    521558 
    522             for num, desc, join_name in (('1', e1_desc, 'primary'),  
    523                                          ('2', e2_desc, 'secondary')): 
     559            for num, desc, join_name, fk_name in ( 
     560                    ('1', e1_desc, 'primary', source_fk_name),  
     561                    ('2', e2_desc, 'secondary', target_fk_name)): 
    524562                fk_colnames = list() 
    525563                fk_refcols = list() 
     
    550588                    join_list.append(col == pk_col) 
    551589                 
    552                 # TODO: better constraint-naming? 
    553590                constraints.append( 
    554591                    ForeignKeyConstraint(fk_colnames, fk_refcols, 
    555                                          name=desc.tablename + '_fk')) 
    556  
    557             if self.user_tablename: 
    558                 tablename = self.user_tablename 
    559             else: 
    560                 # We use the name of the relation for the first entity  
    561                 # (instead of the name of its primary key), so that we can  
    562                 # have two many-to-many relations between the same objects  
    563                 # without having a table name collision.  
    564                 source_part = "%s_%s" % (e1_desc.tablename, self.name) 
    565  
    566                 # And we use the name of the primary key for the second entity 
    567                 # when there is no inverse, so that a many-to-many relation  
    568                 # can be defined without an inverse. 
    569                 if self.inverse: 
    570                     e2_name = self.inverse.name 
    571                 else: 
    572                     e2_name = '_'.join([key.column.name for key in 
    573                                         e2_desc.primary_keys]) 
    574                 target_part = "%s_%s" % (e2_desc.tablename, e2_name) 
    575  
    576                 # we need to keep the table name consistent (independant of  
    577                 # whether this relation or its inverse is setup first) 
    578                 if self.inverse and e1_desc.tablename < e2_desc.tablename: 
    579                     tablename = "%s__%s" % (target_part, source_part) 
    580                 else: 
    581                     tablename = "%s__%s" % (source_part, target_part) 
     592                                         name=fk_name)) 
     593 
    582594 
    583595            args = columns + constraints