Opened 16 years ago

Closed 13 years ago

#6386 closed (fixed)

hash() in creating db names is unpredictable, and unnecessary

Reported by: Ned Batchelder Owned by: elbarto
Component: Core (Other) Version: dev
Severity: Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In this code fragment from django/core/management/sql.py:

    # For MySQL, r_name must be unique in the first 64 characters.
    # So we are careful with character usage here.
    r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
    final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
        (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()),
        qn(r_col), qn(table), qn(col),
        connection.ops.deferrable_sql()))

The r_name is computed with a hash() component. This creates a shorter name, but hash() is not guaranteed to be stable across versions of Python or across 32- and 64-bit architectures. This makes the SQL produced by a model unpredictable, and a development machine and production machine in the same shop could disagree on names.

This became a problem for us when we had to write db upgrades on one machine and apply them to another. We use the SQL generation to verify that the upgrade was successful, and the difference in the names made the validation fail.

The r_name variable is eventually passed into truncate_name anyway: this function does the right thing, shortening the name by using md5 to produce a repeatable hash from the text of the name.

If we remove the hash() from the name generation, we'll have repeatable names.

Change History (3)

comment:1 by Thomas Güttler, 16 years ago

Triage Stage: UnreviewedAccepted

I can confirm that this is a problem. I had problems with the random name, too.

I wanted to delete a foreign key constraint (the history should remain, even if
the model instance was deleted).

I used this with postgres to get the name of the constraint:

select constraint_name from information_schema.key_column_usage where table_name='myapp_history' and column_name='mymodel_id' 

comment:2 by elbarto, 13 years ago

Owner: changed from nobody to elbarto

comment:3 by elbarto, 13 years ago

Resolution: fixed
Status: newclosed

The ticket is obsolete. It was fixed in r8296 where the database backend code was refactored.

Note: See TracTickets for help on using tickets.
Back to Top