Code

Ticket #5461: 5461.patch

File 5461.patch, 86.3 KB (added by brantley, 7 years ago)
  • test/utils.py

     
    11import sys, time 
    22from django.conf import settings 
    3 from django.db import connection, get_creation_module 
     3from django.db import connection 
    44from django.core import mail 
    55from django.core.management import call_command 
    66from django.dispatch import dispatcher 
     
    9595    database already exists. Returns the name of the test database created. 
    9696    """ 
    9797    # If the database backend wants to create the test DB itself, let it 
    98     creation_module = get_creation_module() 
    99     if hasattr(creation_module, "create_test_db"): 
    100         creation_module.create_test_db(settings, connection, verbosity, autoclobber) 
     98    if hasattr(connection.creation, "create_test_db"): 
     99        connection.creation.create_test_db(settings, connection, verbosity, autoclobber) 
    101100        return 
    102101 
    103102    if verbosity >= 1: 
     
    163162 
    164163def destroy_test_db(old_database_name, verbosity=1): 
    165164    # If the database wants to drop the test DB itself, let it 
    166     creation_module = get_creation_module() 
    167     if hasattr(creation_module, "destroy_test_db"): 
    168         creation_module.destroy_test_db(settings, connection, old_database_name, verbosity) 
     165    if hasattr(connection.creation, "destroy_test_db"): 
     166        connection.creation.destroy_test_db(settings, connection, old_database_name, verbosity) 
    169167        return 
    170168 
    171169    # Unless we're using SQLite, remove the test database to clean up after 
  • db/models/fields/__init__.py

     
    66except ImportError: 
    77    from django.utils import _decimal as decimal    # for Python 2.3 
    88 
    9 from django.db import get_creation_module 
    109from django.db.models import signals 
    1110from django.dispatch import dispatcher 
    1211from django.conf import settings 
     
    145144        # mapped to one of the built-in Django field types. In this case, you 
    146145        # can implement db_type() instead of get_internal_type() to specify 
    147146        # exactly which wacky database column type you want to use. 
    148         data_types = get_creation_module().DATA_TYPES 
     147        from django.db import connection 
     148        data_types = connection.creation.data_types 
    149149        internal_type = self.get_internal_type() 
    150150        return data_types[internal_type] % self.__dict__ 
    151151 
  • db/__init__.py

     
    2323    else: 
    2424        raise # If there's some other error, this must be an error in Django itself. 
    2525 
    26 get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, ['']) 
    27 get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) 
    2826runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell() 
    2927 
    3028connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) 
     
    4644def _rollback_on_exception(): 
    4745    from django.db import transaction 
    4846    transaction.rollback_unless_managed() 
    49 dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) 
     47dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) 
     48 No newline at end of file 
  • db/backends/ado_mssql/introspection.py

     
    1 def get_table_list(cursor): 
    2     raise NotImplementedError 
     1from django.db.backends.introspection import BaseIntrospection 
    32 
    4 def get_table_description(cursor, table_name): 
    5     raise NotImplementedError 
    6  
    7 def get_relations(cursor, table_name): 
    8     raise NotImplementedError 
    9  
    10 def get_indexes(cursor, table_name): 
    11     raise NotImplementedError 
    12  
    13 DATA_TYPES_REVERSE = {} 
     3class Introspection(BaseIntrospection): 
     4   pass 
     5    
  • db/backends/ado_mssql/creation.py

     
    1 DATA_TYPES = { 
    2     'AutoField':         'int IDENTITY (1, 1)', 
    3     'BooleanField':      'bit', 
    4     'CharField':         'varchar(%(max_length)s)', 
    5     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
    6     'DateField':         'smalldatetime', 
    7     'DateTimeField':     'smalldatetime', 
    8     'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
    9     'FileField':         'varchar(100)', 
    10     'FilePathField':     'varchar(100)', 
    11     'FloatField':        'double precision', 
    12     'ImageField':        'varchar(100)', 
    13     'IntegerField':      'int', 
    14     'IPAddressField':    'char(15)', 
    15     'NullBooleanField':  'bit', 
    16     'OneToOneField':     'int', 
    17     'PhoneNumberField':  'varchar(20)', 
    18     'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)', 
    19     'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)', 
    20     'SlugField':         'varchar(%(max_length)s)', 
    21     'SmallIntegerField': 'smallint', 
    22     'TextField':         'text', 
    23     'TimeField':         'time', 
    24     'USStateField':      'varchar(2)', 
    25 } 
     1from django.db.backends.creation import BaseCreation 
     2 
     3class Creation(BaseCreation): 
     4    data_types = { 
     5        'AutoField':         'int IDENTITY (1, 1)', 
     6        'BooleanField':      'bit', 
     7        'CharField':         'varchar(%(max_length)s)', 
     8        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
     9        'DateField':         'smalldatetime', 
     10        'DateTimeField':     'smalldatetime', 
     11        'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     12        'FileField':         'varchar(100)', 
     13        'FilePathField':     'varchar(100)', 
     14        'FloatField':        'double precision', 
     15        'ImageField':        'varchar(100)', 
     16        'IntegerField':      'int', 
     17        'IPAddressField':    'char(15)', 
     18        'NullBooleanField':  'bit', 
     19        'OneToOneField':     'int', 
     20        'PhoneNumberField':  'varchar(20)', 
     21        'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)', 
     22        'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)', 
     23        'SlugField':         'varchar(%(max_length)s)', 
     24        'SmallIntegerField': 'smallint', 
     25        'TextField':         'text', 
     26        'TimeField':         'time', 
     27        'USStateField':      'varchar(2)', 
     28    } 
  • db/backends/mysql_old/introspection.py

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

     
    1 # This dictionary maps Field objects to their associated MySQL column 
    2 # types, as strings. Column-type strings can contain format strings; they'll 
    3 # be interpolated against the values of Field.__dict__ before being output. 
    4 # If a column type is set to None, it won't be included in the output. 
    5 DATA_TYPES = { 
    6     'AutoField':         'integer AUTO_INCREMENT', 
    7     'BooleanField':      'bool', 
    8     'CharField':         'varchar(%(max_length)s)', 
    9     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
    10     'DateField':         'date', 
    11     'DateTimeField':     'datetime', 
    12     'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
    13     'FileField':         'varchar(100)', 
    14     'FilePathField':     'varchar(100)', 
    15     'FloatField':        'double precision', 
    16     'ImageField':        'varchar(100)', 
    17     'IntegerField':      'integer', 
    18     'IPAddressField':    'char(15)', 
    19     'NullBooleanField':  'bool', 
    20     'OneToOneField':     'integer', 
    21     'PhoneNumberField':  'varchar(20)', 
    22     'PositiveIntegerField': 'integer UNSIGNED', 
    23     'PositiveSmallIntegerField': 'smallint UNSIGNED', 
    24     'SlugField':         'varchar(%(max_length)s)', 
    25     'SmallIntegerField': 'smallint', 
    26     'TextField':         'longtext', 
    27     'TimeField':         'time', 
    28     'USStateField':      'varchar(2)', 
    29 } 
     1from django.db.backends.creation import BaseCreation 
     2 
     3class Creation(BaseCreation): 
     4    # This dictionary maps Field objects to their associated MySQL column 
     5    # types, as strings. Column-type strings can contain format strings; they'll 
     6    # be interpolated against the values of Field.__dict__ before being output. 
     7    # If a column type is set to None, it won't be included in the output. 
     8    data_types = { 
     9        'AutoField':         'integer AUTO_INCREMENT', 
     10        'BooleanField':      'bool', 
     11        'CharField':         'varchar(%(max_length)s)', 
     12        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
     13        'DateField':         'date', 
     14        'DateTimeField':     'datetime', 
     15        'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     16        'FileField':         'varchar(100)', 
     17        'FilePathField':     'varchar(100)', 
     18        'FloatField':        'double precision', 
     19        'ImageField':        'varchar(100)', 
     20        'IntegerField':      'integer', 
     21        'IPAddressField':    'char(15)', 
     22        'NullBooleanField':  'bool', 
     23        'OneToOneField':     'integer', 
     24        'PhoneNumberField':  'varchar(20)', 
     25        'PositiveIntegerField': 'integer UNSIGNED', 
     26        'PositiveSmallIntegerField': 'smallint UNSIGNED', 
     27        'SlugField':         'varchar(%(max_length)s)', 
     28        'SmallIntegerField': 'smallint', 
     29        'TextField':         'longtext', 
     30        'TimeField':         'time', 
     31        'USStateField':      'varchar(2)', 
     32    } 
  • db/backends/postgresql/introspection.py

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

     
    1 # This dictionary maps Field objects to their associated PostgreSQL column 
    2 # types, as strings. Column-type strings can contain format strings; they'll 
    3 # be interpolated against the values of Field.__dict__ before being output. 
    4 # If a column type is set to None, it won't be included in the output. 
    5 DATA_TYPES = { 
    6     'AutoField':         'serial', 
    7     'BooleanField':      'boolean', 
    8     'CharField':         'varchar(%(max_length)s)', 
    9     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
    10     'DateField':         'date', 
    11     'DateTimeField':     'timestamp with time zone', 
    12     'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
    13     'FileField':         'varchar(100)', 
    14     'FilePathField':     'varchar(100)', 
    15     'FloatField':        'double precision', 
    16     'ImageField':        'varchar(100)', 
    17     'IntegerField':      'integer', 
    18     'IPAddressField':    'inet', 
    19     'NullBooleanField':  'boolean', 
    20     'OneToOneField':     'integer', 
    21     'PhoneNumberField':  'varchar(20)', 
    22     'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', 
    23     'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)', 
    24     'SlugField':         'varchar(%(max_length)s)', 
    25     'SmallIntegerField': 'smallint', 
    26     'TextField':         'text', 
    27     'TimeField':         'time', 
    28     'USStateField':      'varchar(2)', 
    29 } 
     1from django.db.backends.creation import BaseCreation 
     2 
     3class Creation(BaseCreation): 
     4    # This dictionary maps Field objects to their associated PostgreSQL column 
     5    # types, as strings. Column-type strings can contain format strings; they'll 
     6    # be interpolated against the values of Field.__dict__ before being output. 
     7    # If a column type is set to None, it won't be included in the output. 
     8    data_types = { 
     9        'AutoField':         'serial', 
     10        'BooleanField':      'boolean', 
     11        'CharField':         'varchar(%(max_length)s)', 
     12        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
     13        'DateField':         'date', 
     14        'DateTimeField':     'timestamp with time zone', 
     15        'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     16        'FileField':         'varchar(100)', 
     17        'FilePathField':     'varchar(100)', 
     18        'FloatField':        'double precision', 
     19        'ImageField':        'varchar(100)', 
     20        'IntegerField':      'integer', 
     21        'IPAddressField':    'inet', 
     22        'NullBooleanField':  'boolean', 
     23        'OneToOneField':     'integer', 
     24        'PhoneNumberField':  'varchar(20)', 
     25        'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', 
     26        'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)', 
     27        'SlugField':         'varchar(%(max_length)s)', 
     28        'SmallIntegerField': 'smallint', 
     29        'TextField':         'text', 
     30        'TimeField':         'time', 
     31        'USStateField':      'varchar(2)', 
     32    } 
  • db/backends/sqlite3/introspection.py

     
     1from django.db.backends.introspection import BaseIntrospection 
    12from django.db.backends.sqlite3.base import DatabaseOperations 
    23 
    34quote_name = DatabaseOperations().quote_name 
     
    23 
    3 def get_table_list(cursor): 
    4     "Returns a list of table names in the current database." 
    5     # Skip the sqlite_sequence system table used for autoincrement key 
    6     # generation. 
    7     cursor.execute(""" 
    8         SELECT name FROM sqlite_master 
    9         WHERE type='table' AND NOT name='sqlite_sequence' 
    10         ORDER BY name""") 
    11     return [row[0] for row in cursor.fetchall()] 
    12  
    13 def get_table_description(cursor, table_name): 
    14     "Returns a description of the table, with the DB-API cursor.description interface." 
    15     return [(info['name'], info['type'], None, None, None, None, 
    16              info['null_ok']) for info in _table_info(cursor, table_name)] 
    17  
    18 def get_relations(cursor, table_name): 
    19     raise NotImplementedError 
    20  
    21 def get_indexes(cursor, table_name): 
    22     """ 
    23     Returns a dictionary of fieldname -> infodict for the given table, 
    24     where each infodict is in the format: 
    25         {'primary_key': boolean representing whether it's the primary key, 
    26          'unique': boolean representing whether it's a unique index} 
    27     """ 
    28     indexes = {} 
    29     for info in _table_info(cursor, table_name): 
    30         indexes[info['name']] = {'primary_key': info['pk'] != 0, 
    31                                  'unique': False} 
    32     cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name)) 
    33     # seq, name, unique 
    34     for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]: 
    35         if not unique: 
    36             continue 
    37         cursor.execute('PRAGMA index_info(%s)' % quote_name(index)) 
    38         info = cursor.fetchall() 
    39         # Skip indexes across multiple fields 
    40         if len(info) != 1: 
    41             continue 
    42         name = info[0][2] # seqno, cid, name 
    43         indexes[name]['unique'] = True 
    44     return indexes 
    45  
    46 def _table_info(cursor, name): 
    47     cursor.execute('PRAGMA table_info(%s)' % quote_name(name)) 
    48     # cid, name, type, notnull, dflt_value, pk 
    49     return [{'name': field[1], 
    50              'type': field[2], 
    51              'null_ok': not field[3], 
    52              'pk': field[5]     # undocumented 
    53              } for field in cursor.fetchall()] 
    54  
    55 # Maps SQL types to Django Field types. Some of the SQL types have multiple 
    56 # entries here because SQLite allows for anything and doesn't normalize the 
    57 # field type; it uses whatever was given. 
    58 BASE_DATA_TYPES_REVERSE = { 
    59     'bool': 'BooleanField', 
    60     'boolean': 'BooleanField', 
    61     'smallint': 'SmallIntegerField', 
    62     'smallinteger': 'SmallIntegerField', 
    63     'int': 'IntegerField', 
    64     'integer': 'IntegerField', 
    65     'text': 'TextField', 
    66     'char': 'CharField', 
    67     'date': 'DateField', 
    68     'datetime': 'DateTimeField', 
    69     'time': 'TimeField', 
    70 } 
    71  
    724# This light wrapper "fakes" a dictionary interface, because some SQLite data 
    735# types include variables in them -- e.g. "varchar(30)" -- and can't be matched 
    746# as a simple dictionary lookup. 
    757class FlexibleFieldLookupDict: 
     8    base_data_types_reverse = { 
     9        'bool': 'BooleanField', 
     10        'boolean': 'BooleanField', 
     11        'smallint': 'SmallIntegerField', 
     12        'smallinteger': 'SmallIntegerField', 
     13        'int': 'IntegerField', 
     14        'integer': 'IntegerField', 
     15        'text': 'TextField', 
     16        'char': 'CharField', 
     17        'date': 'DateField', 
     18        'datetime': 'DateTimeField', 
     19        'time': 'TimeField', 
     20    } 
     21     
    7622    def __getitem__(self, key): 
    7723        key = key.lower() 
    7824        try: 
    79             return BASE_DATA_TYPES_REVERSE[key] 
     25            return self.base_data_types_reverse[key] 
    8026        except KeyError: 
     
    8632                return ('CharField', {'max_length': int(m.group(1))}) 
    8733            raise KeyError 
    8834 
    89 DATA_TYPES_REVERSE = FlexibleFieldLookupDict() 
     35class Introspection(BaseIntrospection): 
     36    # Maps SQL types to Django Field types. Some of the SQL types have multiple 
     37    # entries here because SQLite allows for anything and doesn't normalize the 
     38    # field type; it uses whatever was given. 
     39    data_types_reverse = FlexibleFieldLookupDict() 
     40 
     41    def get_table_list(self, cursor): 
     42        "Returns a list of table names in the current database." 
     43        # Skip the sqlite_sequence system table used for autoincrement key 
     44        # generation. 
     45        cursor.execute(""" 
     46            SELECT name FROM sqlite_master 
     47            WHERE type='table' AND NOT name='sqlite_sequence' 
     48            ORDER BY name""") 
     49        return [row[0] for row in cursor.fetchall()] 
     50 
     51    def get_table_description(self, cursor, table_name): 
     52        "Returns a description of the table, with the DB-API cursor.description interface." 
     53        return [(info['name'], info['type'], None, None, None, None, 
     54                 info['null_ok']) for info in self._table_info(cursor, table_name)] 
     55 
     56    def get_relations(self, cursor, table_name): 
     57        raise NotImplementedError 
     58 
     59    def get_indexes(self, cursor, table_name): 
     60        """ 
     61        Returns a dictionary of fieldname -> infodict for the given table, 
     62        where each infodict is in the format: 
     63            {'primary_key': boolean representing whether it's the primary key, 
     64             'unique': boolean representing whether it's a unique index} 
     65        """ 
     66        indexes = {} 
     67        for info in self._table_info(cursor, table_name): 
     68            indexes[info['name']] = {'primary_key': info['pk'] != 0, 
     69                                     'unique': False} 
     70        cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name)) 
     71        # seq, name, unique 
     72        for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]: 
     73            if not unique: 
     74                continue 
     75            cursor.execute('PRAGMA index_info(%s)' % quote_name(index)) 
     76            info = cursor.fetchall() 
     77            # Skip indexes across multiple fields 
     78            if len(info) != 1: 
     79                continue 
     80            name = info[0][2] # seqno, cid, name 
     81            indexes[name]['unique'] = True 
     82        return indexes 
     83 
     84    def _table_info(self, cursor, name): 
     85        cursor.execute('PRAGMA table_info(%s)' % quote_name(name)) 
     86        # cid, name, type, notnull, dflt_value, pk 
     87        return [{'name': field[1], 
     88                 'type': field[2], 
     89                 'null_ok': not field[3], 
     90                 'pk': field[5]     # undocumented 
     91                 } for field in cursor.fetchall()] 
  • db/backends/sqlite3/creation.py

     
    11# SQLite doesn't actually support most of these types, but it "does the right 
    22# thing" given more verbose field definitions, so leave them as is so that 
    33# schema inspection is more useful. 
    4 DATA_TYPES = { 
    5     'AutoField':                    'integer', 
    6     'BooleanField':                 'bool', 
    7     'CharField':                    'varchar(%(max_length)s)', 
    8     'CommaSeparatedIntegerField':   'varchar(%(max_length)s)', 
    9     'DateField':                    'date', 
    10     'DateTimeField':                'datetime', 
    11     'DecimalField':                 'decimal', 
    12     'FileField':                    'varchar(100)', 
    13     'FilePathField':                'varchar(100)', 
    14     'FloatField':                   'real', 
    15     'ImageField':                   'varchar(100)', 
    16     'IntegerField':                 'integer', 
    17     'IPAddressField':               'char(15)', 
    18     'NullBooleanField':             'bool', 
    19     'OneToOneField':                'integer', 
    20     'PhoneNumberField':             'varchar(20)', 
    21     'PositiveIntegerField':         'integer unsigned', 
    22     'PositiveSmallIntegerField':    'smallint unsigned', 
    23     'SlugField':                    'varchar(%(max_length)s)', 
    24     'SmallIntegerField':            'smallint', 
    25     'TextField':                    'text', 
    26     'TimeField':                    'time', 
    27     'USStateField':                 'varchar(2)', 
    28 } 
     4from django.db.backends.creation import BaseCreation 
     5 
     6class Creation(BaseCreation): 
     7    data_types = { 
     8        'AutoField':                    'integer', 
     9        'BooleanField':                 'bool', 
     10        'CharField':                    'varchar(%(max_length)s)', 
     11        'CommaSeparatedIntegerField':   'varchar(%(max_length)s)', 
     12        'DateField':                    'date', 
     13        'DateTimeField':                'datetime', 
     14        'DecimalField':                 'decimal', 
     15        'FileField':                    'varchar(100)', 
     16        'FilePathField':                'varchar(100)', 
     17        'FloatField':                   'real', 
     18        'ImageField':                   'varchar(100)', 
     19        'IntegerField':                 'integer', 
     20        'IPAddressField':               'char(15)', 
     21        'NullBooleanField':             'bool', 
     22        'OneToOneField':                'integer', 
     23        'PhoneNumberField':             'varchar(20)', 
     24        'PositiveIntegerField':         'integer unsigned', 
     25        'PositiveSmallIntegerField':    'smallint unsigned', 
     26        'SlugField':                    'varchar(%(max_length)s)', 
     27        'SmallIntegerField':            'smallint', 
     28        'TextField':                    'text', 
     29        'TimeField':                    'time', 
     30        'USStateField':                 'varchar(2)', 
     31    } 
  • db/backends/mysql/introspection.py

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

     
    1 # This dictionary maps Field objects to their associated MySQL column 
    2 # types, as strings. Column-type strings can contain format strings; they'll 
    3 # be interpolated against the values of Field.__dict__ before being output. 
    4 # If a column type is set to None, it won't be included in the output. 
    5 DATA_TYPES = { 
    6     'AutoField':         'integer AUTO_INCREMENT', 
    7     'BooleanField':      'bool', 
    8     'CharField':         'varchar(%(max_length)s)', 
    9     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
    10     'DateField':         'date', 
    11     'DateTimeField':     'datetime', 
    12     'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
    13     'FileField':         'varchar(100)', 
    14     'FilePathField':     'varchar(100)', 
    15     'FloatField':        'double precision', 
    16     'ImageField':        'varchar(100)', 
    17     'IntegerField':      'integer', 
    18     'IPAddressField':    'char(15)', 
    19     'NullBooleanField':  'bool', 
    20     'OneToOneField':     'integer', 
    21     'PhoneNumberField':  'varchar(20)', 
    22     'PositiveIntegerField': 'integer UNSIGNED', 
    23     'PositiveSmallIntegerField': 'smallint UNSIGNED', 
    24     'SlugField':         'varchar(%(max_length)s)', 
    25     'SmallIntegerField': 'smallint', 
    26     'TextField':         'longtext', 
    27     'TimeField':         'time', 
    28     'USStateField':      'varchar(2)', 
    29 } 
     1from django.db.backends.creation import BaseCreation 
     2 
     3class Creation(BaseCreation): 
     4    # This dictionary maps Field objects to their associated MySQL column 
     5    # types, as strings. Column-type strings can contain format strings; they'll 
     6    # be interpolated against the values of Field.__dict__ before being output. 
     7    # If a column type is set to None, it won't be included in the output. 
     8    data_types = { 
     9        'AutoField':         'integer AUTO_INCREMENT', 
     10        'BooleanField':      'bool', 
     11        'CharField':         'varchar(%(max_length)s)', 
     12        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 
     13        'DateField':         'date', 
     14        'DateTimeField':     'datetime', 
     15        'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     16        'FileField':         'varchar(100)', 
     17        'FilePathField':     'varchar(100)', 
     18        'FloatField':        'double precision', 
     19        'ImageField':        'varchar(100)', 
     20        'IntegerField':      'integer', 
     21        'IPAddressField':    'char(15)', 
     22        'NullBooleanField':  'bool', 
     23        'OneToOneField':     'integer', 
     24        'PhoneNumberField':  'varchar(20)', 
     25        'PositiveIntegerField': 'integer UNSIGNED', 
     26        'PositiveSmallIntegerField': 'smallint UNSIGNED', 
     27        'SlugField':         'varchar(%(max_length)s)', 
     28        'SmallIntegerField': 'smallint', 
     29        'TextField':         'longtext', 
     30        'TimeField':         'time', 
     31        'USStateField':      'varchar(2)', 
     32    } 
  • db/backends/oracle/introspection.py

     
     1from django.db.backends.introspection import BaseIntrospection 
    12from django.db.backends.oracle.base import DatabaseOperations 
    23import re 
    34import cx_Oracle 
     
    56quote_name = DatabaseOperations().quote_name 
    67foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 
    78 
    8 def get_table_list(cursor): 
    9     "Returns a list of table names in the current database." 
    10     cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") 
    11     return [row[0].upper() for row in cursor.fetchall()] 
    12  
    13 def get_table_description(cursor, table_name): 
    14     "Returns a description of the table, with the DB-API cursor.description interface." 
    15     cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % quote_name(table_name)) 
    16     return cursor.description 
    17  
    18 def _name_to_index(cursor, table_name): 
    19     """ 
    20     Returns a dictionary of {field_name: field_index} for the given table. 
    21     Indexes are 0-based. 
    22     """ 
    23     return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))]) 
    24  
    25 def get_relations(cursor, table_name): 
    26     """ 
    27     Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
    28     representing all relationships to the given table. Indexes are 0-based. 
    29     """ 
    30     cursor.execute(""" 
     9class BaseIntrospection(BaseIntrospection): 
     10    data_types_reverse = { 
     11        cx_Oracle.CLOB: 'TextField', 
     12        cx_Oracle.DATETIME: 'DateTimeField', 
     13        cx_Oracle.FIXED_CHAR: 'CharField', 
     14        cx_Oracle.NCLOB: 'TextField', 
     15        cx_Oracle.NUMBER: 'DecimalField', 
     16        cx_Oracle.STRING: 'CharField', 
     17        cx_Oracle.TIMESTAMP: 'DateTimeField', 
     18    } 
     19         
     20    def get_table_list(self, cursor): 
     21        "Returns a list of table names in the current database." 
     22        cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") 
     23        return [row[0].upper() for row in cursor.fetchall()] 
     24     
     25    def get_table_description(self, cursor, table_name): 
     26        "Returns a description of the table, with the DB-API cursor.description interface." 
     27        cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % quote_name(table_name)) 
     28        return cursor.description 
     29         
     30    def get_relations(self, cursor, table_name): 
     31        """ 
     32        Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
     33        representing all relationships to the given table. Indexes are 0-based. 
     34        """ 
     35        cursor.execute(""" 
    3136SELECT ta.column_id - 1, tb.table_name, tb.column_id - 1 
    32 FROM   user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 
    33        user_tab_cols ta, user_tab_cols tb 
     37FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 
     38        user_tab_cols ta, user_tab_cols tb 
    3439WHERE  user_constraints.table_name = %s AND 
    35        ta.table_name = %s AND 
    36        ta.column_name = ca.column_name AND 
    37        ca.table_name = %s AND 
    38        user_constraints.constraint_name = ca.constraint_name AND 
    39        user_constraints.r_constraint_name = cb.constraint_name AND 
    40        cb.table_name = tb.table_name AND 
    41        cb.column_name = tb.column_name AND 
    42        ca.position = cb.position""", [table_name, table_name, table_name]) 
    43  
    44     relations = {} 
    45     for row in cursor.fetchall(): 
    46         relations[row[0]] = (row[2], row[1]) 
    47     return relations 
    48  
    49 def get_indexes(cursor, table_name): 
    50     """ 
    51     Returns a dictionary of fieldname -> infodict for the given table, 
    52     where each infodict is in the format: 
    53         {'primary_key': boolean representing whether it's the primary key, 
    54          'unique': boolean representing whether it's a unique index} 
    55     """ 
    56     # This query retrieves each index on the given table, including the 
    57     # first associated field name 
    58     # "We were in the nick of time; you were in great peril!" 
    59     sql = """ 
     40        ta.table_name = %s AND 
     41        ta.column_name = ca.column_name AND 
     42        ca.table_name = %s AND 
     43        user_constraints.constraint_name = ca.constraint_name AND 
     44        user_constraints.r_constraint_name = cb.constraint_name AND 
     45        cb.table_name = tb.table_name AND 
     46        cb.column_name = tb.column_name AND 
     47        ca.position = cb.position""", [table_name, table_name, table_name]) 
     48         
     49        relations = {} 
     50        for row in cursor.fetchall(): 
     51            relations[row[0]] = (row[2], row[1]) 
     52        return relations 
     53     
     54    def get_indexes(self, cursor, table_name): 
     55        """ 
     56        Returns a dictionary of fieldname -> infodict for the given table, 
     57        where each infodict is in the format: 
     58            {'primary_key': boolean representing whether it's the primary key, 
     59             'unique': boolean representing whether it's a unique index} 
     60        """ 
     61        # This query retrieves each index on the given table, including the 
     62        # first associated field name 
     63        # "We were in the nick of time; you were in great peril!" 
     64        sql = """ 
    6065WITH primarycols AS ( 
    6166 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 
    6267 FROM   user_cons_columns, user_constraints 
     
    7681WHERE  allcols.column_name = primarycols.column_name (+) AND 
    7782      allcols.column_name = uniquecols.column_name (+) 
    7883    """ 
    79     cursor.execute(sql, [table_name, table_name]) 
    80     indexes = {} 
    81     for row in cursor.fetchall(): 
    82         # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 
    83         # a string of space-separated integers. This designates the field 
    84         # indexes (1-based) of the fields that have indexes on the table. 
    85         # Here, we skip any indexes across multiple fields. 
    86         indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]} 
    87     return indexes 
    88  
    89 # Maps type objects to Django Field types. 
    90 DATA_TYPES_REVERSE = { 
    91     cx_Oracle.CLOB: 'TextField', 
    92     cx_Oracle.DATETIME: 'DateTimeField', 
    93     cx_Oracle.FIXED_CHAR: 'CharField', 
    94     cx_Oracle.NCLOB: 'TextField', 
    95     cx_Oracle.NUMBER: 'DecimalField', 
    96     cx_Oracle.STRING: 'CharField', 
    97     cx_Oracle.TIMESTAMP: 'DateTimeField', 
    98 } 
     84        cursor.execute(sql, [table_name, table_name]) 
     85        indexes = {} 
     86        for row in cursor.fetchall(): 
     87            # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 
     88            # a string of space-separated integers. This designates the field 
     89            # indexes (1-based) of the fields that have indexes on the table. 
     90            # Here, we skip any indexes across multiple fields. 
     91            indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]} 
     92        return indexes 
     93         
     94    def _name_to_index(self, cursor, table_name): 
     95        """ 
     96        Returns a dictionary of {field_name: field_index} for the given table. 
     97        Indexes are 0-based. 
     98        """ 
     99        return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))]) 
  • db/backends/oracle/creation.py

     
    11import sys, time 
    22from django.core import management 
     3from django.db.backends.creation import BaseCreation 
    34 
    4 # This dictionary maps Field objects to their associated Oracle column 
    5 # types, as strings. Column-type strings can contain format strings; they'll 
    6 # be interpolated against the values of Field.__dict__ before being output. 
    7 # If a column type is set to None, it won't be included in the output. 
    8 DATA_TYPES = { 
    9     'AutoField':                    'NUMBER(11)', 
    10     'BooleanField':                 'NUMBER(1) CHECK (%(column)s IN (0,1))', 
    11     'CharField':                    'NVARCHAR2(%(max_length)s)', 
    12     'CommaSeparatedIntegerField':   'VARCHAR2(%(max_length)s)', 
    13     'DateField':                    'DATE', 
    14     'DateTimeField':                'TIMESTAMP', 
    15     'DecimalField':                 'NUMBER(%(max_digits)s, %(decimal_places)s)', 
    16     'FileField':                    'NVARCHAR2(100)', 
    17     'FilePathField':                'NVARCHAR2(100)', 
    18     'FloatField':                   'DOUBLE PRECISION', 
    19     'ImageField':                   'NVARCHAR2(100)', 
    20     'IntegerField':                 'NUMBER(11)', 
    21     'IPAddressField':               'VARCHAR2(15)', 
    22     'NullBooleanField':             'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', 
    23     'OneToOneField':                'NUMBER(11)', 
    24     'PhoneNumberField':             'VARCHAR2(20)', 
    25     'PositiveIntegerField':         'NUMBER(11) CHECK (%(column)s >= 0)', 
    26     'PositiveSmallIntegerField':    'NUMBER(11) CHECK (%(column)s >= 0)', 
    27     'SlugField':                    'NVARCHAR2(50)', 
    28     'SmallIntegerField':            'NUMBER(11)', 
    29     'TextField':                    'NCLOB', 
    30     'TimeField':                    'TIMESTAMP', 
    31     'URLField':                     'VARCHAR2(200)', 
    32     'USStateField':                 'CHAR(2)', 
    33 } 
     5class Creation(BaseCreation): 
     6    # This dictionary maps Field objects to their associated Oracle column 
     7    # types, as strings. Column-type strings can contain format strings; they'll 
     8    # be interpolated against the values of Field.__dict__ before being output. 
     9    # If a column type is set to None, it won't be included in the output. 
     10    data_types = { 
     11        'AutoField':                    'NUMBER(11)', 
     12        'BooleanField':                 'NUMBER(1) CHECK (%(column)s IN (0,1))', 
     13        'CharField':                    'NVARCHAR2(%(max_length)s)', 
     14        'CommaSeparatedIntegerField':   'VARCHAR2(%(max_length)s)', 
     15        'DateField':                    'DATE', 
     16        'DateTimeField':                'TIMESTAMP', 
     17        'DecimalField':                 'NUMBER(%(max_digits)s, %(decimal_places)s)', 
     18        'FileField':                    'NVARCHAR2(100)', 
     19        'FilePathField':                'NVARCHAR2(100)', 
     20        'FloatField':                   'DOUBLE PRECISION', 
     21        'ImageField':                   'NVARCHAR2(100)', 
     22        'IntegerField':                 'NUMBER(11)', 
     23        'IPAddressField':               'VARCHAR2(15)', 
     24        'NullBooleanField':             'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', 
     25        'OneToOneField':                'NUMBER(11)', 
     26        'PhoneNumberField':             'VARCHAR2(20)', 
     27        'PositiveIntegerField':         'NUMBER(11) CHECK (%(column)s >= 0)', 
     28        'PositiveSmallIntegerField':    'NUMBER(11) CHECK (%(column)s >= 0)', 
     29        'SlugField':                    'NVARCHAR2(50)', 
     30        'SmallIntegerField':            'NUMBER(11)', 
     31        'TextField':                    'NCLOB', 
     32        'TimeField':                    'TIMESTAMP', 
     33        'URLField':                     'VARCHAR2(200)', 
     34        'USStateField':                 'CHAR(2)', 
     35    } 
    3436 
    35 TEST_DATABASE_PREFIX = 'test_' 
    36 PASSWORD = 'Im_a_lumberjack' 
    37 REMEMBER = {} 
     37    def create_test_db(settings, connection, verbosity=1, autoclobber=False): 
     38        TEST_DATABASE_NAME = _test_database_name(settings) 
     39        TEST_DATABASE_USER = _test_database_user(settings) 
     40        TEST_DATABASE_PASSWD = _test_database_passwd(settings) 
     41        TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 
     42        TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 
    3843 
    39 def create_test_db(settings, connection, verbosity=1, autoclobber=False): 
    40     TEST_DATABASE_NAME = _test_database_name(settings) 
    41     TEST_DATABASE_USER = _test_database_user(settings) 
    42     TEST_DATABASE_PASSWD = _test_database_passwd(settings) 
    43     TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 
    44     TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 
     44        parameters = { 
     45            'dbname': TEST_DATABASE_NAME, 
     46            'user': TEST_DATABASE_USER, 
     47            'password': TEST_DATABASE_PASSWD, 
     48            'tblspace': TEST_DATABASE_TBLSPACE, 
     49            'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 
     50        } 
    4551 
    46     parameters = { 
    47         'dbname': TEST_DATABASE_NAME, 
    48         'user': TEST_DATABASE_USER, 
    49         'password': TEST_DATABASE_PASSWD, 
    50         'tblspace': TEST_DATABASE_TBLSPACE, 
    51         'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 
    52         } 
     52        REMEMBER['user'] = settings.DATABASE_USER 
     53        REMEMBER['passwd'] = settings.DATABASE_PASSWORD 
    5354 
    54     REMEMBER['user'] = settings.DATABASE_USER 
    55     REMEMBER['passwd'] = settings.DATABASE_PASSWORD 
     55        cursor = connection.cursor() 
     56        if _test_database_create(settings): 
     57            if verbosity >= 1: 
     58                print 'Creating test database...' 
     59            try: 
     60                _create_test_db(cursor, parameters, verbosity) 
     61            except Exception, e: 
     62                sys.stderr.write("Got an error creating the test database: %s\n" % e) 
     63                if not autoclobber: 
     64                    confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 
     65                if autoclobber or confirm == 'yes': 
     66                    try: 
     67                        if verbosity >= 1: 
     68                            print "Destroying old test database..." 
     69                        _destroy_test_db(cursor, parameters, verbosity) 
     70                        if verbosity >= 1: 
     71                            print "Creating test database..." 
     72                        _create_test_db(cursor, parameters, verbosity) 
     73                    except Exception, e: 
     74                        sys.stderr.write("Got an error recreating the test database: %s\n" % e) 
     75                        sys.exit(2) 
     76                else: 
     77                    print "Tests cancelled." 
     78                    sys.exit(1) 
    5679 
    57     cursor = connection.cursor() 
    58     if _test_database_create(settings): 
    59         if verbosity >= 1: 
    60             print 'Creating test database...' 
    61         try: 
    62             _create_test_db(cursor, parameters, verbosity) 
    63         except Exception, e: 
    64             sys.stderr.write("Got an error creating the test database: %s\n" % e) 
    65             if not autoclobber: 
    66                 confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 
    67             if autoclobber or confirm == 'yes': 
    68                 try: 
    69                     if verbosity >= 1: 
    70                         print "Destroying old test database..." 
    71                     _destroy_test_db(cursor, parameters, verbosity) 
    72                     if verbosity >= 1: 
    73                         print "Creating test database..." 
    74                     _create_test_db(cursor, parameters, verbosity) 
    75                 except Exception, e: 
    76                     sys.stderr.write("Got an error recreating the test database: %s\n" % e) 
    77                     sys.exit(2) 
    78             else: 
    79                 print "Tests cancelled." 
    80                 sys.exit(1) 
     80        if _test_user_create(settings): 
     81            if verbosity >= 1: 
     82                print "Creating test user..." 
     83            try: 
     84                _create_test_user(cursor, parameters, verbosity) 
     85            except Exception, e: 
     86                sys.stderr.write("Got an error creating the test user: %s\n" % e) 
     87                if not autoclobber: 
     88                    confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 
     89                if autoclobber or confirm == 'yes': 
     90                    try: 
     91                        if verbosity >= 1: 
     92                            print "Destroying old test user..." 
     93                        _destroy_test_user(cursor, parameters, verbosity) 
     94                        if verbosity >= 1: 
     95                            print "Creating test user..." 
     96                        _create_test_user(cursor, parameters, verbosity) 
     97                    except Exception, e: 
     98                        sys.stderr.write("Got an error recreating the test user: %s\n" % e) 
     99                        sys.exit(2) 
     100                else: 
     101                    print "Tests cancelled." 
     102                    sys.exit(1) 
    81103 
    82     if _test_user_create(settings): 
    83         if verbosity >= 1: 
    84             print "Creating test user..." 
    85         try: 
    86             _create_test_user(cursor, parameters, verbosity) 
    87         except Exception, e: 
    88             sys.stderr.write("Got an error creating the test user: %s\n" % e) 
    89             if not autoclobber: 
    90                 confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 
    91             if autoclobber or confirm == 'yes': 
    92                 try: 
    93                     if verbosity >= 1: 
    94                         print "Destroying old test user..." 
    95                     _destroy_test_user(cursor, parameters, verbosity) 
    96                     if verbosity >= 1: 
    97                         print "Creating test user..." 
    98                     _create_test_user(cursor, parameters, verbosity) 
    99                 except Exception, e: 
    100                     sys.stderr.write("Got an error recreating the test user: %s\n" % e) 
    101                     sys.exit(2) 
    102             else: 
    103                 print "Tests cancelled." 
    104                 sys.exit(1) 
     104        connection.close() 
     105        settings.DATABASE_USER = TEST_DATABASE_USER 
     106        settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 
    105107 
    106     connection.close() 
    107     settings.DATABASE_USER = TEST_DATABASE_USER 
    108     settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 
     108        management.call_command('syncdb', verbosity=verbosity, interactive=False) 
    109109 
    110     management.call_command('syncdb', verbosity=verbosity, interactive=False) 
     110        # Get a cursor (even though we don't need one yet). This has 
     111        # the side effect of initializing the test database. 
     112        cursor = connection.cursor() 
    111113 
    112     # Get a cursor (even though we don't need one yet). This has 
    113     # the side effect of initializing the test database. 
    114     cursor = connection.cursor() 
     114    def destroy_test_db(settings, connection, old_database_name, verbosity=1): 
     115        connection.close() 
    115116 
    116 def destroy_test_db(settings, connection, old_database_name, verbosity=1): 
    117     connection.close() 
     117        TEST_DATABASE_NAME = _test_database_name(settings) 
     118        TEST_DATABASE_USER = _test_database_user(settings) 
     119        TEST_DATABASE_PASSWD = _test_database_passwd(settings) 
     120        TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 
     121        TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 
    118122 
    119     TEST_DATABASE_NAME = _test_database_name(settings) 
    120     TEST_DATABASE_USER = _test_database_user(settings) 
    121     TEST_DATABASE_PASSWD = _test_database_passwd(settings) 
    122     TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 
    123     TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 
     123        settings.DATABASE_NAME = old_database_name 
     124        settings.DATABASE_USER = REMEMBER['user'] 
     125        settings.DATABASE_PASSWORD = REMEMBER['passwd'] 
    124126 
    125     settings.DATABASE_NAME = old_database_name 
    126     settings.DATABASE_USER = REMEMBER['user'] 
    127     settings.DATABASE_PASSWORD = REMEMBER['passwd'] 
     127        parameters = { 
     128            'dbname': TEST_DATABASE_NAME, 
     129            'user': TEST_DATABASE_USER, 
     130            'password': TEST_DATABASE_PASSWD, 
     131            'tblspace': TEST_DATABASE_TBLSPACE, 
     132            'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 
     133        } 
    128134 
    129     parameters = { 
    130         'dbname': TEST_DATABASE_NAME, 
    131         'user': TEST_DATABASE_USER, 
    132         'password': TEST_DATABASE_PASSWD, 
    133         'tblspace': TEST_DATABASE_TBLSPACE, 
    134         'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 
    135         } 
     135        REMEMBER['user'] = settings.DATABASE_USER 
     136        REMEMBER['passwd'] = settings.DATABASE_PASSWORD 
    136137 
    137     REMEMBER['user'] = settings.DATABASE_USER 
    138     REMEMBER['passwd'] = settings.DATABASE_PASSWORD 
     138        cursor = connection.cursor() 
     139        time.sleep(1) # To avoid "database is being accessed by other users" errors. 
     140        if _test_user_create(settings): 
     141            if verbosity >= 1: 
     142                print 'Destroying test user...' 
     143            _destroy_test_user(cursor, parameters, verbosity) 
     144        if _test_database_create(settings): 
     145            if verbosity >= 1: 
     146                print 'Destroying test database...' 
     147            _destroy_test_db(cursor, parameters, verbosity) 
     148        connection.close() 
    139149 
    140     cursor = connection.cursor() 
    141     time.sleep(1) # To avoid "database is being accessed by other users" errors. 
    142     if _test_user_create(settings): 
    143         if verbosity >= 1: 
    144             print 'Destroying test user...' 
    145         _destroy_test_user(cursor, parameters, verbosity) 
    146     if _test_database_create(settings): 
    147         if verbosity >= 1: 
    148             print 'Destroying test database...' 
    149         _destroy_test_db(cursor, parameters, verbosity) 
    150     connection.close() 
     150# Seriously? 
     151TEST_DATABASE_PREFIX = 'test_' 
     152PASSWORD = 'Im_a_lumberjack' 
     153REMEMBER = {} 
    151154 
    152155def _create_test_db(cursor, parameters, verbosity): 
    153156    if verbosity >= 2: 
  • db/backends/__init__.py

     
    3838    def make_debug_cursor(self, cursor): 
    3939        from django.db.backends import util 
    4040        return util.CursorDebugWrapper(cursor, self) 
     41         
     42    def _get_creation(self): 
     43        if not hasattr(self, '_creation'): 
     44            from django.conf import settings 
     45            module = __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) 
     46            self._creation = module.Creation() 
     47        return self._creation 
     48    creation = property(fget=_get_creation) 
     49         
     50    def _get_introspection(self): 
     51        if not hasattr(self, '_introspection'): 
     52            from django.conf import settings 
     53            module = __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, ['']) 
     54            self._introspection = module.Introspection() 
     55        return self._introspection 
     56    introspection = property(_get_introspection) 
    4157 
    4258class BaseDatabaseFeatures(object): 
    4359    allows_group_by_ordinal = True 
  • db/backends/postgresql_psycopg2/introspection.py

     
     1from django.db.backends.introspection import BaseIntrospection 
    12from django.db.backends.postgresql_psycopg2.base import DatabaseOperations 
    23 
    34quote_name = DatabaseOperations().quote_name 
     
    23 
    3 def get_table_list(cursor): 
    4     "Returns a list of table names in the current database." 
    5     cursor.execute(""" 
    6         SELECT c.relname 
    7         FROM pg_catalog.pg_class c 
    8         LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
    9         WHERE c.relkind IN ('r', 'v', '') 
    10             AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 
    11             AND pg_catalog.pg_table_is_visible(c.oid)""") 
    12     return [row[0] for row in cursor.fetchall()] 
     4class Introspection(BaseIntrospection): 
     5    data_types_reverse = { 
     6        16: 'BooleanField', 
     7        21: 'SmallIntegerField', 
     8        23: 'IntegerField', 
     9        25: 'TextField', 
     10        701: 'FloatField', 
     11        869: 'IPAddressField', 
     12        1043: 'CharField', 
     13        1082: 'DateField', 
     14        1083: 'TimeField', 
     15        1114: 'DateTimeField', 
     16        1184: 'DateTimeField', 
     17        1266: 'TimeField', 
     18        1700: 'DecimalField', 
     19    } 
     20     
     21    def get_table_list(self, cursor): 
     22        "Returns a list of table names in the current database." 
     23        cursor.execute(""" 
     24            SELECT c.relname 
     25            FROM pg_catalog.pg_class c 
     26            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
     27            WHERE c.relkind IN ('r', 'v', '') 
     28                AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 
     29                AND pg_catalog.pg_table_is_visible(c.oid)""") 
     30        return [row[0] for row in cursor.fetchall()] 
    1331 
    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 
     32    def get_table_description(self, cursor, table_name): 
     33        "Returns a description of the table, with the DB-API cursor.description interface." 
     34        cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name)) 
     35        return cursor.description 
    1836 
    19 def get_relations(cursor, table_name): 
    20     """ 
    21     Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
    22     representing all relationships to the given table. Indexes are 0-based. 
    23     """ 
    24     cursor.execute(""" 
    25         SELECT con.conkey, con.confkey, c2.relname 
    26         FROM pg_constraint con, pg_class c1, pg_class c2 
    27         WHERE c1.oid = con.conrelid 
    28             AND c2.oid = con.confrelid 
    29             AND c1.relname = %s 
    30             AND con.contype = 'f'""", [table_name]) 
    31     relations = {} 
    32     for row in cursor.fetchall(): 
    33         # row[0] and row[1] are single-item lists, so grab the single item. 
    34         relations[row[0][0] - 1] = (row[1][0] - 1, row[2]) 
    35     return relations 
     37    def get_relations(self, cursor, table_name): 
     38        """ 
     39        Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
     40        representing all relationships to the given table. Indexes are 0-based. 
     41        """ 
     42        cursor.execute(""" 
     43            SELECT con.conkey, con.confkey, c2.relname 
     44            FROM pg_constraint con, pg_class c1, pg_class c2 
     45            WHERE c1.oid = con.conrelid 
     46                AND c2.oid = con.confrelid 
     47                AND c1.relname = %s 
     48                AND con.contype = 'f'""", [table_name]) 
     49        relations = {} 
     50        for row in cursor.fetchall(): 
     51            # row[0] and row[1] are single-item lists, so grab the single item. 
     52            relations[row[0][0] - 1] = (row[1][0] - 1, row[2]) 
     53        return relations 
    3654 
    37 def get_indexes(cursor, table_name): 
    38     """ 
    39     Returns a dictionary of fieldname -> infodict for the given table, 
    40     where each infodict is in the format: 
    41         {'primary_key': boolean representing whether it's the primary key, 
    42          'unique': boolean representing whether it's a unique index} 
    43     """ 
    44     # This query retrieves each index on the given table, including the 
    45     # first associated field name 
    46     cursor.execute(""" 
    47         SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary 
    48         FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, 
    49             pg_catalog.pg_index idx, pg_catalog.pg_attribute attr 
    50         WHERE c.oid = idx.indrelid 
    51             AND idx.indexrelid = c2.oid 
    52             AND attr.attrelid = c.oid 
    53             AND attr.attnum = idx.indkey[0] 
    54             AND c.relname = %s""", [table_name]) 
    55     indexes = {} 
    56     for row in cursor.fetchall(): 
    57         # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 
    58         # a string of space-separated integers. This designates the field 
    59         # indexes (1-based) of the fields that have indexes on the table. 
    60         # Here, we skip any indexes across multiple fields. 
    61         if ' ' in row[1]: 
    62             continue 
    63         indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]} 
    64     return indexes 
     55    def get_indexes(self, cursor, table_name): 
     56        """ 
     57        Returns a dictionary of fieldname -> infodict for the given table, 
     58        where each infodict is in the format: 
     59            {'primary_key': boolean representing whether it's the primary key, 
     60             'unique': boolean representing whether it's a unique index} 
     61        """ 
     62        # This query retrieves each index on the given table, including the 
     63        # first associated field name 
     64        cursor.execute(""" 
     65            SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary 
     66            FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, 
     67                pg_catalog.pg_index idx, pg_catalog.pg_attribute attr 
     68            WHERE c.oid = idx.indrelid 
     69                AND idx.indexrelid = c2.oid 
     70                AND attr.attrelid = c.oid 
     71                AND attr.attnum = idx.indkey[0] 
     72                AND c.relname = %s""", [table_name]) 
     73        indexes = {} 
     74        for row in cursor.fetchall(): 
     75            # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 
     76            # a string of space-separated integers. This designates the field 
     77            # indexes (1-based) of the fields that have indexes on the table. 
     78            # Here, we skip any indexes across multiple fields. 
     79            if ' ' in row[1]: 
     80                continue 
     81            indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]} 
     82        return indexes 
    6583 
    66 # Maps type codes to Django Field types. 
    67 DATA_TYPES_REVERSE = { 
    68     16: 'BooleanField', 
    69     21: 'SmallIntegerField', 
    70     23: 'IntegerField', 
    71     25: 'TextField', 
    72     701: 'FloatField', 
    73     869: 'IPAddressField', 
    74     1043: 'CharField', 
    75     1082: 'DateField', 
    76     1083: 'TimeField', 
    77     1114: 'DateTimeField', 
    78     1184: 'DateTimeField', 
    79     1266: 'TimeField', 
    80     1700: 'DecimalField', 
    81 } 
  • db/backends/dummy/introspection.py

     
     1from django.db.backends.introspection import BaseIntrospection 
    12from django.db.backends.dummy.base import complain 
    23 
    3 get_table_list = complain 
    4 get_table_description = complain 
    5 get_relations = complain 
    6 get_indexes = complain 
    7  
    8 DATA_TYPES_REVERSE = {} 
     4class Introspection(BaseIntrospection): 
     5    get_table_list = complain 
     6    get_table_description = complain 
     7    get_relations = complain 
     8    get_indexes = complain 
  • db/backends/dummy/creation.py

     
    1 DATA_TYPES = {} 
     1from django.db.backends.creation import BaseCreation 
     2 
     3class Creation(BaseCreation): 
     4    data_types = {} 
     5 No newline at end of file 
  • db/backends/creation.py

     
    44    database *creation*, such as the column types to use for particular Django 
    55    Fields. 
    66    """ 
    7     pass 
     7    data_types = {}     # 'ModelField': 'database_type', 
     8     
     9    def create_test_db(self, settings, connection, verbosity=1, autoclobber=False): 
     10        raise NotImplementedError() 
     11         
     12    def destroy_test_db(self, settings, connection, old_database_name, verbosity=1): 
     13        raise NotImplementedError() 
     14 No newline at end of file 
  • core/management/commands/inspectdb.py

     
    1313            raise CommandError("Database inspection isn't supported for the currently selected database backend.") 
    1414 
    1515    def handle_inspection(self): 
    16         from django.db import connection, get_introspection_module 
     16        from django.db import connection 
    1717        import keyword 
    1818 
    19         introspection_module = get_introspection_module() 
    20  
    2119        table2model = lambda table_name: table_name.title().replace('_', '') 
    2220 
    2321        cursor = connection.cursor() 
     
    3230        yield '' 
    3331        yield 'from django.db import models' 
    3432        yield '' 
    35         for table_name in introspection_module.get_table_list(cursor): 
     33        for table_name in connection.introspection.get_table_list(cursor): 
    3634            yield 'class %s(models.Model):' % table2model(table_name) 
    3735            try: 
    38                 relations = introspection_module.get_relations(cursor, table_name) 
     36                relations = connection.introspection.get_relations(cursor, table_name) 
    3937            except NotImplementedError: 
    4038                relations = {} 
    4139            try: 
    42                 indexes = introspection_module.get_indexes(cursor, table_name) 
     40                indexes = connection.introspection.get_indexes(cursor, table_name) 
    4341            except NotImplementedError: 
    4442                indexes = {} 
    45             for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)): 
     43            for i, row in enumerate(connection.introspection.get_table_description(cursor, table_name)): 
    4644                att_name = row[0].lower() 
    4745                comment_notes = [] # Holds Field notes, to be displayed in a Python comment. 
    4846                extra_params = {}  # Holds Field parameters such as 'db_column'. 
     
    6563                        extra_params['db_column'] = att_name 
    6664                else: 
    6765                    try: 
    68                         field_type = introspection_module.DATA_TYPES_REVERSE[row[1]] 
     66                        field_type = connection.introspection.data_types_reverse[row[1]] 
    6967                    except KeyError: 
    7068                        field_type = 'TextField' 
    7169                        comment_notes.append('This field type is a guess.') 
    7270 
    73                     # This is a hook for DATA_TYPES_REVERSE to return a tuple of 
     71                    # This is a hook for data_types_reverse to return a tuple of 
    7472                    # (field_type, extra_params_dict). 
    7573                    if type(field_type) is tuple: 
    7674                        field_type, new_params = field_type 
  • core/management/commands/syncdb.py

     
    2121    def handle_noargs(self, **options): 
    2222        from django.db import connection, transaction, models 
    2323        from django.conf import settings 
    24         from django.core.management.sql import table_list, installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal 
     24        from django.core.management.sql import installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal 
    2525 
    2626        verbosity = int(options.get('verbosity', 1)) 
    2727        interactive = options.get('interactive') 
     
    4040 
    4141        # Get a list of all existing database tables, 
    4242        # so we know what needs to be added. 
    43         table_list = table_list() 
     43        table_list = connection.introspection.get_table_list(cursor) 
    4444        if connection.features.uses_case_insensitive_names: 
    4545            table_name_converter = str.upper 
    4646        else: 
  • core/management/sql.py

     
    77except NameError: 
    88    from sets import Set as set   # Python 2.3 fallback 
    99 
    10 def table_list(): 
    11     "Returns a list of all table names that exist in the database." 
    12     from django.db import connection, get_introspection_module 
    13     cursor = connection.cursor() 
    14     return get_introspection_module().get_table_list(cursor) 
    15  
    1610def django_table_list(only_existing=False): 
    1711    """ 
    1812    Returns a list of all table names that have associated Django models and 
     
    2216    that actually exist in the database. 
    2317    """ 
    2418    from django.db import models 
     19    from django.db import connection 
    2520    tables = [] 
    2621    for app in models.get_apps(): 
    2722        for model in models.get_models(app): 
    2823            tables.append(model._meta.db_table) 
    2924            tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 
    3025    if only_existing: 
    31         existing = table_list() 
     26        existing = connection.introspection.get_table_list(connection.cursor()) 
    3227        tables = [t for t in tables if t in existing] 
    3328    return tables 
    3429 
     
    6661 
    6762def sql_create(app, style): 
    6863    "Returns a list of the CREATE TABLE SQL statements for the given app." 
    69     from django.db import models 
     64    from django.db import connection, models 
    7065    from django.conf import settings 
    7166 
    7267    if settings.DATABASE_ENGINE == 'dummy': 
     
    8277    # we can be conservative). 
    8378    app_models = models.get_models(app) 
    8479    final_output = [] 
    85     known_models = set([model for model in installed_models(table_list()) if model not in app_models]) 
     80    tables = connection.introspection.get_table_list(connection.cursor()) 
     81    known_models = set([model for model in installed_models(tables) if model not in app_models]) 
    8682    pending_references = {} 
    8783 
    8884    for model in app_models: 
     
    114110 
    115111def sql_delete(app, style): 
    116112    "Returns a list of the DROP TABLE SQL statements for the given app." 
    117     from django.db import connection, models, get_introspection_module 
     113    from django.db import connection, models 
    118114    from django.db.backends.util import truncate_name 
    119     introspection = get_introspection_module() 
    120115 
    121116    # This should work even if a connection isn't available 
    122117    try: 
     
    126121 
    127122    # Figure out which tables already exist 
    128123    if cursor: 
    129         table_names = introspection.get_table_list(cursor) 
     124        table_names = connection.introspection.get_table_list(cursor) 
    130125    else: 
    131126        table_names = [] 
    132127    if connection.features.uses_case_insensitive_names: 
     
    211206    if only_django: 
    212207        tables = django_table_list() 
    213208    else: 
    214         tables = table_list() 
     209        tables = connection.introspection.get_table_list(connection.cursor()) 
    215210    statements = connection.ops.sql_flush(style, tables, sequence_list()) 
    216211    return statements 
    217212