web/lib/django/db/backends/postgresql/introspection.py
author ymh <ymh.work@gmail.com>
Tue, 15 Mar 2011 10:34:41 +0100
changeset 65 3d18d15135f1
parent 38 77b6da96e6f1
permissions -rw-r--r--
put video url in segment object
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
from django.db.backends import BaseDatabaseIntrospection
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
class DatabaseIntrospection(BaseDatabaseIntrospection):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
    # Maps type codes to Django Field types.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
    data_types_reverse = {
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
        16: 'BooleanField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
        20: 'BigIntegerField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
        21: 'SmallIntegerField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
        23: 'IntegerField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
        25: 'TextField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
        700: 'FloatField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
        701: 'FloatField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
        869: 'IPAddressField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        1043: 'CharField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
        1082: 'DateField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
        1083: 'TimeField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
        1114: 'DateTimeField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
        1184: 'DateTimeField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
        1266: 'TimeField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
        1700: 'DecimalField',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    }
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    def get_table_list(self, cursor):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
        "Returns a list of table names in the current database."
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        cursor.execute("""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
            SELECT c.relname
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
            FROM pg_catalog.pg_class c
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
            WHERE c.relkind IN ('r', 'v', '')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
                AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
                AND pg_catalog.pg_table_is_visible(c.oid)""")
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
        return [row[0] for row in cursor.fetchall()]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
    def get_table_description(self, cursor, table_name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        "Returns a description of the table, with the DB-API cursor.description interface."
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        return cursor.description
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    def get_relations(self, cursor, table_name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        Returns a dictionary of {field_index: (field_index_other_table, other_table)}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        representing all relationships to the given table. Indexes are 0-based.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        cursor.execute("""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
            SELECT con.conkey, con.confkey, c2.relname
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
            FROM pg_constraint con, pg_class c1, pg_class c2
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
            WHERE c1.oid = con.conrelid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
                AND c2.oid = con.confrelid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
                AND c1.relname = %s
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
                AND con.contype = 'f'""", [table_name])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        relations = {}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        for row in cursor.fetchall():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
            try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
                # row[0] and row[1] are like "{2}", so strip the curly braces.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
                relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
            except ValueError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
                continue
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        return relations
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
    def get_indexes(self, cursor, table_name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        Returns a dictionary of fieldname -> infodict for the given table,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        where each infodict is in the format:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
            {'primary_key': boolean representing whether it's the primary key,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
             'unique': boolean representing whether it's a unique index}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
        # This query retrieves each index on the given table, including the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
        # first associated field name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
        cursor.execute("""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
            SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
            FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
                pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
            WHERE c.oid = idx.indrelid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
                AND idx.indexrelid = c2.oid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
                AND attr.attrelid = c.oid
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
                AND attr.attnum = idx.indkey[0]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
                AND c.relname = %s""", [table_name])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
        indexes = {}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
        for row in cursor.fetchall():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
            # row[1] (idx.indkey) is stored in the DB as an array. It comes out as
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
            # a string of space-separated integers. This designates the field
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
            # indexes (1-based) of the fields that have indexes on the table.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
            # Here, we skip any indexes across multiple fields.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
            if ' ' in row[1]:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                continue
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
            indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
        return indexes
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88