app/django/db/backends/mysql/introspection.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 from django.db.backends.mysql.base import DatabaseOperations
       
     2 from MySQLdb import ProgrammingError, OperationalError
       
     3 from MySQLdb.constants import FIELD_TYPE
       
     4 import re
       
     5 
       
     6 quote_name = DatabaseOperations().quote_name
       
     7 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
       
     8 
       
     9 def get_table_list(cursor):
       
    10     "Returns a list of table names in the current database."
       
    11     cursor.execute("SHOW TABLES")
       
    12     return [row[0] for row in cursor.fetchall()]
       
    13 
       
    14 def get_table_description(cursor, table_name):
       
    15     "Returns a description of the table, with the DB-API cursor.description interface."
       
    16     cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
       
    17     return cursor.description
       
    18 
       
    19 def _name_to_index(cursor, table_name):
       
    20     """
       
    21     Returns a dictionary of {field_name: field_index} for the given table.
       
    22     Indexes are 0-based.
       
    23     """
       
    24     return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))])
       
    25 
       
    26 def get_relations(cursor, table_name):
       
    27     """
       
    28     Returns a dictionary of {field_index: (field_index_other_table, other_table)}
       
    29     representing all relationships to the given table. Indexes are 0-based.
       
    30     """
       
    31     my_field_dict = _name_to_index(cursor, table_name)
       
    32     constraints = []
       
    33     relations = {}
       
    34     try:
       
    35         # This should work for MySQL 5.0.
       
    36         cursor.execute("""
       
    37             SELECT column_name, referenced_table_name, referenced_column_name
       
    38             FROM information_schema.key_column_usage
       
    39             WHERE table_name = %s
       
    40                 AND table_schema = DATABASE()
       
    41                 AND referenced_table_name IS NOT NULL
       
    42                 AND referenced_column_name IS NOT NULL""", [table_name])
       
    43         constraints.extend(cursor.fetchall())
       
    44     except (ProgrammingError, OperationalError):
       
    45         # Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
       
    46         # Go through all constraints and save the equal matches.
       
    47         cursor.execute("SHOW CREATE TABLE %s" % quote_name(table_name))
       
    48         for row in cursor.fetchall():
       
    49             pos = 0
       
    50             while True:
       
    51                 match = foreign_key_re.search(row[1], pos)
       
    52                 if match == None:
       
    53                     break
       
    54                 pos = match.end()
       
    55                 constraints.append(match.groups())
       
    56 
       
    57     for my_fieldname, other_table, other_field in constraints:
       
    58         other_field_index = _name_to_index(cursor, other_table)[other_field]
       
    59         my_field_index = my_field_dict[my_fieldname]
       
    60         relations[my_field_index] = (other_field_index, other_table)
       
    61 
       
    62     return relations
       
    63 
       
    64 def get_indexes(cursor, table_name):
       
    65     """
       
    66     Returns a dictionary of fieldname -> infodict for the given table,
       
    67     where each infodict is in the format:
       
    68         {'primary_key': boolean representing whether it's the primary key,
       
    69          'unique': boolean representing whether it's a unique index}
       
    70     """
       
    71     cursor.execute("SHOW INDEX FROM %s" % quote_name(table_name))
       
    72     indexes = {}
       
    73     for row in cursor.fetchall():
       
    74         indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
       
    75     return indexes
       
    76 
       
    77 DATA_TYPES_REVERSE = {
       
    78     FIELD_TYPE.BLOB: 'TextField',
       
    79     FIELD_TYPE.CHAR: 'CharField',
       
    80     FIELD_TYPE.DECIMAL: 'DecimalField',
       
    81     FIELD_TYPE.DATE: 'DateField',
       
    82     FIELD_TYPE.DATETIME: 'DateTimeField',
       
    83     FIELD_TYPE.DOUBLE: 'FloatField',
       
    84     FIELD_TYPE.FLOAT: 'FloatField',
       
    85     FIELD_TYPE.INT24: 'IntegerField',
       
    86     FIELD_TYPE.LONG: 'IntegerField',
       
    87     FIELD_TYPE.LONGLONG: 'IntegerField',
       
    88     FIELD_TYPE.SHORT: 'IntegerField',
       
    89     FIELD_TYPE.STRING: 'CharField',
       
    90     FIELD_TYPE.TIMESTAMP: 'DateTimeField',
       
    91     FIELD_TYPE.TINY: 'IntegerField',
       
    92     FIELD_TYPE.TINY_BLOB: 'TextField',
       
    93     FIELD_TYPE.MEDIUM_BLOB: 'TextField',
       
    94     FIELD_TYPE.LONG_BLOB: 'TextField',
       
    95     FIELD_TYPE.VAR_STRING: 'CharField',
       
    96 }