Ticket #5461: 5461.patch
File 5461.patch, 86.3 KB (added by , 17 years ago) |
---|
-
test/utils.py
1 1 import sys, time 2 2 from django.conf import settings 3 from django.db import connection , get_creation_module3 from django.db import connection 4 4 from django.core import mail 5 5 from django.core.management import call_command 6 6 from django.dispatch import dispatcher … … 95 95 database already exists. Returns the name of the test database created. 96 96 """ 97 97 # 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) 101 100 return 102 101 103 102 if verbosity >= 1: … … 163 162 164 163 def destroy_test_db(old_database_name, verbosity=1): 165 164 # 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) 169 167 return 170 168 171 169 # Unless we're using SQLite, remove the test database to clean up after -
db/models/fields/__init__.py
6 6 except ImportError: 7 7 from django.utils import _decimal as decimal # for Python 2.3 8 8 9 from django.db import get_creation_module10 9 from django.db.models import signals 11 10 from django.dispatch import dispatcher 12 11 from django.conf import settings … … 145 144 # mapped to one of the built-in Django field types. In this case, you 146 145 # can implement db_type() instead of get_internal_type() to specify 147 146 # 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 149 149 internal_type = self.get_internal_type() 150 150 return data_types[internal_type] % self.__dict__ 151 151 -
db/__init__.py
23 23 else: 24 24 raise # If there's some other error, this must be an error in Django itself. 25 25 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, {}, {}, [''])28 26 runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell() 29 27 30 28 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) … … 46 44 def _rollback_on_exception(): 47 45 from django.db import transaction 48 46 transaction.rollback_unless_managed() 49 dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) 47 dispatcher.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 1 from django.db.backends.introspection import BaseIntrospection 3 2 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 = {} 3 class 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 } 1 from django.db.backends.creation import BaseCreation 2 3 class 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.mysql_old.base import DatabaseOperations 2 3 from MySQLdb import ProgrammingError, OperationalError 3 4 from MySQLdb.constants import FIELD_TYPE … … 6 7 quote_name = DatabaseOperations().quote_name 7 8 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 8 9 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()] 10 class 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 } 13 31 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.description32 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()] 18 36 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 25 41 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))]) 56 48 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()) 61 79 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) 63 84 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 76 86 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 } 1 from django.db.backends.creation import BaseCreation 2 3 class 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.postgresql.base import DatabaseOperations 2 3 3 4 quote_name = DatabaseOperations().quote_name … … 2 3 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()] 4 class 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 } 13 20 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()] 18 31 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 39 36 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 68 57 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 } 1 from django.db.backends.creation import BaseCreation 2 3 class 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.sqlite3.base import DatabaseOperations 2 3 3 4 quote_name = DatabaseOperations().quote_name … … 2 3 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 key6 # generation.7 cursor.execute("""8 SELECT name FROM sqlite_master9 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 NotImplementedError20 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, unique34 for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:35 if not unique:36 continue37 cursor.execute('PRAGMA index_info(%s)' % quote_name(index))38 info = cursor.fetchall()39 # Skip indexes across multiple fields40 if len(info) != 1:41 continue42 name = info[0][2] # seqno, cid, name43 indexes[name]['unique'] = True44 return indexes45 46 def _table_info(cursor, name):47 cursor.execute('PRAGMA table_info(%s)' % quote_name(name))48 # cid, name, type, notnull, dflt_value, pk49 return [{'name': field[1],50 'type': field[2],51 'null_ok': not field[3],52 'pk': field[5] # undocumented53 } for field in cursor.fetchall()]54 55 # Maps SQL types to Django Field types. Some of the SQL types have multiple56 # entries here because SQLite allows for anything and doesn't normalize the57 # 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 72 4 # This light wrapper "fakes" a dictionary interface, because some SQLite data 73 5 # types include variables in them -- e.g. "varchar(30)" -- and can't be matched 74 6 # as a simple dictionary lookup. 75 7 class 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 76 22 def __getitem__(self, key): 77 23 key = key.lower() 78 24 try: 79 return BASE_DATA_TYPES_REVERSE[key]25 return self.base_data_types_reverse[key] 80 26 except KeyError: … … 86 32 return ('CharField', {'max_length': int(m.group(1))}) 87 33 raise KeyError 88 34 89 DATA_TYPES_REVERSE = FlexibleFieldLookupDict() 35 class 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
1 1 # SQLite doesn't actually support most of these types, but it "does the right 2 2 # thing" given more verbose field definitions, so leave them as is so that 3 3 # 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 } 4 from django.db.backends.creation import BaseCreation 5 6 class 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.mysql.base import DatabaseOperations 2 3 from MySQLdb import ProgrammingError, OperationalError 3 4 from MySQLdb.constants import FIELD_TYPE … … 6 7 quote_name = DatabaseOperations().quote_name 7 8 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 8 9 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()] 10 class 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 } 13 31 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.description32 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()] 18 36 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 25 41 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))]) 56 48 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()) 61 79 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) 63 84 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 76 86 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 } 1 from django.db.backends.creation import BaseCreation 2 3 class 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.oracle.base import DatabaseOperations 2 3 import re 3 4 import cx_Oracle … … 5 6 quote_name = DatabaseOperations().quote_name 6 7 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 7 8 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(""" 9 class 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(""" 31 36 SELECT ta.column_id - 1, tb.table_name, tb.column_id - 1 32 FROM 33 user_tab_cols ta, user_tab_cols tb37 FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 38 user_tab_cols ta, user_tab_cols tb 34 39 WHERE user_constraints.table_name = %s AND 35 ta.table_name = %s AND36 ta.column_name = ca.column_name AND37 ca.table_name = %s AND38 user_constraints.constraint_name = ca.constraint_name AND39 user_constraints.r_constraint_name = cb.constraint_name AND40 cb.table_name = tb.table_name AND41 cb.column_name = tb.column_name AND42 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 relations48 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 the57 # first associated field name58 # "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 = """ 60 65 WITH primarycols AS ( 61 66 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 62 67 FROM user_cons_columns, user_constraints … … 76 81 WHERE allcols.column_name = primarycols.column_name (+) AND 77 82 allcols.column_name = uniquecols.column_name (+) 78 83 """ 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
1 1 import sys, time 2 2 from django.core import management 3 from django.db.backends.creation import BaseCreation 3 4 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 } 5 class 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 } 34 36 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) 38 43 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 } 45 51 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 53 54 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) 56 79 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) 81 103 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 105 107 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) 109 109 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() 111 113 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() 115 116 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) 118 122 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'] 124 126 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 } 128 134 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 136 137 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() 139 149 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? 151 TEST_DATABASE_PREFIX = 'test_' 152 PASSWORD = 'Im_a_lumberjack' 153 REMEMBER = {} 151 154 152 155 def _create_test_db(cursor, parameters, verbosity): 153 156 if verbosity >= 2: -
db/backends/__init__.py
38 38 def make_debug_cursor(self, cursor): 39 39 from django.db.backends import util 40 40 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) 41 57 42 58 class BaseDatabaseFeatures(object): 43 59 allows_group_by_ordinal = True -
db/backends/postgresql_psycopg2/introspection.py
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.postgresql_psycopg2.base import DatabaseOperations 2 3 3 4 quote_name = DatabaseOperations().quote_name … … 2 3 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()] 4 class 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()] 13 31 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.description32 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 18 36 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.relname26 FROM pg_constraint con, pg_class c1, pg_class c227 WHERE c1.oid = con.conrelid28 AND c2.oid = con.confrelid29 AND c1.relname = %s30 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 relations37 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 36 54 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 the45 # first associated field name46 cursor.execute("""47 SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary48 FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,49 pg_catalog.pg_index idx, pg_catalog.pg_attribute attr50 WHERE c.oid = idx.indrelid51 AND idx.indexrelid = c2.oid52 AND attr.attrelid = c.oid53 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 as58 # a string of space-separated integers. This designates the field59 # 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 continue63 indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}64 return indexes55 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 65 83 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
1 from django.db.backends.introspection import BaseIntrospection 1 2 from django.db.backends.dummy.base import complain 2 3 3 get_table_list = complain 4 get_table_description = complain 5 get_relations = complain 6 get_indexes = complain 7 8 DATA_TYPES_REVERSE = {} 4 class 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 = {} 1 from django.db.backends.creation import BaseCreation 2 3 class Creation(BaseCreation): 4 data_types = {} 5 No newline at end of file -
db/backends/creation.py
4 4 database *creation*, such as the column types to use for particular Django 5 5 Fields. 6 6 """ 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
13 13 raise CommandError("Database inspection isn't supported for the currently selected database backend.") 14 14 15 15 def handle_inspection(self): 16 from django.db import connection , get_introspection_module16 from django.db import connection 17 17 import keyword 18 18 19 introspection_module = get_introspection_module()20 21 19 table2model = lambda table_name: table_name.title().replace('_', '') 22 20 23 21 cursor = connection.cursor() … … 32 30 yield '' 33 31 yield 'from django.db import models' 34 32 yield '' 35 for table_name in introspection_module.get_table_list(cursor):33 for table_name in connection.introspection.get_table_list(cursor): 36 34 yield 'class %s(models.Model):' % table2model(table_name) 37 35 try: 38 relations = introspection_module.get_relations(cursor, table_name)36 relations = connection.introspection.get_relations(cursor, table_name) 39 37 except NotImplementedError: 40 38 relations = {} 41 39 try: 42 indexes = introspection_module.get_indexes(cursor, table_name)40 indexes = connection.introspection.get_indexes(cursor, table_name) 43 41 except NotImplementedError: 44 42 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)): 46 44 att_name = row[0].lower() 47 45 comment_notes = [] # Holds Field notes, to be displayed in a Python comment. 48 46 extra_params = {} # Holds Field parameters such as 'db_column'. … … 65 63 extra_params['db_column'] = att_name 66 64 else: 67 65 try: 68 field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]66 field_type = connection.introspection.data_types_reverse[row[1]] 69 67 except KeyError: 70 68 field_type = 'TextField' 71 69 comment_notes.append('This field type is a guess.') 72 70 73 # This is a hook for DATA_TYPES_REVERSEto return a tuple of71 # This is a hook for data_types_reverse to return a tuple of 74 72 # (field_type, extra_params_dict). 75 73 if type(field_type) is tuple: 76 74 field_type, new_params = field_type -
core/management/commands/syncdb.py
21 21 def handle_noargs(self, **options): 22 22 from django.db import connection, transaction, models 23 23 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_signal24 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 25 25 26 26 verbosity = int(options.get('verbosity', 1)) 27 27 interactive = options.get('interactive') … … 40 40 41 41 # Get a list of all existing database tables, 42 42 # so we know what needs to be added. 43 table_list = table_list()43 table_list = connection.introspection.get_table_list(cursor) 44 44 if connection.features.uses_case_insensitive_names: 45 45 table_name_converter = str.upper 46 46 else: -
core/management/sql.py
7 7 except NameError: 8 8 from sets import Set as set # Python 2.3 fallback 9 9 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_module13 cursor = connection.cursor()14 return get_introspection_module().get_table_list(cursor)15 16 10 def django_table_list(only_existing=False): 17 11 """ 18 12 Returns a list of all table names that have associated Django models and … … 22 16 that actually exist in the database. 23 17 """ 24 18 from django.db import models 19 from django.db import connection 25 20 tables = [] 26 21 for app in models.get_apps(): 27 22 for model in models.get_models(app): 28 23 tables.append(model._meta.db_table) 29 24 tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 30 25 if only_existing: 31 existing = table_list()26 existing = connection.introspection.get_table_list(connection.cursor()) 32 27 tables = [t for t in tables if t in existing] 33 28 return tables 34 29 … … 66 61 67 62 def sql_create(app, style): 68 63 "Returns a list of the CREATE TABLE SQL statements for the given app." 69 from django.db import models64 from django.db import connection, models 70 65 from django.conf import settings 71 66 72 67 if settings.DATABASE_ENGINE == 'dummy': … … 82 77 # we can be conservative). 83 78 app_models = models.get_models(app) 84 79 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]) 86 82 pending_references = {} 87 83 88 84 for model in app_models: … … 114 110 115 111 def sql_delete(app, style): 116 112 "Returns a list of the DROP TABLE SQL statements for the given app." 117 from django.db import connection, models , get_introspection_module113 from django.db import connection, models 118 114 from django.db.backends.util import truncate_name 119 introspection = get_introspection_module()120 115 121 116 # This should work even if a connection isn't available 122 117 try: … … 126 121 127 122 # Figure out which tables already exist 128 123 if cursor: 129 table_names = introspection.get_table_list(cursor)124 table_names = connection.introspection.get_table_list(cursor) 130 125 else: 131 126 table_names = [] 132 127 if connection.features.uses_case_insensitive_names: … … 211 206 if only_django: 212 207 tables = django_table_list() 213 208 else: 214 tables = table_list()209 tables = connection.introspection.get_table_list(connection.cursor()) 215 210 statements = connection.ops.sql_flush(style, tables, sequence_list()) 216 211 return statements 217 212