Django

Code

Changeset 6650

Show
Ignore:
Timestamp:
11/04/07 00:05:24 (10 months ago)
Author:
mtredinnick
Message:

Fixed #5729 -- For MySQL (only), always delay the creation of foreign key
references, for all tables, until after the table has been created. This means
that when using the InnoDB storage engine, true foreign key constraints are
created (inline "REFERENCES" are ignored by InnoDB, unfortunately).

Fully backwards compatible.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/management/sql.py

    r6298 r6650  
    253253    pending_references = {} 
    254254    qn = connection.ops.quote_name 
     255    inline_references = connection.features.inline_fk_references 
    255256    for f in opts.fields: 
    256257        col_type = f.db_type() 
     
    273274            field_output.append(connection.ops.tablespace_sql(tablespace, inline=True)) 
    274275        if f.rel: 
    275             if f.rel.to in known_models: 
     276            if inline_references and f.rel.to in known_models: 
    276277                field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \ 
    277278                    style.SQL_TABLE(qn(f.rel.to._meta.db_table)) + ' (' + \ 
     
    342343    from django.db import connection, models 
    343344    from django.contrib.contenttypes import generic 
     345    from django.db.backends.util import truncate_name 
    344346 
    345347    opts = model._meta 
    346348    final_output = [] 
    347349    qn = connection.ops.quote_name 
     350    inline_references = connection.features.inline_fk_references 
    348351    for f in opts.many_to_many: 
    349352        if not isinstance(f.rel, generic.GenericRel): 
     
    355358            table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ 
    356359                style.SQL_TABLE(qn(f.m2m_db_table())) + ' ('] 
    357             table_output.append('    %s %s %s%s,' % \ 
     360            table_output.append('    %s %s %s%s,' % 
    358361                (style.SQL_FIELD(qn('id')), 
    359362                style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()), 
    360363                style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), 
    361364                tablespace_sql)) 
    362             table_output.append('    %s %s %s %s (%s)%s,' % \ 
    363                 (style.SQL_FIELD(qn(f.m2m_column_name())), 
    364                 style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 
    365                 style.SQL_KEYWORD('NOT NULL REFERENCES'), 
    366                 style.SQL_TABLE(qn(opts.db_table)), 
    367                 style.SQL_FIELD(qn(opts.pk.column)), 
    368                 connection.ops.deferrable_sql())) 
    369             table_output.append('    %s %s %s %s (%s)%s,' % \ 
    370                 (style.SQL_FIELD(qn(f.m2m_reverse_name())), 
    371                 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()), 
    372                 style.SQL_KEYWORD('NOT NULL REFERENCES'), 
    373                 style.SQL_TABLE(qn(f.rel.to._meta.db_table)), 
    374                 style.SQL_FIELD(qn(f.rel.to._meta.pk.column)), 
    375                 connection.ops.deferrable_sql())) 
    376             table_output.append('    %s (%s, %s)%s' % \ 
     365            if inline_references: 
     366                deferred = [] 
     367                table_output.append('    %s %s %s %s (%s)%s,' % 
     368                    (style.SQL_FIELD(qn(f.m2m_column_name())), 
     369                    style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 
     370                    style.SQL_KEYWORD('NOT NULL REFERENCES'), 
     371                    style.SQL_TABLE(qn(opts.db_table)), 
     372                    style.SQL_FIELD(qn(opts.pk.column)), 
     373                    connection.ops.deferrable_sql())) 
     374                table_output.append('    %s %s %s %s (%s)%s,' % 
     375                    (style.SQL_FIELD(qn(f.m2m_reverse_name())), 
     376                    style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()), 
     377                    style.SQL_KEYWORD('NOT NULL REFERENCES'), 
     378                    style.SQL_TABLE(qn(f.rel.to._meta.db_table)), 
     379                    style.SQL_FIELD(qn(f.rel.to._meta.pk.column)), 
     380                    connection.ops.deferrable_sql())) 
     381            else: 
     382                table_output.append('    %s %s %s,' % 
     383                    (style.SQL_FIELD(qn(f.m2m_column_name())), 
     384                    style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 
     385                    style.SQL_KEYWORD('NOT NULL'))) 
     386                table_output.append('    %s %s %s,' % 
     387                    (style.SQL_FIELD(qn(f.m2m_reverse_name())), 
     388                    style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()), 
     389                    style.SQL_KEYWORD('NOT NULL'))) 
     390                deferred = [ 
     391                    (f.m2m_db_table(), f.m2m_column_name(), opts.db_table, 
     392                        opts.pk.column), 
     393                    ( f.m2m_db_table(), f.m2m_reverse_name(), 
     394                        f.rel.to._meta.db_table, f.rel.to._meta.pk.column) 
     395                    ] 
     396            table_output.append('    %s (%s, %s)%s' % 
    377397                (style.SQL_KEYWORD('UNIQUE'), 
    378398                style.SQL_FIELD(qn(f.m2m_column_name())), 
     
    385405            table_output.append(';') 
    386406            final_output.append('\n'.join(table_output)) 
     407 
     408            for r_table, r_col, table, col in deferred: 
     409                r_name = '%s_refs_%s_%x' % (r_col, col, 
     410                        abs(hash((r_table, table)))) 
     411                final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' %  
     412                (qn(r_table), 
     413                truncate_name(r_name, connection.ops.max_name_length()), 
     414                qn(r_col), qn(table), qn(col), 
     415                connection.ops.deferrable_sql())) 
    387416 
    388417            # Add any extra SQL needed to support auto-incrementing PKs 
  • django/trunk/django/db/backends/__init__.py

    r6601 r6650  
    4444    allows_unique_and_pk = True 
    4545    autoindexes_primary_keys = True 
     46    inline_fk_references = True 
    4647    needs_datetime_string_cast = True 
    4748    needs_upper_for_iops = False 
  • django/trunk/django/db/backends/mysql/base.py

    r6244 r6650  
    6262class DatabaseFeatures(BaseDatabaseFeatures): 
    6363    autoindexes_primary_keys = False 
     64    inline_fk_references = False 
    6465 
    6566class DatabaseOperations(BaseDatabaseOperations): 
  • django/trunk/django/db/backends/mysql_old/base.py

    r5983 r6650  
    6666class DatabaseFeatures(BaseDatabaseFeatures): 
    6767    autoindexes_primary_keys = False 
     68    inline_fk_references = False 
    6869 
    6970class DatabaseOperations(BaseDatabaseOperations):