Ticket #5461: 5461-r8156.diff
File 5461-r8156.diff, 90.3 KB (added by , 16 years ago) |
---|
-
django/test/utils.py
1 1 import sys, time, os 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 … … 101 101 database already exists. Returns the name of the test database created. 102 102 """ 103 103 # If the database backend wants to create the test DB itself, let it 104 creation_module = get_creation_module() 105 if hasattr(creation_module, "create_test_db"): 106 creation_module.create_test_db(settings, connection, verbosity, autoclobber) 104 if hasattr(connection.creation, "create_test_db"): 105 connection.creation.create_test_db(settings, connection, verbosity, autoclobber) 107 106 return 108 107 109 108 if verbosity >= 1: … … 191 190 192 191 def destroy_test_db(old_database_name, verbosity=1): 193 192 # If the database wants to drop the test DB itself, let it 194 creation_module = get_creation_module() 195 if hasattr(creation_module, "destroy_test_db"): 196 creation_module.destroy_test_db(settings, connection, old_database_name, verbosity) 193 if hasattr(connection.creation, "destroy_test_db"): 194 connection.creation.destroy_test_db(settings, connection, old_database_name, verbosity) 197 195 return 198 196 199 197 if verbosity >= 1: -
django/db/models/fields/__init__.py
7 7 except ImportError: 8 8 from django.utils import _decimal as decimal # for Python 2.3 9 9 10 from django.db import connection , get_creation_module10 from django.db import connection 11 11 from django.db.models import signals 12 12 from django.db.models.query_utils import QueryWrapper 13 13 from django.dispatch import dispatcher … … 150 150 # as the TextField Django field type, which means XMLField's 151 151 # get_internal_type() returns 'TextField'. 152 152 # 153 # But the limitation of the get_internal_type() / DATA_TYPESapproach153 # But the limitation of the get_internal_type() / data_types approach 154 154 # is that it cannot handle database column types that aren't already 155 155 # mapped to one of the built-in Django field types. In this case, you 156 156 # can implement db_type() instead of get_internal_type() to specify 157 157 # exactly which wacky database column type you want to use. 158 158 data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_") 159 159 try: 160 return get_creation_module().DATA_TYPES[self.get_internal_type()] % data160 return connection.creation.data_types[self.get_internal_type()] % data 161 161 except KeyError: 162 162 return None 163 163 -
django/db/__init__.py
15 15 # backends that ships with Django, so look there first. 16 16 _import_path = 'django.db.backends.' 17 17 backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) 18 creation = __import__('%s%s.creation' % (_import_path, settings.DATABASE_ENGINE), {}, {}, [''])19 18 except ImportError, e: 19 import traceback 20 traceback.print_exc() 20 21 # If the import failed, we might be looking for a database backend 21 22 # distributed external to Django. So we'll try that next. 22 23 try: 23 24 _import_path = '' 24 25 backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) 25 creation = __import__('%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])26 26 except ImportError, e_user: 27 27 # The database backend wasn't found. Display a helpful error message 28 28 # listing all possible (built-in) database backends. … … 35 35 else: 36 36 raise # If there's some other error, this must be an error in Django itself. 37 37 38 def _import_database_module(import_path='', module_name=''):39 """Lazily import a database module when requested."""40 return __import__('%s%s.%s' % (import_path, settings.DATABASE_ENGINE, module_name), {}, {}, [''])41 42 # We don't want to import the introspect module unless someone asks for it, so43 # lazily load it on demmand.44 get_introspection_module = curry(_import_database_module, _import_path, 'introspection')45 46 def get_creation_module():47 return creation48 49 # We want runshell() to work the same way, but we have to treat it a50 # little differently (since it just runs instead of returning a module like51 # the above) and wrap the lazily-loaded runshell() method.52 runshell = lambda: _import_database_module(_import_path, "client").runshell()53 54 38 # Convenient aliases for backend bits. 55 39 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) 56 40 DatabaseError = backend.DatabaseError -
django/db/backends/postgresql/base.py
7 7 from django.utils.encoding import smart_str, smart_unicode 8 8 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, util 9 9 from django.db.backends.postgresql.operations import DatabaseOperations 10 from django.db.backends.postgresql.client import DatabaseClient 11 from django.db.backends.postgresql.creation import DatabaseCreation 12 from django.db.backends.postgresql.introspection import DatabaseIntrospection 13 10 14 try: 11 15 import psycopg as Database 12 16 except ImportError, e: … … 65 69 class DatabaseWrapper(BaseDatabaseWrapper): 66 70 features = DatabaseFeatures() 67 71 ops = DatabaseOperations() 72 client = DatabaseClient() 73 creation = DatabaseCreation() 74 introspection = DatabaseIntrospection(ops) 75 68 76 operators = { 69 77 'exact': '= %s', 70 78 'iexact': 'ILIKE %s', -
django/db/backends/postgresql/client.py
1 from django.db.backends import BaseDatabaseClient 1 2 from django.conf import settings 2 3 import os 3 4 4 def runshell(): 5 args = ['psql'] 6 if settings.DATABASE_USER: 7 args += ["-U", settings.DATABASE_USER] 8 if settings.DATABASE_PASSWORD: 9 args += ["-W"] 10 if settings.DATABASE_HOST: 11 args.extend(["-h", settings.DATABASE_HOST]) 12 if settings.DATABASE_PORT: 13 args.extend(["-p", str(settings.DATABASE_PORT)]) 14 args += [settings.DATABASE_NAME] 15 os.execvp('psql', args) 5 class DatabaseClient(BaseDatabaseClient): 6 def runshell(self): 7 args = ['psql'] 8 if settings.DATABASE_USER: 9 args += ["-U", settings.DATABASE_USER] 10 if settings.DATABASE_PASSWORD: 11 args += ["-W"] 12 if settings.DATABASE_HOST: 13 args.extend(["-h", settings.DATABASE_HOST]) 14 if settings.DATABASE_PORT: 15 args.extend(["-p", str(settings.DATABASE_PORT)]) 16 args += [settings.DATABASE_NAME] 17 os.execvp('psql', args) -
django/db/backends/postgresql/introspection.py
1 from django.db.backends .postgresql.base import DatabaseOperations1 from django.db.backends import BaseDatabaseIntrospection 2 2 3 quote_name = DatabaseOperations().quote_name 3 class DatabaseIntrospection(BaseDatabaseIntrospection): 4 # Maps type codes to Django Field types. 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 __init__(self, ops): 22 self.ops = ops 23 24 def get_table_list(self, cursor): 25 "Returns a list of table names in the current database." 26 cursor.execute(""" 27 SELECT c.relname 28 FROM pg_catalog.pg_class c 29 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 30 WHERE c.relkind IN ('r', 'v', '') 31 AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 32 AND pg_catalog.pg_table_is_visible(c.oid)""") 33 return [row[0] for row in cursor.fetchall()] 4 34 5 def get_table_list(cursor): 6 "Returns a list of table names in the current database." 7 cursor.execute(""" 8 SELECT c.relname 9 FROM pg_catalog.pg_class c 10 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 11 WHERE c.relkind IN ('r', 'v', '') 12 AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 13 AND pg_catalog.pg_table_is_visible(c.oid)""") 14 return [row[0] for row in cursor.fetchall()] 35 def get_table_description(self, cursor, table_name): 36 "Returns a description of the table, with the DB-API cursor.description interface." 37 cursor.execute("SELECT * FROM %s LIMIT 1" % self.ops.quote_name(table_name)) 38 return cursor.description 15 39 16 def get_table_description(cursor, table_name): 17 "Returns a description of the table, with the DB-API cursor.description interface." 18 cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name)) 19 return cursor.description 40 def get_relations(self, cursor, table_name): 41 """ 42 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 43 representing all relationships to the given table. Indexes are 0-based. 44 """ 45 cursor.execute(""" 46 SELECT con.conkey, con.confkey, c2.relname 47 FROM pg_constraint con, pg_class c1, pg_class c2 48 WHERE c1.oid = con.conrelid 49 AND c2.oid = con.confrelid 50 AND c1.relname = %s 51 AND con.contype = 'f'""", [table_name]) 52 relations = {} 53 for row in cursor.fetchall(): 54 try: 55 # row[0] and row[1] are like "{2}", so strip the curly braces. 56 relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2]) 57 except ValueError: 58 continue 59 return relations 20 60 21 def get_relations(cursor, table_name): 22 """ 23 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 24 representing all relationships to the given table. Indexes are 0-based. 25 """ 26 cursor.execute(""" 27 SELECT con.conkey, con.confkey, c2.relname 28 FROM pg_constraint con, pg_class c1, pg_class c2 29 WHERE c1.oid = con.conrelid 30 AND c2.oid = con.confrelid 31 AND c1.relname = %s 32 AND con.contype = 'f'""", [table_name]) 33 relations = {} 34 for row in cursor.fetchall(): 35 try: 36 # row[0] and row[1] are like "{2}", so strip the curly braces. 37 relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2]) 38 except ValueError: 39 continue 40 return relations 61 def get_indexes(self, cursor, table_name): 62 """ 63 Returns a dictionary of fieldname -> infodict for the given table, 64 where each infodict is in the format: 65 {'primary_key': boolean representing whether it's the primary key, 66 'unique': boolean representing whether it's a unique index} 67 """ 68 # This query retrieves each index on the given table, including the 69 # first associated field name 70 cursor.execute(""" 71 SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary 72 FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, 73 pg_catalog.pg_index idx, pg_catalog.pg_attribute attr 74 WHERE c.oid = idx.indrelid 75 AND idx.indexrelid = c2.oid 76 AND attr.attrelid = c.oid 77 AND attr.attnum = idx.indkey[0] 78 AND c.relname = %s""", [table_name]) 79 indexes = {} 80 for row in cursor.fetchall(): 81 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 82 # a string of space-separated integers. This designates the field 83 # indexes (1-based) of the fields that have indexes on the table. 84 # Here, we skip any indexes across multiple fields. 85 if ' ' in row[1]: 86 continue 87 indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]} 88 return indexes 41 89 42 def get_indexes(cursor, table_name):43 """44 Returns a dictionary of fieldname -> infodict for the given table,45 where each infodict is in the format:46 {'primary_key': boolean representing whether it's the primary key,47 'unique': boolean representing whether it's a unique index}48 """49 # This query retrieves each index on the given table, including the50 # first associated field name51 cursor.execute("""52 SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary53 FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,54 pg_catalog.pg_index idx, pg_catalog.pg_attribute attr55 WHERE c.oid = idx.indrelid56 AND idx.indexrelid = c2.oid57 AND attr.attrelid = c.oid58 AND attr.attnum = idx.indkey[0]59 AND c.relname = %s""", [table_name])60 indexes = {}61 for row in cursor.fetchall():62 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as63 # a string of space-separated integers. This designates the field64 # indexes (1-based) of the fields that have indexes on the table.65 # Here, we skip any indexes across multiple fields.66 if ' ' in row[1]:67 continue68 indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}69 return indexes70 71 # Maps type codes to Django Field types.72 DATA_TYPES_REVERSE = {73 16: 'BooleanField',74 21: 'SmallIntegerField',75 23: 'IntegerField',76 25: 'TextField',77 701: 'FloatField',78 869: 'IPAddressField',79 1043: 'CharField',80 1082: 'DateField',81 1083: 'TimeField',82 1114: 'DateTimeField',83 1184: 'DateTimeField',84 1266: 'TimeField',85 1700: 'DecimalField',86 } -
django/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(%(max_length)s)', 14 'FilePathField': 'varchar(%(max_length)s)', 15 'FloatField': 'double precision', 16 'IntegerField': 'integer', 17 'IPAddressField': 'inet', 18 'NullBooleanField': 'boolean', 19 'OneToOneField': 'integer', 20 'PhoneNumberField': 'varchar(20)', 21 'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', 22 'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)', 23 'SlugField': 'varchar(%(max_length)s)', 24 'SmallIntegerField': 'smallint', 25 'TextField': 'text', 26 'TimeField': 'time', 27 'USStateField': 'varchar(2)', 28 } 1 from django.db.backends import BaseDatabaseCreation 2 3 class DatabaseCreation(BaseDatabaseCreation): 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(%(max_length)s)', 17 'FilePathField': 'varchar(%(max_length)s)', 18 'FloatField': 'double precision', 19 'IntegerField': 'integer', 20 'IPAddressField': 'inet', 21 'NullBooleanField': 'boolean', 22 'OneToOneField': 'integer', 23 'PhoneNumberField': 'varchar(20)', 24 'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', 25 'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)', 26 'SlugField': 'varchar(%(max_length)s)', 27 'SmallIntegerField': 'smallint', 28 'TextField': 'text', 29 'TimeField': 'time', 30 'USStateField': 'varchar(2)', 31 } -
django/db/backends/sqlite3/base.py
7 7 """ 8 8 9 9 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 10 from django.db.backends.sqlite3.client import DatabaseClient 11 from django.db.backends.sqlite3.creation import DatabaseCreation 12 from django.db.backends.sqlite3.introspection import DatabaseIntrospection 13 10 14 try: 11 15 try: 12 16 from sqlite3 import dbapi2 as Database … … 93 97 class DatabaseWrapper(BaseDatabaseWrapper): 94 98 features = DatabaseFeatures() 95 99 ops = DatabaseOperations() 100 client = DatabaseClient() 101 creation = DatabaseCreation() 102 introspection = DatabaseIntrospection(ops) 96 103 97 104 # SQLite requires LIKE statements to include an ESCAPE clause if the value 98 105 # being escaped has a percent or underscore in it. -
django/db/backends/sqlite3/client.py
1 from django.db.backends import BaseDatabaseClient 1 2 from django.conf import settings 2 3 import os 3 4 4 def runshell(): 5 args = ['', settings.DATABASE_NAME] 6 os.execvp('sqlite3', args) 5 class DatabaseClient(BaseDatabaseClient): 6 def runshell(self): 7 args = ['', settings.DATABASE_NAME] 8 os.execvp('sqlite3', args) -
django/db/backends/sqlite3/introspection.py
1 from django.db.backends .sqlite3.base import DatabaseOperations1 from django.db.backends import BaseDatabaseIntrospection 2 2 3 quote_name = DatabaseOperations().quote_name4 5 def get_table_list(cursor):6 "Returns a list of table names in the current database."7 # Skip the sqlite_sequence system table used for autoincrement key8 # generation.9 cursor.execute("""10 SELECT name FROM sqlite_master11 WHERE type='table' AND NOT name='sqlite_sequence'12 ORDER BY name""")13 return [row[0] for row in cursor.fetchall()]14 15 def get_table_description(cursor, table_name):16 "Returns a description of the table, with the DB-API cursor.description interface."17 return [(info['name'], info['type'], None, None, None, None,18 info['null_ok']) for info in _table_info(cursor, table_name)]19 20 def get_relations(cursor, table_name):21 raise NotImplementedError22 23 def get_indexes(cursor, table_name):24 """25 Returns a dictionary of fieldname -> infodict for the given table,26 where each infodict is in the format:27 {'primary_key': boolean representing whether it's the primary key,28 'unique': boolean representing whether it's a unique index}29 """30 indexes = {}31 for info in _table_info(cursor, table_name):32 indexes[info['name']] = {'primary_key': info['pk'] != 0,33 'unique': False}34 cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name))35 # seq, name, unique36 for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:37 if not unique:38 continue39 cursor.execute('PRAGMA index_info(%s)' % quote_name(index))40 info = cursor.fetchall()41 # Skip indexes across multiple fields42 if len(info) != 1:43 continue44 name = info[0][2] # seqno, cid, name45 indexes[name]['unique'] = True46 return indexes47 48 def _table_info(cursor, name):49 cursor.execute('PRAGMA table_info(%s)' % quote_name(name))50 # cid, name, type, notnull, dflt_value, pk51 return [{'name': field[1],52 'type': field[2],53 'null_ok': not field[3],54 'pk': field[5] # undocumented55 } for field in cursor.fetchall()]56 57 # Maps SQL types to Django Field types. Some of the SQL types have multiple58 # entries here because SQLite allows for anything and doesn't normalize the59 # field type; it uses whatever was given.60 BASE_DATA_TYPES_REVERSE = {61 'bool': 'BooleanField',62 'boolean': 'BooleanField',63 'smallint': 'SmallIntegerField',64 'smallinteger': 'SmallIntegerField',65 'int': 'IntegerField',66 'integer': 'IntegerField',67 'text': 'TextField',68 'char': 'CharField',69 'date': 'DateField',70 'datetime': 'DateTimeField',71 'time': 'TimeField',72 }73 74 3 # This light wrapper "fakes" a dictionary interface, because some SQLite data 75 4 # types include variables in them -- e.g. "varchar(30)" -- and can't be matched 76 5 # as a simple dictionary lookup. 77 6 class FlexibleFieldLookupDict: 7 # Maps SQL types to Django Field types. Some of the SQL types have multiple 8 # entries here because SQLite allows for anything and doesn't normalize the 9 # field type; it uses whatever was given. 10 base_data_types_reverse = { 11 'bool': 'BooleanField', 12 'boolean': 'BooleanField', 13 'smallint': 'SmallIntegerField', 14 'smallinteger': 'SmallIntegerField', 15 'int': 'IntegerField', 16 'integer': 'IntegerField', 17 'text': 'TextField', 18 'char': 'CharField', 19 'date': 'DateField', 20 'datetime': 'DateTimeField', 21 'time': 'TimeField', 22 } 23 78 24 def __getitem__(self, key): 79 25 key = key.lower() 80 26 try: 81 return BASE_DATA_TYPES_REVERSE[key]27 return self.base_data_types_reverse[key] 82 28 except KeyError: 83 29 import re 84 30 m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key) … … 86 32 return ('CharField', {'max_length': int(m.group(1))}) 87 33 raise KeyError 88 34 89 DATA_TYPES_REVERSE = FlexibleFieldLookupDict() 35 class DatabaseIntrospection(BaseDatabaseIntrospection): 36 data_types_reverse = FlexibleFieldLookupDict() 37 38 def __init__(self, ops): 39 self.ops = ops 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)' % self.ops.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)' % self.ops.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)' % self.ops.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()] 92 -
django/db/backends/sqlite3/creation.py
1 # SQLite doesn't actually support most of these types, but it "does the right 2 # thing" given more verbose field definitions, so leave them as is so that 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(%(max_length)s)', 13 'FilePathField': 'varchar(%(max_length)s)', 14 'FloatField': 'real', 15 'IntegerField': 'integer', 16 'IPAddressField': 'char(15)', 17 'NullBooleanField': 'bool', 18 'OneToOneField': 'integer', 19 'PhoneNumberField': 'varchar(20)', 20 'PositiveIntegerField': 'integer unsigned', 21 'PositiveSmallIntegerField': 'smallint unsigned', 22 'SlugField': 'varchar(%(max_length)s)', 23 'SmallIntegerField': 'smallint', 24 'TextField': 'text', 25 'TimeField': 'time', 26 'USStateField': 'varchar(2)', 27 } 1 from django.db.backends import BaseDatabaseCreation 2 3 class DatabaseCreation(BaseDatabaseCreation): 4 # SQLite doesn't actually support most of these types, but it "does the right 5 # thing" given more verbose field definitions, so leave them as is so that 6 # schema inspection is more useful. 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(%(max_length)s)', 16 'FilePathField': 'varchar(%(max_length)s)', 17 'FloatField': 'real', 18 'IntegerField': 'integer', 19 'IPAddressField': 'char(15)', 20 'NullBooleanField': 'bool', 21 'OneToOneField': 'integer', 22 'PhoneNumberField': 'varchar(20)', 23 'PositiveIntegerField': 'integer unsigned', 24 'PositiveSmallIntegerField': 'smallint unsigned', 25 'SlugField': 'varchar(%(max_length)s)', 26 'SmallIntegerField': 'smallint', 27 'TextField': 'text', 28 'TimeField': 'time', 29 'USStateField': 'varchar(2)', 30 } -
django/db/backends/mysql/base.py
5 5 """ 6 6 7 7 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 8 from django.db.backends.mysql.client import DatabaseClient 9 from django.db.backends.mysql.creation import DatabaseCreation 10 from django.db.backends.mysql.introspection import DatabaseIntrospection 11 8 12 try: 9 13 import MySQLdb as Database 10 14 except ImportError, e: … … 144 148 class DatabaseWrapper(BaseDatabaseWrapper): 145 149 features = DatabaseFeatures() 146 150 ops = DatabaseOperations() 151 client = DatabaseClient() 152 creation = DatabaseCreation() 153 introspection = DatabaseIntrospection(ops) 154 147 155 operators = { 148 156 'exact': '= BINARY %s', 149 157 'iexact': 'LIKE %s', -
django/db/backends/mysql/client.py
1 from django.db.backends import BaseDatabaseClient 1 2 from django.conf import settings 2 3 import os 3 4 4 def runshell(): 5 args = [''] 6 db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME) 7 user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER) 8 passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD) 9 host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST) 10 port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT) 11 defaults_file = settings.DATABASE_OPTIONS.get('read_default_file') 12 # Seems to be no good way to set sql_mode with CLI 5 class DatabaseClient(BaseDatabaseClient): 6 def runshell(self): 7 args = [''] 8 db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME) 9 user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER) 10 passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD) 11 host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST) 12 port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT) 13 defaults_file = settings.DATABASE_OPTIONS.get('read_default_file') 14 # Seems to be no good way to set sql_mode with CLI 13 15 14 if defaults_file:15 args += ["--defaults-file=%s" % defaults_file]16 if user:17 args += ["--user=%s" % user]18 if passwd:19 args += ["--password=%s" % passwd]20 if host:21 args += ["--host=%s" % host]22 if port:23 args += ["--port=%s" % port]24 if db:25 args += [db]16 if defaults_file: 17 args += ["--defaults-file=%s" % defaults_file] 18 if user: 19 args += ["--user=%s" % user] 20 if passwd: 21 args += ["--password=%s" % passwd] 22 if host: 23 args += ["--host=%s" % host] 24 if port: 25 args += ["--port=%s" % port] 26 if db: 27 args += [db] 26 28 27 os.execvp('mysql', args)29 os.execvp('mysql', args) -
django/db/backends/mysql/introspection.py
1 from django.db.backends .mysql.base import DatabaseOperations1 from django.db.backends import BaseDatabaseIntrospection 2 2 from MySQLdb import ProgrammingError, OperationalError 3 3 from MySQLdb.constants import FIELD_TYPE 4 4 import re 5 5 6 quote_name = DatabaseOperations().quote_name7 6 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 8 7 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()] 8 class DatabaseIntrospection(BaseDatabaseIntrospection): 9 data_types_reverse = { 10 FIELD_TYPE.BLOB: 'TextField', 11 FIELD_TYPE.CHAR: 'CharField', 12 FIELD_TYPE.DECIMAL: 'DecimalField', 13 FIELD_TYPE.DATE: 'DateField', 14 FIELD_TYPE.DATETIME: 'DateTimeField', 15 FIELD_TYPE.DOUBLE: 'FloatField', 16 FIELD_TYPE.FLOAT: 'FloatField', 17 FIELD_TYPE.INT24: 'IntegerField', 18 FIELD_TYPE.LONG: 'IntegerField', 19 FIELD_TYPE.LONGLONG: 'IntegerField', 20 FIELD_TYPE.SHORT: 'IntegerField', 21 FIELD_TYPE.STRING: 'CharField', 22 FIELD_TYPE.TIMESTAMP: 'DateTimeField', 23 FIELD_TYPE.TINY: 'IntegerField', 24 FIELD_TYPE.TINY_BLOB: 'TextField', 25 FIELD_TYPE.MEDIUM_BLOB: 'TextField', 26 FIELD_TYPE.LONG_BLOB: 'TextField', 27 FIELD_TYPE.VAR_STRING: 'CharField', 28 } 13 29 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 30 def __init__(self, ops): 31 self.ops = ops 32 33 def get_table_list(self, cursor): 34 "Returns a list of table names in the current database." 35 cursor.execute("SHOW TABLES") 36 return [row[0] for row in cursor.fetchall()] 18 37 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))]) 38 def get_table_description(self, cursor, table_name): 39 "Returns a description of the table, with the DB-API cursor.description interface." 40 cursor.execute("SELECT * FROM %s LIMIT 1" % self.ops.quote_name(table_name)) 41 return cursor.description 25 42 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()) 43 def _name_to_index(self, cursor, table_name): 44 """ 45 Returns a dictionary of {field_name: field_index} for the given table. 46 Indexes are 0-based. 47 """ 48 return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))]) 56 49 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) 50 def get_relations(self, cursor, table_name): 51 """ 52 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 53 representing all relationships to the given table. Indexes are 0-based. 54 """ 55 my_field_dict = self._name_to_index(cursor, table_name) 56 constraints = [] 57 relations = {} 58 try: 59 # This should work for MySQL 5.0. 60 cursor.execute(""" 61 SELECT column_name, referenced_table_name, referenced_column_name 62 FROM information_schema.key_column_usage 63 WHERE table_name = %s 64 AND table_schema = DATABASE() 65 AND referenced_table_name IS NOT NULL 66 AND referenced_column_name IS NOT NULL""", [table_name]) 67 constraints.extend(cursor.fetchall()) 68 except (ProgrammingError, OperationalError): 69 # Fall back to "SHOW CREATE TABLE", for previous MySQL versions. 70 # Go through all constraints and save the equal matches. 71 cursor.execute("SHOW CREATE TABLE %s" % self.ops.quote_name(table_name)) 72 for row in cursor.fetchall(): 73 pos = 0 74 while True: 75 match = foreign_key_re.search(row[1], pos) 76 if match == None: 77 break 78 pos = match.end() 79 constraints.append(match.groups()) 61 80 62 return relations 81 for my_fieldname, other_table, other_field in constraints: 82 other_field_index = self._name_to_index(cursor, other_table)[other_field] 83 my_field_index = my_field_dict[my_fieldname] 84 relations[my_field_index] = (other_field_index, other_table) 63 85 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 86 return relations 76 87 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 } 88 def get_indexes(self, cursor, table_name): 89 """ 90 Returns a dictionary of fieldname -> infodict for the given table, 91 where each infodict is in the format: 92 {'primary_key': boolean representing whether it's the primary key, 93 'unique': boolean representing whether it's a unique index} 94 """ 95 cursor.execute("SHOW INDEX FROM %s" % self.ops.quote_name(table_name)) 96 indexes = {} 97 for row in cursor.fetchall(): 98 indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])} 99 return indexes 100 -
django/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(%(max_length)s)', 14 'FilePathField': 'varchar(%(max_length)s)', 15 'FloatField': 'double precision', 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': 'longtext', 26 'TimeField': 'time', 27 'USStateField': 'varchar(2)', 28 } 1 from django.db.backends import BaseDatabaseCreation 2 3 class DatabaseCreation(BaseDatabaseCreation): 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(%(max_length)s)', 17 'FilePathField': 'varchar(%(max_length)s)', 18 'FloatField': 'double precision', 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': 'longtext', 29 'TimeField': 'time', 30 'USStateField': 'varchar(2)', 31 } -
django/db/backends/oracle/base.py
10 10 11 11 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 12 12 from django.db.backends.oracle import query 13 from django.db.backends.oracle.client import DatabaseClient 14 from django.db.backends.oracle.creation import DatabaseCreation 15 from django.db.backends.oracle.introspection import DatabaseIntrospection 13 16 from django.utils.encoding import smart_str, force_unicode 14 17 15 18 # Oracle takes client-side character set encoding from the environment. … … 198 201 class DatabaseWrapper(BaseDatabaseWrapper): 199 202 features = DatabaseFeatures() 200 203 ops = DatabaseOperations() 204 client = DatabaseClient() 205 creation = DatabaseCreation() 206 introspection = DatabaseIntrospection(ops) 207 201 208 operators = { 202 209 'exact': '= %s', 203 210 'iexact': '= UPPER(%s)', -
django/db/backends/oracle/client.py
1 from django.db.backends import BaseDatabaseClient 1 2 from django.conf import settings 2 3 import os 3 4 4 def runshell(): 5 dsn = settings.DATABASE_USER 6 if settings.DATABASE_PASSWORD: 7 dsn += "/%s" % settings.DATABASE_PASSWORD 8 if settings.DATABASE_NAME: 9 dsn += "@%s" % settings.DATABASE_NAME 10 args = ["sqlplus", "-L", dsn] 11 os.execvp("sqlplus", args) 5 class DatabaseClient(BaseDatabaseClient): 6 def runshell(self): 7 dsn = settings.DATABASE_USER 8 if settings.DATABASE_PASSWORD: 9 dsn += "/%s" % settings.DATABASE_PASSWORD 10 if settings.DATABASE_NAME: 11 dsn += "@%s" % settings.DATABASE_NAME 12 args = ["sqlplus", "-L", dsn] 13 os.execvp("sqlplus", args) -
django/db/backends/oracle/introspection.py
1 from django.db.backends.oracle.base import DatabaseOperations 1 from django.db.backends import BaseDatabaseIntrospection 2 import cx_Oracle 2 3 import re 3 import cx_Oracle4 4 5 quote_name = DatabaseOperations().quote_name6 5 foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)") 7 6 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()] 7 class DatabaseIntrospection(BaseDatabaseIntrospection): 8 # Maps type objects to Django Field types. 9 data_types_reverse = { 10 cx_Oracle.CLOB: 'TextField', 11 cx_Oracle.DATETIME: 'DateTimeField', 12 cx_Oracle.FIXED_CHAR: 'CharField', 13 cx_Oracle.NCLOB: 'TextField', 14 cx_Oracle.NUMBER: 'DecimalField', 15 cx_Oracle.STRING: 'CharField', 16 cx_Oracle.TIMESTAMP: 'DateTimeField', 17 } 12 18 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 19 def __init__(self, ops): 20 self.ops = ops 21 22 def get_table_list(self, cursor): 23 "Returns a list of table names in the current database." 24 cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") 25 return [row[0].upper() for row in cursor.fetchall()] 17 26 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))]) 27 def get_table_description(self, cursor, table_name): 28 "Returns a description of the table, with the DB-API cursor.description interface." 29 cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % self.ops.quote_name(table_name)) 30 return cursor.description 24 31 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(""" 31 SELECT 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 34 WHERE 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]) 32 def _name_to_index(self, cursor, table_name): 33 """ 34 Returns a dictionary of {field_name: field_index} for the given table. 35 Indexes are 0-based. 36 """ 37 return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))]) 43 38 44 relations = {} 45 for row in cursor.fetchall(): 46 relations[row[0]] = (row[2], row[1]) 47 return relations 39 def get_relations(self, cursor, table_name): 40 """ 41 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 42 representing all relationships to the given table. Indexes are 0-based. 43 """ 44 cursor.execute(""" 45 SELECT ta.column_id - 1, tb.table_name, tb.column_id - 1 46 FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 47 user_tab_cols ta, user_tab_cols tb 48 WHERE user_constraints.table_name = %s AND 49 ta.table_name = %s AND 50 ta.column_name = ca.column_name AND 51 ca.table_name = %s AND 52 user_constraints.constraint_name = ca.constraint_name AND 53 user_constraints.r_constraint_name = cb.constraint_name AND 54 cb.table_name = tb.table_name AND 55 cb.column_name = tb.column_name AND 56 ca.position = cb.position""", [table_name, table_name, table_name]) 48 57 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 = """ 60 WITH primarycols AS ( 61 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 62 FROM user_cons_columns, user_constraints 63 WHERE user_cons_columns.constraint_name = user_constraints.constraint_name AND 64 user_constraints.constraint_type = 'P' AND 65 user_cons_columns.table_name = %s), 66 uniquecols AS ( 67 SELECT user_ind_columns.table_name, user_ind_columns.column_name, 1 AS UNIQUECOL 68 FROM user_indexes, user_ind_columns 69 WHERE uniqueness = 'UNIQUE' AND 70 user_indexes.index_name = user_ind_columns.index_name AND 71 user_ind_columns.table_name = %s) 72 SELECT allcols.column_name, primarycols.primarycol, uniquecols.UNIQUECOL 73 FROM (SELECT column_name FROM primarycols UNION SELECT column_name FROM 74 uniquecols) allcols, 75 primarycols, uniquecols 76 WHERE allcols.column_name = primarycols.column_name (+) AND 77 allcols.column_name = uniquecols.column_name (+) 78 """ 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 58 relations = {} 59 for row in cursor.fetchall(): 60 relations[row[0]] = (row[2], row[1]) 61 return relations 88 62 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 } 63 def get_indexes(self, cursor, table_name): 64 """ 65 Returns a dictionary of fieldname -> infodict for the given table, 66 where each infodict is in the format: 67 {'primary_key': boolean representing whether it's the primary key, 68 'unique': boolean representing whether it's a unique index} 69 """ 70 # This query retrieves each index on the given table, including the 71 # first associated field name 72 # "We were in the nick of time; you were in great peril!" 73 sql = """ 74 WITH primarycols AS ( 75 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 76 FROM user_cons_columns, user_constraints 77 WHERE user_cons_columns.constraint_name = user_constraints.constraint_name AND 78 user_constraints.constraint_type = 'P' AND 79 user_cons_columns.table_name = %s), 80 uniquecols AS ( 81 SELECT user_ind_columns.table_name, user_ind_columns.column_name, 1 AS UNIQUECOL 82 FROM user_indexes, user_ind_columns 83 WHERE uniqueness = 'UNIQUE' AND 84 user_indexes.index_name = user_ind_columns.index_name AND 85 user_ind_columns.table_name = %s) 86 SELECT allcols.column_name, primarycols.primarycol, uniquecols.UNIQUECOL 87 FROM (SELECT column_name FROM primarycols UNION SELECT column_name FROM 88 uniquecols) allcols, 89 primarycols, uniquecols 90 WHERE allcols.column_name = primarycols.column_name (+) AND 91 allcols.column_name = uniquecols.column_name (+) 92 """ 93 cursor.execute(sql, [table_name, table_name]) 94 indexes = {} 95 for row in cursor.fetchall(): 96 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 97 # a string of space-separated integers. This designates the field 98 # indexes (1-based) of the fields that have indexes on the table. 99 # Here, we skip any indexes across multiple fields. 100 indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]} 101 return indexes 102 -
django/db/backends/oracle/creation.py
1 1 import sys, time 2 2 from django.core import management 3 from django.db.backends import BaseDatabaseCreation 3 4 4 # This dictionary maps Field objects to their associated Oracle column5 # types, as strings. Column-type strings can contain format strings; they'll6 # 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 #9 # Any format strings starting with "qn_" are quoted before being used in the10 # output (the "qn_" prefix is stripped before the lookup is performed.11 12 DATA_TYPES = {13 'AutoField': 'NUMBER(11)',14 'BooleanField': 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))',15 'CharField': 'NVARCHAR2(%(max_length)s)',16 'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',17 'DateField': 'DATE',18 'DateTimeField': 'TIMESTAMP',19 'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)',20 'FileField': 'NVARCHAR2(%(max_length)s)',21 'FilePathField': 'NVARCHAR2(%(max_length)s)',22 'FloatField': 'DOUBLE PRECISION',23 'IntegerField': 'NUMBER(11)',24 'IPAddressField': 'VARCHAR2(15)',25 'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))',26 'OneToOneField': 'NUMBER(11)',27 'PhoneNumberField': 'VARCHAR2(20)',28 'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',29 'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',30 'SlugField': 'NVARCHAR2(50)',31 'SmallIntegerField': 'NUMBER(11)',32 'TextField': 'NCLOB',33 'TimeField': 'TIMESTAMP',34 'URLField': 'VARCHAR2(%(max_length)s)',35 'USStateField': 'CHAR(2)',36 }37 38 5 TEST_DATABASE_PREFIX = 'test_' 39 6 PASSWORD = 'Im_a_lumberjack' 40 REMEMBER = {}41 7 42 def create_test_db(settings, connection, verbosity=1, autoclobber=False): 43 TEST_DATABASE_NAME = _test_database_name(settings) 44 TEST_DATABASE_USER = _test_database_user(settings) 45 TEST_DATABASE_PASSWD = _test_database_passwd(settings) 46 TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 47 TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 8 class DatabaseCreation(BaseDatabaseCreation): 9 # This dictionary maps Field objects to their associated Oracle column 10 # types, as strings. Column-type strings can contain format strings; they'll 11 # be interpolated against the values of Field.__dict__ before being output. 12 # If a column type is set to None, it won't be included in the output. 13 # 14 # Any format strings starting with "qn_" are quoted before being used in the 15 # output (the "qn_" prefix is stripped before the lookup is performed. 48 16 49 parameters = { 50 'dbname': TEST_DATABASE_NAME, 51 'user': TEST_DATABASE_USER, 52 'password': TEST_DATABASE_PASSWD, 53 'tblspace': TEST_DATABASE_TBLSPACE, 54 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 55 } 17 data_types = { 18 'AutoField': 'NUMBER(11)', 19 'BooleanField': 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))', 20 'CharField': 'NVARCHAR2(%(max_length)s)', 21 'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)', 22 'DateField': 'DATE', 23 'DateTimeField': 'TIMESTAMP', 24 'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)', 25 'FileField': 'NVARCHAR2(%(max_length)s)', 26 'FilePathField': 'NVARCHAR2(%(max_length)s)', 27 'FloatField': 'DOUBLE PRECISION', 28 'IntegerField': 'NUMBER(11)', 29 'IPAddressField': 'VARCHAR2(15)', 30 'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))', 31 'OneToOneField': 'NUMBER(11)', 32 'PhoneNumberField': 'VARCHAR2(20)', 33 'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)', 34 'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)', 35 'SlugField': 'NVARCHAR2(50)', 36 'SmallIntegerField': 'NUMBER(11)', 37 'TextField': 'NCLOB', 38 'TimeField': 'TIMESTAMP', 39 'URLField': 'VARCHAR2(%(max_length)s)', 40 'USStateField': 'CHAR(2)', 41 } 42 43 def create_test_db(settings, connection, verbosity=1, autoclobber=False): 44 TEST_DATABASE_NAME = self._test_database_name(settings) 45 TEST_DATABASE_USER = self._test_database_user(settings) 46 TEST_DATABASE_PASSWD = self._test_database_passwd(settings) 47 TEST_DATABASE_TBLSPACE = self._test_database_tblspace(settings) 48 TEST_DATABASE_TBLSPACE_TMP = self._test_database_tblspace_tmp(settings) 56 49 57 REMEMBER['user'] = settings.DATABASE_USER 58 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 50 parameters = { 51 'dbname': TEST_DATABASE_NAME, 52 'user': TEST_DATABASE_USER, 53 'password': TEST_DATABASE_PASSWD, 54 'tblspace': TEST_DATABASE_TBLSPACE, 55 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 56 } 59 57 60 cursor = connection.cursor() 61 if _test_database_create(settings): 62 if verbosity >= 1: 63 print 'Creating test database...' 64 try: 65 _create_test_db(cursor, parameters, verbosity) 66 except Exception, e: 67 sys.stderr.write("Got an error creating the test database: %s\n" % e) 68 if not autoclobber: 69 confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 70 if autoclobber or confirm == 'yes': 71 try: 72 if verbosity >= 1: 73 print "Destroying old test database..." 74 _destroy_test_db(cursor, parameters, verbosity) 75 if verbosity >= 1: 76 print "Creating test database..." 77 _create_test_db(cursor, parameters, verbosity) 78 except Exception, e: 79 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 80 sys.exit(2) 81 else: 82 print "Tests cancelled." 83 sys.exit(1) 58 self.remember['user'] = settings.DATABASE_USER 59 self.remember['passwd'] = settings.DATABASE_PASSWORD 84 60 85 if _test_user_create(settings): 86 if verbosity >= 1: 87 print "Creating test user..." 88 try: 89 _create_test_user(cursor, parameters, verbosity) 90 except Exception, e: 91 sys.stderr.write("Got an error creating the test user: %s\n" % e) 92 if not autoclobber: 93 confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 94 if autoclobber or confirm == 'yes': 95 try: 96 if verbosity >= 1: 97 print "Destroying old test user..." 98 _destroy_test_user(cursor, parameters, verbosity) 99 if verbosity >= 1: 100 print "Creating test user..." 101 _create_test_user(cursor, parameters, verbosity) 102 except Exception, e: 103 sys.stderr.write("Got an error recreating the test user: %s\n" % e) 104 sys.exit(2) 105 else: 106 print "Tests cancelled." 107 sys.exit(1) 61 cursor = connection.cursor() 62 if self._test_database_create(settings): 63 if verbosity >= 1: 64 print 'Creating test database...' 65 try: 66 self._create_test_db(cursor, parameters, verbosity) 67 except Exception, e: 68 sys.stderr.write("Got an error creating the test database: %s\n" % e) 69 if not autoclobber: 70 confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 71 if autoclobber or confirm == 'yes': 72 try: 73 if verbosity >= 1: 74 print "Destroying old test database..." 75 self._destroy_test_db(cursor, parameters, verbosity) 76 if verbosity >= 1: 77 print "Creating test database..." 78 self._create_test_db(cursor, parameters, verbosity) 79 except Exception, e: 80 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 81 sys.exit(2) 82 else: 83 print "Tests cancelled." 84 sys.exit(1) 108 85 109 connection.close() 110 settings.DATABASE_USER = TEST_DATABASE_USER 111 settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 86 if self._test_user_create(settings): 87 if verbosity >= 1: 88 print "Creating test user..." 89 try: 90 self._create_test_user(cursor, parameters, verbosity) 91 except Exception, e: 92 sys.stderr.write("Got an error creating the test user: %s\n" % e) 93 if not autoclobber: 94 confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 95 if autoclobber or confirm == 'yes': 96 try: 97 if verbosity >= 1: 98 print "Destroying old test user..." 99 self._destroy_test_user(cursor, parameters, verbosity) 100 if verbosity >= 1: 101 print "Creating test user..." 102 self._create_test_user(cursor, parameters, verbosity) 103 except Exception, e: 104 sys.stderr.write("Got an error recreating the test user: %s\n" % e) 105 sys.exit(2) 106 else: 107 print "Tests cancelled." 108 sys.exit(1) 112 109 113 management.call_command('syncdb', verbosity=verbosity, interactive=False) 110 connection.close() 111 settings.DATABASE_USER = TEST_DATABASE_USER 112 settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 114 113 115 # Get a cursor (even though we don't need one yet). This has 116 # the side effect of initializing the test database. 117 cursor = connection.cursor() 114 management.call_command('syncdb', verbosity=verbosity, interactive=False) 118 115 119 def destroy_test_db(settings, connection, old_database_name, verbosity=1): 120 connection.close() 116 # Get a cursor (even though we don't need one yet). This has 117 # the side effect of initializing the test database. 118 cursor = connection.cursor() 121 119 122 TEST_DATABASE_NAME = _test_database_name(settings) 123 TEST_DATABASE_USER = _test_database_user(settings) 124 TEST_DATABASE_PASSWD = _test_database_passwd(settings) 125 TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings) 126 TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings) 120 def destroy_test_db(settings, connection, old_database_name, verbosity=1): 121 connection.close() 127 122 128 settings.DATABASE_NAME = old_database_name 129 settings.DATABASE_USER = REMEMBER['user'] 130 settings.DATABASE_PASSWORD = REMEMBER['passwd'] 123 TEST_DATABASE_NAME = self._test_database_name(settings) 124 TEST_DATABASE_USER = self._test_database_user(settings) 125 TEST_DATABASE_PASSWD = self._test_database_passwd(settings) 126 TEST_DATABASE_TBLSPACE = self._test_database_tblspace(settings) 127 TEST_DATABASE_TBLSPACE_TMP = self._test_database_tblspace_tmp(settings) 131 128 132 parameters = { 133 'dbname': TEST_DATABASE_NAME, 134 'user': TEST_DATABASE_USER, 135 'password': TEST_DATABASE_PASSWD, 136 'tblspace': TEST_DATABASE_TBLSPACE, 137 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 138 } 129 settings.DATABASE_NAME = old_database_name 130 settings.DATABASE_USER = self.remember['user'] 131 settings.DATABASE_PASSWORD = self.remember['passwd'] 139 132 140 REMEMBER['user'] = settings.DATABASE_USER 141 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 133 parameters = { 134 'dbname': TEST_DATABASE_NAME, 135 'user': TEST_DATABASE_USER, 136 'password': TEST_DATABASE_PASSWD, 137 'tblspace': TEST_DATABASE_TBLSPACE, 138 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 139 } 142 140 143 cursor = connection.cursor() 144 time.sleep(1) # To avoid "database is being accessed by other users" errors. 145 if _test_user_create(settings): 146 if verbosity >= 1: 147 print 'Destroying test user...' 148 _destroy_test_user(cursor, parameters, verbosity) 149 if _test_database_create(settings): 150 if verbosity >= 1: 151 print 'Destroying test database...' 152 _destroy_test_db(cursor, parameters, verbosity) 153 connection.close() 141 self.remember['user'] = settings.DATABASE_USER 142 self.remember['passwd'] = settings.DATABASE_PASSWORD 154 143 155 def _create_test_db(cursor, parameters, verbosity): 156 if verbosity >= 2: 157 print "_create_test_db(): dbname = %s" % parameters['dbname'] 158 statements = [ 159 """CREATE TABLESPACE %(tblspace)s 160 DATAFILE '%(tblspace)s.dbf' SIZE 20M 161 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 162 """, 163 """CREATE TEMPORARY TABLESPACE %(tblspace_temp)s 164 TEMPFILE '%(tblspace_temp)s.dbf' SIZE 20M 165 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 166 """, 167 ] 168 _execute_statements(cursor, statements, parameters, verbosity) 144 cursor = connection.cursor() 145 time.sleep(1) # To avoid "database is being accessed by other users" errors. 146 if self._test_user_create(settings): 147 if verbosity >= 1: 148 print 'Destroying test user...' 149 self._destroy_test_user(cursor, parameters, verbosity) 150 if self._test_database_create(settings): 151 if verbosity >= 1: 152 print 'Destroying test database...' 153 self._destroy_test_db(cursor, parameters, verbosity) 154 connection.close() 169 155 170 def _create_test_user(cursor, parameters, verbosity): 171 if verbosity >= 2: 172 print "_create_test_user(): username = %s" % parameters['user'] 173 statements = [ 174 """CREATE USER %(user)s 175 IDENTIFIED BY %(password)s 176 DEFAULT TABLESPACE %(tblspace)s 177 TEMPORARY TABLESPACE %(tblspace_temp)s 178 """, 179 """GRANT CONNECT, RESOURCE TO %(user)s""", 180 ] 181 _execute_statements(cursor, statements, parameters, verbosity) 156 def _create_test_db(cursor, parameters, verbosity): 157 if verbosity >= 2: 158 print "_create_test_db(): dbname = %s" % parameters['dbname'] 159 statements = [ 160 """CREATE TABLESPACE %(tblspace)s 161 DATAFILE '%(tblspace)s.dbf' SIZE 20M 162 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 163 """, 164 """CREATE TEMPORARY TABLESPACE %(tblspace_temp)s 165 TEMPFILE '%(tblspace_temp)s.dbf' SIZE 20M 166 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 167 """, 168 ] 169 _execute_statements(cursor, statements, parameters, verbosity) 182 170 183 def _destroy_test_db(cursor, parameters, verbosity): 184 if verbosity >= 2: 185 print "_destroy_test_db(): dbname=%s" % parameters['dbname'] 186 statements = [ 187 'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 188 'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 171 def _create_test_user(cursor, parameters, verbosity): 172 if verbosity >= 2: 173 print "_create_test_user(): username = %s" % parameters['user'] 174 statements = [ 175 """CREATE USER %(user)s 176 IDENTIFIED BY %(password)s 177 DEFAULT TABLESPACE %(tblspace)s 178 TEMPORARY TABLESPACE %(tblspace_temp)s 179 """, 180 """GRANT CONNECT, RESOURCE TO %(user)s""", 189 181 ] 190 _execute_statements(cursor, statements, parameters, verbosity)182 _execute_statements(cursor, statements, parameters, verbosity) 191 183 192 def _destroy_test_user(cursor, parameters, verbosity):193 if verbosity >= 2:194 print "_destroy_test_user(): user=%s" % parameters['user']195 print "Be patient. This can take some time..."196 statements = [197 'DROP USER %(user)s CASCADE',198 ]199 _execute_statements(cursor, statements, parameters, verbosity)184 def _destroy_test_db(cursor, parameters, verbosity): 185 if verbosity >= 2: 186 print "_destroy_test_db(): dbname=%s" % parameters['dbname'] 187 statements = [ 188 'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 189 'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 190 ] 191 _execute_statements(cursor, statements, parameters, verbosity) 200 192 201 def _execute_statements(cursor, statements, parameters, verbosity): 202 for template in statements: 203 stmt = template % parameters 193 def _destroy_test_user(cursor, parameters, verbosity): 204 194 if verbosity >= 2: 205 print stmt 195 print "_destroy_test_user(): user=%s" % parameters['user'] 196 print "Be patient. This can take some time..." 197 statements = [ 198 'DROP USER %(user)s CASCADE', 199 ] 200 _execute_statements(cursor, statements, parameters, verbosity) 201 202 def _execute_statements(cursor, statements, parameters, verbosity): 203 for template in statements: 204 stmt = template % parameters 205 if verbosity >= 2: 206 print stmt 207 try: 208 cursor.execute(stmt) 209 except Exception, err: 210 sys.stderr.write("Failed (%s)\n" % (err)) 211 raise 212 213 def _test_database_name(settings): 214 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 206 215 try: 207 cursor.execute(stmt) 208 except Exception, err: 209 sys.stderr.write("Failed (%s)\n" % (err)) 216 if settings.TEST_DATABASE_NAME: 217 name = settings.TEST_DATABASE_NAME 218 except AttributeError: 219 pass 220 except: 210 221 raise 222 return name 211 223 212 def _test_database_name(settings): 213 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 214 try: 215 if settings.TEST_DATABASE_NAME: 216 name = settings.TEST_DATABASE_NAME 217 except AttributeError: 218 pass 219 except: 220 raise 221 return name 224 def _test_database_create(settings): 225 name = True 226 try: 227 if settings.TEST_DATABASE_CREATE: 228 name = True 229 else: 230 name = False 231 except AttributeError: 232 pass 233 except: 234 raise 235 return name 222 236 223 def _test_database_create(settings):224 name = True225 try:226 if settings.TEST_DATABASE_CREATE:227 name = True228 else:229 name = False230 except AttributeError:231 pass232 except:233 raise234 return name237 def _test_user_create(settings): 238 name = True 239 try: 240 if settings.TEST_USER_CREATE: 241 name = True 242 else: 243 name = False 244 except AttributeError: 245 pass 246 except: 247 raise 248 return name 235 249 236 def _test_user_create(settings): 237 name = True 238 try: 239 if settings.TEST_USER_CREATE: 240 name = True 241 else: 242 name = False 243 except AttributeError: 244 pass 245 except: 246 raise 247 return name 250 def _test_database_user(settings): 251 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 252 try: 253 if settings.TEST_DATABASE_USER: 254 name = settings.TEST_DATABASE_USER 255 except AttributeError: 256 pass 257 except: 258 raise 259 return name 248 260 249 def _test_database_user(settings):250 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME251 try:252 if settings.TEST_DATABASE_USER:253 name = settings.TEST_DATABASE_USER254 except AttributeError:255 pass256 except:257 raise258 return name261 def _test_database_passwd(settings): 262 name = PASSWORD 263 try: 264 if settings.TEST_DATABASE_PASSWD: 265 name = settings.TEST_DATABASE_PASSWD 266 except AttributeError: 267 pass 268 except: 269 raise 270 return name 259 271 260 def _test_database_passwd(settings):261 name = PASSWORD262 try:263 if settings.TEST_DATABASE_PASSWD:264 name = settings.TEST_DATABASE_PASSWD265 except AttributeError:266 pass267 except:268 raise269 return name272 def _test_database_tblspace(settings): 273 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 274 try: 275 if settings.TEST_DATABASE_TBLSPACE: 276 name = settings.TEST_DATABASE_TBLSPACE 277 except AttributeError: 278 pass 279 except: 280 raise 281 return name 270 282 271 def _test_database_tblspace(settings): 272 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 273 try: 274 if settings.TEST_DATABASE_TBLSPACE: 275 name = settings.TEST_DATABASE_TBLSPACE 276 except AttributeError: 277 pass 278 except: 279 raise 280 return name 281 282 def _test_database_tblspace_tmp(settings): 283 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME + '_temp' 284 try: 285 if settings.TEST_DATABASE_TBLSPACE_TMP: 286 name = settings.TEST_DATABASE_TBLSPACE_TMP 287 except AttributeError: 288 pass 289 except: 290 raise 291 return name 283 def _test_database_tblspace_tmp(settings): 284 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME + '_temp' 285 try: 286 if settings.TEST_DATABASE_TBLSPACE_TMP: 287 name = settings.TEST_DATABASE_TBLSPACE_TMP 288 except AttributeError: 289 pass 290 except: 291 raise 292 return name -
django/db/backends/__init__.py
325 325 """ 326 326 return self.year_lookup_bounds(value) 327 327 328 class BaseDatabaseCreation(object): 329 """ 330 This class encapsulates all backend-specific differences that pertain to 331 database *creation*, such as the column types to use for particular Django 332 Fields. 333 """ 334 data_types = {} 335 336 class BaseDatabaseIntrospection(object): 337 """ 338 This class encapsulates all backend-specific introspection utilities 339 """ 340 data_types_reverse = {} 341 342 class BaseDatabaseClient(object): 343 """ 344 This class encapsualtes all backend-specific methods for opening a 345 client shell 346 """ 347 def runshell(): 348 raise NotImplementedError() 349 350 No newline at end of file -
django/db/backends/postgresql_psycopg2/base.py
6 6 7 7 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures 8 8 from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations 9 from django.db.backends.postgresql.client import DatabaseClient 10 from django.db.backends.postgresql.creation import DatabaseCreation 11 from django.db.backends.postgresql_psycopg2.introspection import DatabaseIntrospection 12 9 13 from django.utils.safestring import SafeUnicode 10 14 try: 11 15 import psycopg2 as Database … … 33 37 class DatabaseWrapper(BaseDatabaseWrapper): 34 38 features = DatabaseFeatures() 35 39 ops = DatabaseOperations() 40 client = DatabaseClient() 41 creation = DatabaseCreation() 42 introspection = DatabaseIntrospection(ops) 43 36 44 operators = { 37 45 'exact': '= %s', 38 46 'iexact': 'ILIKE %s', -
django/db/backends/postgresql_psycopg2/client.py
1 from django.db.backends.postgresql.client import * -
django/db/backends/postgresql_psycopg2/introspection.py
1 from django.db.backends.postgresql _psycopg2.base import DatabaseOperations1 from django.db.backends.postgresql.introspection import DatabaseIntrospection as PostgresDatabaseIntrospection 2 2 3 quote_name = DatabaseOperations().quote_name 3 class DatabaseIntrospection(PostgresDatabaseIntrospection): 4 4 5 def get_table_list(cursor): 6 "Returns a list of table names in the current database." 7 cursor.execute(""" 8 SELECT c.relname 9 FROM pg_catalog.pg_class c 10 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 11 WHERE c.relkind IN ('r', 'v', '') 12 AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 13 AND pg_catalog.pg_table_is_visible(c.oid)""") 14 return [row[0] for row in cursor.fetchall()] 15 16 def get_table_description(cursor, table_name): 17 "Returns a description of the table, with the DB-API cursor.description interface." 18 cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name)) 19 return cursor.description 20 21 def get_relations(cursor, table_name): 22 """ 23 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 24 representing all relationships to the given table. Indexes are 0-based. 25 """ 26 cursor.execute(""" 27 SELECT con.conkey, con.confkey, c2.relname 28 FROM pg_constraint con, pg_class c1, pg_class c2 29 WHERE c1.oid = con.conrelid 30 AND c2.oid = con.confrelid 31 AND c1.relname = %s 32 AND con.contype = 'f'""", [table_name]) 33 relations = {} 34 for row in cursor.fetchall(): 35 # row[0] and row[1] are single-item lists, so grab the single item. 36 relations[row[0][0] - 1] = (row[1][0] - 1, row[2]) 37 return relations 38 39 def get_indexes(cursor, table_name): 40 """ 41 Returns a dictionary of fieldname -> infodict for the given table, 42 where each infodict is in the format: 43 {'primary_key': boolean representing whether it's the primary key, 44 'unique': boolean representing whether it's a unique index} 45 """ 46 # This query retrieves each index on the given table, including the 47 # first associated field name 48 cursor.execute(""" 49 SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary 50 FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, 51 pg_catalog.pg_index idx, pg_catalog.pg_attribute attr 52 WHERE c.oid = idx.indrelid 53 AND idx.indexrelid = c2.oid 54 AND attr.attrelid = c.oid 55 AND attr.attnum = idx.indkey[0] 56 AND c.relname = %s""", [table_name]) 57 indexes = {} 58 for row in cursor.fetchall(): 59 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 60 # a string of space-separated integers. This designates the field 61 # indexes (1-based) of the fields that have indexes on the table. 62 # Here, we skip any indexes across multiple fields. 63 if ' ' in row[1]: 64 continue 65 indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]} 66 return indexes 67 68 # Maps type codes to Django Field types. 69 DATA_TYPES_REVERSE = { 70 16: 'BooleanField', 71 21: 'SmallIntegerField', 72 23: 'IntegerField', 73 25: 'TextField', 74 701: 'FloatField', 75 869: 'IPAddressField', 76 1043: 'CharField', 77 1082: 'DateField', 78 1083: 'TimeField', 79 1114: 'DateTimeField', 80 1184: 'DateTimeField', 81 1266: 'TimeField', 82 1700: 'DecimalField', 83 } 5 def get_relations(self, cursor, table_name): 6 """ 7 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 8 representing all relationships to the given table. Indexes are 0-based. 9 """ 10 cursor.execute(""" 11 SELECT con.conkey, con.confkey, c2.relname 12 FROM pg_constraint con, pg_class c1, pg_class c2 13 WHERE c1.oid = con.conrelid 14 AND c2.oid = con.confrelid 15 AND c1.relname = %s 16 AND con.contype = 'f'""", [table_name]) 17 relations = {} 18 for row in cursor.fetchall(): 19 # row[0] and row[1] are single-item lists, so grab the single item. 20 relations[row[0][0] - 1] = (row[1][0] - 1, row[2]) 21 return relations -
django/db/backends/postgresql_psycopg2/creation.py
1 from django.db.backends.postgresql.creation import * -
django/db/backends/dummy/base.py
9 9 10 10 from django.core.exceptions import ImproperlyConfigured 11 11 from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations 12 from django.db.backends import BaseDatabaseClient, BaseDatabaseCreation, BaseDatabaseIntrospection 12 13 13 14 def complain(*args, **kwargs): 14 15 raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet." … … 25 26 class DatabaseOperations(BaseDatabaseOperations): 26 27 quote_name = complain 27 28 29 class DatabaseClient(BaseDatabaseClient): 30 runshell = complain 31 32 class DatabaseCreation(BaseDatabaseCreation): 33 pass 34 35 class DatabaseIntrospection(BaseDatabaseIntrospection): 36 get_table_list = complain 37 get_table_description = complain 38 get_relations = complain 39 get_indexes = complain 40 28 41 class DatabaseWrapper(object): 29 42 features = BaseDatabaseFeatures() 30 43 ops = DatabaseOperations() 44 client = DatabaseClient() 45 creation = DatabaseCreation() 46 introspection = DatabaseIntrospection() 47 31 48 operators = {} 32 49 cursor = complain 33 50 _commit = complain -
django/db/backends/dummy/client.py
1 from django.db.backends.dummy.base import complain2 3 runshell = complain -
django/db/backends/dummy/introspection.py
1 from django.db.backends.dummy.base import complain2 3 get_table_list = complain4 get_table_description = complain5 get_relations = complain6 get_indexes = complain7 8 DATA_TYPES_REVERSE = {} -
django/db/backends/dummy/creation.py
1 DATA_TYPES = {} -
django/db/backends/creation.py
1 class BaseCreation(object):2 """3 This class encapsulates all backend-specific differences that pertain to4 database *creation*, such as the column types to use for particular Django5 Fields.6 """7 pass -
django/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.') -
django/core/management/commands/dbshell.py
6 6 requires_model_validation = False 7 7 8 8 def handle_noargs(self, **options): 9 from django.db import runshell10 runshell()9 from django.db import connection 10 connection.client.runshell() -
django/core/management/sql.py
9 9 10 10 def table_names(): 11 11 "Returns a list of all table names that exist in the database." 12 from django.db import connection , get_introspection_module12 from django.db import connection 13 13 cursor = connection.cursor() 14 return set( get_introspection_module().get_table_list(cursor))14 return set(connection.introspection.get_table_list(cursor)) 15 15 16 16 def django_table_names(only_existing=False): 17 17 """