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