~kkubasik/django/aggregation-branch

« back to all changes in this revision

Viewing changes to django/db/backends/mysql/introspection.py

  • Committer: adrian
  • Date: 2006-05-02 01:31:56 UTC
  • Revision ID: vcs-imports@canonical.com-20060502013156-2941fcd40d080649
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.db import transaction
 
2
from django.db.backends.mysql.base import quote_name
 
3
from MySQLdb import ProgrammingError, OperationalError
 
4
from MySQLdb.constants import FIELD_TYPE
 
5
import re
 
6
 
 
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 referenced_table_name IS NOT NULL
 
41
                AND referenced_column_name IS NOT NULL""", [table_name])
 
42
        constraints.extend(cursor.fetchall())
 
43
    except (ProgrammingError, OperationalError):
 
44
        # Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
 
45
        # Go through all constraints and save the equal matches.
 
46
        cursor.execute("SHOW CREATE TABLE %s" % table_name)
 
47
        for row in cursor.fetchall():
 
48
            pos = 0
 
49
            while True:
 
50
                match = foreign_key_re.search(row[1], pos)
 
51
                if match == None:
 
52
                    break
 
53
                pos = match.end()
 
54
                constraints.append(match.groups())
 
55
 
 
56
    for my_fieldname, other_table, other_field in constraints:
 
57
        other_field_index = _name_to_index(cursor, other_table)[other_field]
 
58
        my_field_index = my_field_dict[my_fieldname]
 
59
        relations[my_field_index] = (other_field_index, other_table)
 
60
 
 
61
    return relations
 
62
 
 
63
def get_indexes(cursor, table_name):
 
64
    """
 
65
    Returns a dictionary of fieldname -> infodict for the given table,
 
66
    where each infodict is in the format:
 
67
        {'primary_key': boolean representing whether it's the primary key,
 
68
         'unique': boolean representing whether it's a unique index}
 
69
    """
 
70
    cursor.execute("SHOW INDEX FROM %s" % quote_name(table_name))
 
71
    indexes = {}
 
72
    for row in cursor.fetchall():
 
73
        indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
 
74
    return indexes
 
75
 
 
76
DATA_TYPES_REVERSE = {
 
77
    FIELD_TYPE.BLOB: 'TextField',
 
78
    FIELD_TYPE.CHAR: 'CharField',
 
79
    FIELD_TYPE.DECIMAL: 'FloatField',
 
80
    FIELD_TYPE.DATE: 'DateField',
 
81
    FIELD_TYPE.DATETIME: 'DateTimeField',
 
82
    FIELD_TYPE.DOUBLE: 'FloatField',
 
83
    FIELD_TYPE.FLOAT: 'FloatField',
 
84
    FIELD_TYPE.INT24: 'IntegerField',
 
85
    FIELD_TYPE.LONG: 'IntegerField',
 
86
    FIELD_TYPE.LONGLONG: 'IntegerField',
 
87
    FIELD_TYPE.SHORT: 'IntegerField',
 
88
    FIELD_TYPE.STRING: 'TextField',
 
89
    FIELD_TYPE.TIMESTAMP: 'DateTimeField',
 
90
    FIELD_TYPE.TINY_BLOB: 'TextField',
 
91
    FIELD_TYPE.MEDIUM_BLOB: 'TextField',
 
92
    FIELD_TYPE.LONG_BLOB: 'TextField',
 
93
    FIELD_TYPE.VAR_STRING: 'CharField',
 
94
}